github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/cleaner/cleaner_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cleaner_test 5 6 import ( 7 "errors" 8 "time" 9 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 "launchpad.net/tomb" 13 14 coretesting "github.com/juju/juju/testing" 15 "github.com/juju/juju/watcher" 16 "github.com/juju/juju/worker" 17 "github.com/juju/juju/worker/cleaner" 18 ) 19 20 type CleanerSuite struct { 21 coretesting.BaseSuite 22 mockState *cleanerMock 23 } 24 25 var _ = gc.Suite(&CleanerSuite{}) 26 27 func (s *CleanerSuite) SetUpTest(c *gc.C) { 28 s.BaseSuite.SetUpTest(c) 29 s.mockState = &cleanerMock{ 30 calls: make(chan string), 31 } 32 s.mockState.watcher = s.newMockNotifyWatcher(nil) 33 } 34 35 func (s *CleanerSuite) AssertReceived(c *gc.C, expect string) { 36 select { 37 case call := <-s.mockState.calls: 38 c.Assert(call, gc.Matches, expect) 39 case <-time.After(coretesting.LongWait): 40 c.Fatalf("Timed out waiting for %s", expect) 41 } 42 } 43 44 func (s *CleanerSuite) AssertEmpty(c *gc.C) { 45 select { 46 case call, ok := <-s.mockState.calls: 47 c.Fatalf("Unexpected %s (ok: %v)", call, ok) 48 case <-time.After(coretesting.ShortWait): 49 } 50 } 51 52 func (s *CleanerSuite) TestCleaner(c *gc.C) { 53 cln, err := cleaner.NewCleaner(s.mockState) 54 c.Assert(err, jc.ErrorIsNil) 55 defer func() { c.Assert(worker.Stop(cln), jc.ErrorIsNil) }() 56 57 s.AssertReceived(c, "WatchCleanups") 58 s.AssertReceived(c, "Cleanup") 59 60 s.mockState.watcher.Change() 61 s.AssertReceived(c, "Cleanup") 62 } 63 64 func (s *CleanerSuite) TestWatchCleanupsError(c *gc.C) { 65 s.mockState.err = []error{errors.New("hello")} 66 cln, err := cleaner.NewCleaner(s.mockState) 67 c.Assert(err, jc.ErrorIsNil) 68 69 s.AssertReceived(c, "WatchCleanups") 70 s.AssertEmpty(c) 71 err = worker.Stop(cln) 72 c.Assert(err, gc.ErrorMatches, "hello") 73 } 74 75 func (s *CleanerSuite) TestCleanupError(c *gc.C) { 76 s.mockState.err = []error{nil, errors.New("hello")} 77 cln, err := cleaner.NewCleaner(s.mockState) 78 c.Assert(err, jc.ErrorIsNil) 79 80 s.AssertReceived(c, "WatchCleanups") 81 s.AssertReceived(c, "Cleanup") 82 err = worker.Stop(cln) 83 c.Assert(err, jc.ErrorIsNil) 84 log := c.GetTestLog() 85 c.Assert(log, jc.Contains, "ERROR juju.worker.cleaner cannot cleanup state: hello") 86 } 87 88 func (s *CleanerSuite) newMockNotifyWatcher(err error) *mockNotifyWatcher { 89 m := &mockNotifyWatcher{ 90 changes: make(chan struct{}, 1), 91 err: err, 92 } 93 go func() { 94 defer m.tomb.Done() 95 defer m.tomb.Kill(m.err) 96 <-m.tomb.Dying() 97 }() 98 s.AddCleanup(func(c *gc.C) { 99 err := worker.Stop(m) 100 c.Check(err, jc.ErrorIsNil) 101 }) 102 m.Change() 103 return m 104 } 105 106 type mockNotifyWatcher struct { 107 watcher.NotifyWatcher 108 109 tomb tomb.Tomb 110 err error 111 changes chan struct{} 112 } 113 114 func (m *mockNotifyWatcher) Kill() { 115 m.tomb.Kill(nil) 116 } 117 118 func (m *mockNotifyWatcher) Wait() error { 119 return m.tomb.Wait() 120 } 121 122 func (m *mockNotifyWatcher) Changes() watcher.NotifyChannel { 123 return m.changes 124 } 125 126 func (m *mockNotifyWatcher) Change() { 127 m.changes <- struct{}{} 128 } 129 130 // cleanerMock is used to check the 131 // calls of Cleanup() and WatchCleanups() 132 type cleanerMock struct { 133 cleaner.StateCleaner 134 watcher *mockNotifyWatcher 135 calls chan string 136 err []error 137 } 138 139 func (m *cleanerMock) getError() (e error) { 140 if len(m.err) > 0 { 141 e = m.err[0] 142 m.err = m.err[1:] 143 } 144 return 145 } 146 147 func (m *cleanerMock) Cleanup() error { 148 m.calls <- "Cleanup" 149 return m.getError() 150 } 151 152 func (m *cleanerMock) WatchCleanups() (watcher.NotifyWatcher, error) { 153 m.calls <- "WatchCleanups" 154 return m.watcher, m.getError() 155 }