github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/workertest/check.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package workertest 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 coretesting "github.com/juju/juju/testing" 14 "github.com/juju/juju/worker" 15 ) 16 17 var ( 18 // AliveDelay is the minimum time an Alive helper will Wait for its worker 19 // to stop before returning successfully. 20 aliveDelay = coretesting.ShortWait 21 22 // KillTimeout is the maximum time a Kill helper will Wait for its worker 23 // before failing the test. 24 killTimeout = coretesting.LongWait 25 ) 26 27 // CheckAlive Wait()s a short time for the supplied worker to return an error, 28 // and fails the test if it does. If it doesn't fail, it'll leave a goroutine 29 // running in the background, blocked on the worker's death; but that doesn't 30 // matter, because of *course* you correctly deferred a suitable Kill helper 31 // as soon as you created the worker in the first place. Right? Right. 32 // 33 // It doesn't Assert and is therefore suitable for use from any goroutine. 34 func CheckAlive(c *gc.C, w worker.Worker) { 35 wait := make(chan error, 1) 36 go func() { 37 wait <- w.Wait() 38 }() 39 select { 40 case <-time.After(aliveDelay): 41 case err := <-wait: 42 c.Errorf("expected alive worker; failed with %v", err) 43 } 44 } 45 46 // CheckKilled Wait()s for the supplied worker's error, which it returns for 47 // further analysis, or fails the test after a timeout expires. It doesn't 48 // Assert and is therefore suitable for use from any goroutine. 49 func CheckKilled(c *gc.C, w worker.Worker) error { 50 wait := make(chan error, 1) 51 go func() { 52 wait <- w.Wait() 53 }() 54 select { 55 case err := <-wait: 56 return err 57 case <-time.After(killTimeout): 58 c.Errorf("timed out waiting for worker to stop") 59 return errors.New("workertest: worker not stopping") 60 } 61 } 62 63 // CheckKill Kill()s the supplied worker and Wait()s for its error, which it 64 // returns for further analysis, or fails the test after a timeout expires. 65 // It doesn't Assert and is therefore suitable for use from any goroutine. 66 func CheckKill(c *gc.C, w worker.Worker) error { 67 w.Kill() 68 return CheckKilled(c, w) 69 } 70 71 // CleanKill calls CheckKill with the supplied arguments, and Checks that the 72 // returned error is nil. It's particularly suitable for deferring: 73 // 74 // someWorker, err := some.NewWorker() 75 // c.Assert(err, jc.ErrorIsNil) 76 // defer workertest.CleanKill(c, someWorker) 77 // 78 // ...in the large number (majority?) of situations where a worker is expected 79 // to run successfully; and it doesn't Assert, and is therefore suitable for use 80 // from any goroutine. 81 func CleanKill(c *gc.C, w worker.Worker) { 82 err := CheckKill(c, w) 83 c.Check(err, jc.ErrorIsNil) 84 } 85 86 // DirtyKill calls CheckKill with the supplied arguments, and logs the returned 87 // error. It's particularly suitable for deferring: 88 // 89 // someWorker, err := some.NewWorker() 90 // c.Assert(err, jc.ErrorIsNil) 91 // defer workertest.DirtyKill(c, someWorker) 92 // 93 // ...in the cases where we expect a worker to fail, but aren't specifically 94 // testing that failure; and it doesn't Assert, and is therefore suitable for 95 // use from any goroutine. 96 func DirtyKill(c *gc.C, w worker.Worker) { 97 err := CheckKill(c, w) 98 c.Logf("ignoring error: %v", err) 99 } 100 101 // CheckNilOrKill has no effect if w is nil; otherwise, it fails the test 102 // and tries to stop the (non-nil) worker via CleanKill(). It's suitable 103 // for testing constructor failure: 104 // 105 // someWorker, err := some.NewWorker(badConfig) 106 // workertest.CheckNilOrKill(c, someWorker) 107 // c.Check(err, ... 108 // 109 // ...because it will do the right thing if your constructor succeeds 110 // unexpectedly, and make every effort to prevent a rogue worker living 111 // beyond its test. 112 func CheckNilOrKill(c *gc.C, w worker.Worker) { 113 if !c.Check(w, gc.IsNil) { 114 c.Logf("stopping rogue worker...") 115 CleanKill(c, w) 116 } 117 }