Skip to content

Commit 26162d7

Browse files
authored
Merge pull request #44 from hpidcock/enhance-workertest
feat!: enhance workertest to wait indefinitely on fatal checks
2 parents 9759c00 + e6d8bba commit 26162d7

4 files changed

Lines changed: 187 additions & 43 deletions

File tree

go.mod

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module github.com/juju/worker/v4
22

3-
go 1.21
3+
go 1.24.2
44

5-
toolchain go1.21.5
5+
toolchain go1.24.3
66

77
require (
88
github.com/juju/clock v1.0.3
@@ -16,11 +16,14 @@ require (
1616

1717
require (
1818
github.com/juju/loggo/v2 v2.1.0 // indirect
19+
github.com/juju/tc v0.0.0-20250523041547-7f66c35f9f03 // indirect
1920
github.com/juju/utils/v3 v3.1.1 // indirect
2021
github.com/kr/pretty v0.3.1 // indirect
2122
github.com/kr/text v0.2.0 // indirect
22-
github.com/rogpeppe/go-internal v1.12.0 // indirect
23-
golang.org/x/crypto v0.23.0 // indirect
24-
golang.org/x/net v0.25.0 // indirect
23+
github.com/rogpeppe/go-internal v1.14.1 // indirect
24+
golang.org/x/crypto v0.28.0 // indirect
25+
golang.org/x/net v0.30.0 // indirect
2526
gopkg.in/yaml.v2 v2.4.0 // indirect
2627
)
28+
29+
replace gopkg.in/check.v1 => github.com/hpidcock/gc-compat-tc v0.0.0-20250523041742-c3a83c867edf

go.sum

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3+
github.com/hpidcock/gc-compat-tc v0.0.0-20250523041742-c3a83c867edf h1:sFwkVpTbk799e1EPlDfWLULd5/+w5EuMv2z5koBa908=
4+
github.com/hpidcock/gc-compat-tc v0.0.0-20250523041742-c3a83c867edf/go.mod h1:lyEaDukSWSGyb/L0YGDaS1hU2p40qb5s/Ck6qm4CneU=
25
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
36
github.com/juju/clock v1.0.3 h1:yJHIsWXeU8j3QcBdiess09SzfiXRRrsjKPn2whnMeds=
47
github.com/juju/clock v1.0.3/go.mod h1:HIBvJ8kiV/n7UHwKuCkdYL4l/MDECztHR2sAvWDxxf0=
@@ -10,32 +13,92 @@ github.com/juju/loggo v1.0.0 h1:Y6ZMQOGR9Aj3BGkiWx7HBbIx6zNwNkxhVNOHU2i1bl0=
1013
github.com/juju/loggo v1.0.0/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg=
1114
github.com/juju/loggo/v2 v2.1.0 h1:cKBvJZhAJ6pvvBgnH8Fzy58E2Bm4N8f8cCqi/HulHbI=
1215
github.com/juju/loggo/v2 v2.1.0/go.mod h1:647d6WvXBLj5lvka2qBvccr7vMIvF2KFkEH+0ZuFOUM=
16+
github.com/juju/tc v0.0.0-20250523041547-7f66c35f9f03 h1:x/rsZcDhRKEubIDOnSXRUMTs5I6/lGyT7Sd7xAmkazo=
17+
github.com/juju/tc v0.0.0-20250523041547-7f66c35f9f03/go.mod h1:YdExdo5XpLqX+BT6eCcS8HCqbZO09fP3mwoiJXv35Vg=
1318
github.com/juju/testing v1.2.0 h1:Q0wxjaxx4XPVEN+SgzxKr3d82pjmSBcuM3WndAU391c=
1419
github.com/juju/testing v1.2.0/go.mod h1:lqZVzNwBKAbylGZidK77ts6kIdoOkmD52+4m0ysetPo=
1520
github.com/juju/utils/v3 v3.1.1 h1:shEMr/4Wkw0YCOPz5IFOYkLv1ec50pzRi59TRl0qQ/0=
1621
github.com/juju/utils/v3 v3.1.1/go.mod h1:nAj3sHtdYfAkvnkqttTy3Xzm2HzkD9Hfgnc+upOW2Z8=
17-
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
1822
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
1923
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
20-
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
21-
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
2224
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2325
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
2426
github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
2527
github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
2628
github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
2729
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
2830
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
29-
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
30-
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
31-
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
31+
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
32+
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
33+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
34+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
35+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
36+
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
37+
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
3238
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
33-
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
39+
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
40+
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
41+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
42+
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
43+
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
44+
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
45+
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
46+
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
47+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
48+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
49+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
50+
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
51+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
52+
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
53+
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
3454
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
35-
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
36-
gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
37-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
38-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
55+
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
56+
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
57+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
58+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
59+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
60+
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
61+
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
62+
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
63+
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
64+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
65+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
66+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
67+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
68+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
69+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
70+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
71+
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
72+
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
73+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
74+
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
75+
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
76+
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
77+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
78+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
79+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
80+
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
81+
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
82+
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
83+
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
84+
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
85+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
86+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
87+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
88+
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
89+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
90+
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
91+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
92+
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
93+
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
94+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
95+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
96+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
97+
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
98+
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
99+
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
100+
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
101+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
39102
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 h1:yiW+nvdHb9LVqSHQBXfZCieqV4fzYhNBql77zY0ykqs=
40103
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk=
41104
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

workertest/check.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package workertest
55

66
import (
7+
"context"
78
"time"
89

910
"github.com/juju/errors"
@@ -29,6 +30,8 @@ type C interface {
2930
Errorf(format string, args ...any)
3031
Check(obtained any, checker gc.Checker, args ...any) bool
3132
Logf(format string, args ...any)
33+
Context() context.Context
34+
Helper()
3235
}
3336

3437
// CheckAlive Wait()s a short time for the supplied worker to return an error,
@@ -39,6 +42,7 @@ type C interface {
3942
//
4043
// It doesn't Assert and is therefore suitable for use from any goroutine.
4144
func CheckAlive(c C, w worker.Worker) {
45+
c.Helper()
4246
wait := make(chan error, 1)
4347
go func() {
4448
wait <- w.Wait()
@@ -54,23 +58,30 @@ func CheckAlive(c C, w worker.Worker) {
5458
// further analysis, or fails the test after a timeout expires. It doesn't
5559
// Assert and is therefore suitable for use from any goroutine.
5660
func CheckKilled(c C, w worker.Worker) error {
61+
c.Helper()
5762
wait := make(chan error, 1)
5863
go func() {
5964
wait <- w.Wait()
6065
}()
61-
select {
62-
case err := <-wait:
63-
return err
64-
case <-time.After(killTimeout):
65-
c.Errorf("timed out waiting for worker to stop")
66-
return errors.New("workertest: worker not stopping")
66+
logTimeout := time.After(killTimeout)
67+
for {
68+
select {
69+
case err := <-wait:
70+
return err
71+
case <-logTimeout:
72+
c.Logf("still waiting for worker to be killed")
73+
case <-c.Context().Done():
74+
c.Errorf("timed out waiting for worker to stop")
75+
return errors.New("workertest: worker not stopping")
76+
}
6777
}
6878
}
6979

7080
// CheckKill Kill()s the supplied worker and Wait()s for its error, which it
7181
// returns for further analysis, or fails the test after a timeout expires.
7282
// It doesn't Assert and is therefore suitable for use from any goroutine.
7383
func CheckKill(c C, w worker.Worker) error {
84+
c.Helper()
7485
w.Kill()
7586
return CheckKilled(c, w)
7687
}
@@ -86,6 +97,7 @@ func CheckKill(c C, w worker.Worker) error {
8697
// to run successfully; and it doesn't Assert, and is therefore suitable for use
8798
// from any goroutine.
8899
func CleanKill(c C, w worker.Worker) {
100+
c.Helper()
89101
err := CheckKill(c, w)
90102
c.Check(err, jc.ErrorIsNil)
91103
}
@@ -101,6 +113,7 @@ func CleanKill(c C, w worker.Worker) {
101113
// testing that failure; and it doesn't Assert, and is therefore suitable for
102114
// use from any goroutine.
103115
func DirtyKill(c C, w worker.Worker) {
116+
c.Helper()
104117
err := CheckKill(c, w)
105118
if err != nil {
106119
c.Logf("ignoring error: %v", err)
@@ -119,6 +132,7 @@ func DirtyKill(c C, w worker.Worker) {
119132
// unexpectedly, and make every effort to prevent a rogue worker living
120133
// beyond its test.
121134
func CheckNilOrKill(c C, w worker.Worker) {
135+
c.Helper()
122136
if !c.Check(w, gc.IsNil) {
123137
c.Logf("stopping rogue worker...")
124138
CleanKill(c, w)

workertest/workertest_test.go

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
package workertest_test
55

66
import (
7+
"context"
8+
"fmt"
9+
"sync/atomic"
710
"time"
811

912
"github.com/juju/errors"
@@ -24,15 +27,6 @@ func (s *Suite) SetUpTest(c *gc.C) {
2427
s.PatchValue(workertest.KillTimeout, time.Second)
2528
}
2629

27-
func (s *Suite) CheckFailed(c *gc.C) {
28-
if c.Failed() {
29-
c.Succeed()
30-
} else {
31-
c.Errorf("expected failure; none observed")
32-
}
33-
c.Logf("-------------------------------")
34-
}
35-
3630
func (s *Suite) TestCheckAliveSuccess(c *gc.C) {
3731
w := workertest.NewErrorWorker(nil)
3832
defer workertest.CleanKill(c, w)
@@ -43,8 +37,9 @@ func (s *Suite) TestCheckAliveSuccess(c *gc.C) {
4337
func (s *Suite) TestCheckAliveFailure(c *gc.C) {
4438
w := workertest.NewDeadWorker(nil)
4539

46-
workertest.CheckAlive(c, w)
47-
s.CheckFailed(c)
40+
x := &noFail{C: c}
41+
workertest.CheckAlive(x, w)
42+
c.Assert(x.failed.Load(), gc.Equals, true)
4843
}
4944

5045
func (s *Suite) TestCheckKilledSuccess(c *gc.C) {
@@ -61,8 +56,11 @@ func (s *Suite) TestCheckKilledTimeout(c *gc.C) {
6156
w := workertest.NewErrorWorker(nil)
6257
defer workertest.CleanKill(c, w)
6358

64-
err := workertest.CheckKilled(c, w)
65-
s.CheckFailed(c)
59+
ctx, cancel := context.WithTimeout(c.Context(), 10*time.Second)
60+
defer cancel()
61+
x := &noFail{C: c, ctx: ctx}
62+
err := workertest.CheckKilled(x, w)
63+
c.Assert(x.failed.Load(), gc.Equals, true)
6664
c.Check(err, gc.ErrorMatches, "workertest: worker not stopping")
6765
}
6866

@@ -79,8 +77,11 @@ func (s *Suite) TestCheckKillTimeout(c *gc.C) {
7977
w := workertest.NewForeverWorker(nil)
8078
defer w.ReallyKill()
8179

82-
err := workertest.CheckKill(c, w)
83-
s.CheckFailed(c)
80+
ctx, cancel := context.WithTimeout(c.Context(), 10*time.Second)
81+
defer cancel()
82+
x := &noFail{C: c, ctx: ctx}
83+
err := workertest.CheckKill(x, w)
84+
c.Assert(x.failed.Load(), gc.Equals, true)
8485
c.Check(err, gc.ErrorMatches, "workertest: worker not stopping")
8586
}
8687

@@ -93,16 +94,20 @@ func (s *Suite) TestCleanKillSuccess(c *gc.C) {
9394
func (s *Suite) TestCleanKillFailure(c *gc.C) {
9495
w := workertest.NewErrorWorker(errors.New("kebdrix"))
9596

96-
workertest.CleanKill(c, w)
97-
s.CheckFailed(c)
97+
x := &noFail{C: c}
98+
workertest.CleanKill(x, w)
99+
c.Assert(x.failed.Load(), gc.Equals, true)
98100
}
99101

100102
func (s *Suite) TestCleanKillTimeout(c *gc.C) {
101103
w := workertest.NewForeverWorker(nil)
102104
defer w.ReallyKill()
103105

104-
workertest.CleanKill(c, w)
105-
s.CheckFailed(c)
106+
ctx, cancel := context.WithTimeout(c.Context(), 10*time.Second)
107+
defer cancel()
108+
x := &noFail{C: c, ctx: ctx}
109+
workertest.CleanKill(x, w)
110+
c.Assert(x.failed.Load(), gc.Equals, true)
106111
}
107112

108113
func (s *Suite) TestDirtyKillSuccess(c *gc.C) {
@@ -115,6 +120,65 @@ func (s *Suite) TestDirtyKillTimeout(c *gc.C) {
115120
w := workertest.NewForeverWorker(nil)
116121
defer w.ReallyKill()
117122

118-
workertest.DirtyKill(c, w)
119-
s.CheckFailed(c)
123+
ctx, cancel := context.WithTimeout(c.Context(), 10*time.Second)
124+
defer cancel()
125+
x := &noFail{C: c, ctx: ctx}
126+
workertest.DirtyKill(x, w)
127+
c.Assert(x.failed.Load(), gc.Equals, true)
128+
}
129+
130+
// noFail is a helper to check failed checkers
131+
type noFail struct {
132+
*gc.C
133+
failed atomic.Bool
134+
ctx context.Context
135+
}
136+
137+
func (c *noFail) Context() context.Context {
138+
if c.ctx == nil {
139+
return c.C.Context()
140+
}
141+
return c.ctx
142+
}
143+
144+
func (c *noFail) Error(args ...any) {
145+
c.Logf("%s", fmt.Sprintln(args...))
146+
c.failed.Store(true)
147+
}
148+
149+
func (c *noFail) Errorf(format string, args ...any) {
150+
c.Logf(format, args...)
151+
c.failed.Store(true)
152+
}
153+
154+
func (c *noFail) Fatal(args ...any) {
155+
c.Logf("%s", fmt.Sprintln(args...))
156+
c.failed.Store(true)
157+
panic("failed")
158+
}
159+
160+
func (c *noFail) Fatalf(format string, args ...any) {
161+
c.Logf(format, args...)
162+
c.failed.Store(true)
163+
panic("failed")
164+
}
165+
166+
func (c *noFail) Check(obtained any, checker gc.Checker, args ...any) bool {
167+
ok, errString := checker.Check(append([]any{obtained}, args...), checker.Info().Params)
168+
if ok {
169+
return true
170+
}
171+
c.Logf("%s", errString)
172+
c.failed.Store(true)
173+
return false
174+
}
175+
176+
func (c *noFail) Assert(obtained any, checker gc.Checker, args ...any) {
177+
ok, errString := checker.Check(append([]any{obtained}, args...), checker.Info().Params)
178+
if ok {
179+
return
180+
}
181+
c.Logf("%s", errString)
182+
c.failed.Store(true)
183+
panic("failed")
120184
}

0 commit comments

Comments
 (0)