github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/undertaker/mock_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package undertaker_test 5 6 import ( 7 "context" 8 "time" 9 10 "github.com/juju/clock/testclock" 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 "github.com/juju/worker/v3" 14 "github.com/juju/worker/v3/workertest" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/core/status" 18 "github.com/juju/juju/core/watcher" 19 "github.com/juju/juju/environs" 20 "github.com/juju/juju/environs/cloudspec" 21 "github.com/juju/juju/environs/config" 22 environscontext "github.com/juju/juju/environs/context" 23 "github.com/juju/juju/rpc/params" 24 "github.com/juju/juju/worker/undertaker" 25 ) 26 27 type mockFacade struct { 28 stub *testing.Stub 29 info params.UndertakerModelInfoResult 30 clock testclock.AdvanceableClock 31 advance time.Duration 32 modelChanges chan struct{} 33 } 34 35 func (mock *mockFacade) ModelInfo() (params.UndertakerModelInfoResult, error) { 36 mock.stub.AddCall("ModelInfo") 37 if err := mock.stub.NextErr(); err != nil { 38 return params.UndertakerModelInfoResult{}, err 39 } 40 return mock.info, nil 41 } 42 43 func (mock *mockFacade) WatchModelResources() (watcher.NotifyWatcher, error) { 44 mock.stub.AddCall("WatchModelResources") 45 if mock.advance > 0 { 46 mock.clock.Advance(mock.advance) 47 } 48 if err := mock.stub.NextErr(); err != nil { 49 return nil, err 50 } 51 const count = 5 52 changes := make(chan struct{}, count) 53 for i := 0; i < count; i++ { 54 changes <- struct{}{} 55 } 56 return &mockWatcher{ 57 Worker: workertest.NewErrorWorker(nil), 58 changes: changes, 59 }, nil 60 } 61 62 func (mock *mockFacade) ProcessDyingModel() error { 63 mock.stub.AddCall("ProcessDyingModel") 64 time.Sleep(100 * time.Millisecond) 65 return mock.stub.NextErr() 66 } 67 68 func (mock *mockFacade) SetStatus(status status.Status, info string, data map[string]interface{}) error { 69 mock.stub.MethodCall(mock, "SetStatus", status, info, data) 70 return mock.stub.NextErr() 71 } 72 73 func (mock *mockFacade) RemoveModel() error { 74 mock.stub.AddCall("RemoveModel") 75 time.Sleep(100 * time.Millisecond) 76 return mock.stub.NextErr() 77 } 78 79 func (mock *mockFacade) ModelConfig() (*config.Config, error) { 80 mock.stub.AddCall("ModelConfig") 81 cfg, _ := config.New(config.NoDefaults, map[string]interface{}{ 82 "uuid": "00000000-0000-0000-0000-000000000000", 83 "name": "name", 84 }) 85 return cfg, mock.stub.NextErr() 86 } 87 88 func (mock *mockFacade) CloudSpec() (cloudspec.CloudSpec, error) { 89 mock.stub.AddCall("CloudSpec") 90 return cloudspec.CloudSpec{}, mock.stub.NextErr() 91 } 92 93 func (mock *mockFacade) WatchModel() (watcher.NotifyWatcher, error) { 94 mock.stub.AddCall("WatchModel") 95 if err := mock.stub.NextErr(); err != nil { 96 return nil, err 97 } 98 return &mockWatcher{ 99 Worker: workertest.NewErrorWorker(nil), 100 changes: mock.modelChanges, 101 }, nil 102 } 103 104 type mockDestroyer struct { 105 environs.Environ 106 stub *testing.Stub 107 } 108 109 func (mock *mockDestroyer) Destroy(ctx environscontext.ProviderCallContext) error { 110 mock.stub.AddCall("Destroy", ctx) 111 // A small delay to allow any timeout to expire. 112 time.Sleep(100 * time.Millisecond) 113 return mock.stub.NextErr() 114 } 115 116 type mockWatcher struct { 117 worker.Worker 118 changes chan struct{} 119 } 120 121 func (mock *mockWatcher) Changes() watcher.NotifyChannel { 122 return mock.changes 123 } 124 125 type fixture struct { 126 info params.UndertakerModelInfoResult 127 errors []error 128 dirty bool 129 logger fakeLogger 130 clock testclock.AdvanceableClock 131 advance time.Duration 132 } 133 134 func (fix *fixture) cleanup(c *gc.C, w worker.Worker) { 135 if fix.dirty { 136 workertest.DirtyKill(c, w) 137 } else { 138 workertest.CleanKill(c, w) 139 } 140 } 141 142 func (fix *fixture) run(c *gc.C, test func(worker.Worker)) *testing.Stub { 143 stub := &testing.Stub{} 144 facade := &mockFacade{ 145 stub: stub, 146 info: fix.info, 147 clock: fix.clock, 148 advance: fix.advance, 149 modelChanges: make(chan struct{}, 1), 150 } 151 facade.modelChanges <- struct{}{} 152 stub.SetErrors(fix.errors...) 153 w, err := undertaker.NewUndertaker(undertaker.Config{ 154 Facade: facade, 155 CredentialAPI: &fakeCredentialAPI{}, 156 Logger: &fix.logger, 157 Clock: fix.clock, 158 NewCloudDestroyerFunc: func(ctx context.Context, op environs.OpenParams) (environs.CloudDestroyer, error) { 159 return &mockDestroyer{stub: stub}, nil 160 }, 161 }) 162 c.Assert(err, jc.ErrorIsNil) 163 defer fix.cleanup(c, w) 164 test(w) 165 return stub 166 }