github.phpd.cn/hashicorp/packer@v1.3.2/packer/provisioner_test.go (about) 1 package packer 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 ) 8 9 func TestProvisionHook_Impl(t *testing.T) { 10 var raw interface{} 11 raw = &ProvisionHook{} 12 if _, ok := raw.(Hook); !ok { 13 t.Fatalf("must be a Hook") 14 } 15 } 16 17 func TestProvisionHook(t *testing.T) { 18 pA := &MockProvisioner{} 19 pB := &MockProvisioner{} 20 21 ui := testUi() 22 var comm Communicator = new(MockCommunicator) 23 var data interface{} = nil 24 25 hook := &ProvisionHook{ 26 Provisioners: []*HookedProvisioner{ 27 {pA, nil, ""}, 28 {pB, nil, ""}, 29 }, 30 } 31 32 hook.Run("foo", ui, comm, data) 33 34 if !pA.ProvCalled { 35 t.Error("provision should be called on pA") 36 } 37 38 if !pB.ProvCalled { 39 t.Error("provision should be called on pB") 40 } 41 } 42 43 func TestProvisionHook_nilComm(t *testing.T) { 44 pA := &MockProvisioner{} 45 pB := &MockProvisioner{} 46 47 ui := testUi() 48 var comm Communicator = nil 49 var data interface{} = nil 50 51 hook := &ProvisionHook{ 52 Provisioners: []*HookedProvisioner{ 53 {pA, nil, ""}, 54 {pB, nil, ""}, 55 }, 56 } 57 58 err := hook.Run("foo", ui, comm, data) 59 if err == nil { 60 t.Fatal("should error") 61 } 62 } 63 64 func TestProvisionHook_cancel(t *testing.T) { 65 var lock sync.Mutex 66 order := make([]string, 0, 2) 67 68 p := &MockProvisioner{ 69 ProvFunc: func() error { 70 time.Sleep(100 * time.Millisecond) 71 72 lock.Lock() 73 defer lock.Unlock() 74 order = append(order, "prov") 75 76 return nil 77 }, 78 } 79 80 hook := &ProvisionHook{ 81 Provisioners: []*HookedProvisioner{ 82 {p, nil, ""}, 83 }, 84 } 85 86 finished := make(chan struct{}) 87 go func() { 88 hook.Run("foo", nil, new(MockCommunicator), nil) 89 close(finished) 90 }() 91 92 // Cancel it while it is running 93 time.Sleep(10 * time.Millisecond) 94 hook.Cancel() 95 lock.Lock() 96 order = append(order, "cancel") 97 lock.Unlock() 98 99 // Wait 100 <-finished 101 102 // Verify order 103 if len(order) != 2 || order[0] != "cancel" || order[1] != "prov" { 104 t.Fatalf("bad: %#v", order) 105 } 106 } 107 108 // TODO(mitchellh): Test that they're run in the proper order 109 110 func TestPausedProvisioner_impl(t *testing.T) { 111 var _ Provisioner = new(PausedProvisioner) 112 } 113 114 func TestPausedProvisionerPrepare(t *testing.T) { 115 mock := new(MockProvisioner) 116 prov := &PausedProvisioner{ 117 Provisioner: mock, 118 } 119 120 prov.Prepare(42) 121 if !mock.PrepCalled { 122 t.Fatal("prepare should be called") 123 } 124 if mock.PrepConfigs[0] != 42 { 125 t.Fatal("should have proper configs") 126 } 127 } 128 129 func TestPausedProvisionerProvision(t *testing.T) { 130 mock := new(MockProvisioner) 131 prov := &PausedProvisioner{ 132 Provisioner: mock, 133 } 134 135 ui := testUi() 136 comm := new(MockCommunicator) 137 prov.Provision(ui, comm) 138 if !mock.ProvCalled { 139 t.Fatal("prov should be called") 140 } 141 if mock.ProvUi != ui { 142 t.Fatal("should have proper ui") 143 } 144 if mock.ProvCommunicator != comm { 145 t.Fatal("should have proper comm") 146 } 147 } 148 149 func TestPausedProvisionerProvision_waits(t *testing.T) { 150 mock := new(MockProvisioner) 151 prov := &PausedProvisioner{ 152 PauseBefore: 50 * time.Millisecond, 153 Provisioner: mock, 154 } 155 156 dataCh := make(chan struct{}) 157 mock.ProvFunc = func() error { 158 close(dataCh) 159 return nil 160 } 161 162 go prov.Provision(testUi(), new(MockCommunicator)) 163 164 select { 165 case <-time.After(10 * time.Millisecond): 166 case <-dataCh: 167 t.Fatal("should not be called") 168 } 169 170 select { 171 case <-time.After(100 * time.Millisecond): 172 t.Fatal("never called") 173 case <-dataCh: 174 } 175 } 176 177 func TestPausedProvisionerCancel(t *testing.T) { 178 mock := new(MockProvisioner) 179 prov := &PausedProvisioner{ 180 Provisioner: mock, 181 } 182 183 provCh := make(chan struct{}) 184 mock.ProvFunc = func() error { 185 close(provCh) 186 time.Sleep(10 * time.Millisecond) 187 return nil 188 } 189 190 // Start provisioning and wait for it to start 191 go prov.Provision(testUi(), new(MockCommunicator)) 192 <-provCh 193 194 // Cancel it 195 prov.Cancel() 196 if !mock.CancelCalled { 197 t.Fatal("cancel should be called") 198 } 199 } 200 201 func TestDebuggedProvisioner_impl(t *testing.T) { 202 var _ Provisioner = new(DebuggedProvisioner) 203 } 204 205 func TestDebuggedProvisionerPrepare(t *testing.T) { 206 mock := new(MockProvisioner) 207 prov := &DebuggedProvisioner{ 208 Provisioner: mock, 209 } 210 211 prov.Prepare(42) 212 if !mock.PrepCalled { 213 t.Fatal("prepare should be called") 214 } 215 if mock.PrepConfigs[0] != 42 { 216 t.Fatal("should have proper configs") 217 } 218 } 219 220 func TestDebuggedProvisionerProvision(t *testing.T) { 221 mock := new(MockProvisioner) 222 prov := &DebuggedProvisioner{ 223 Provisioner: mock, 224 } 225 226 ui := testUi() 227 comm := new(MockCommunicator) 228 writeReader(ui, "\n") 229 prov.Provision(ui, comm) 230 if !mock.ProvCalled { 231 t.Fatal("prov should be called") 232 } 233 if mock.ProvUi != ui { 234 t.Fatal("should have proper ui") 235 } 236 if mock.ProvCommunicator != comm { 237 t.Fatal("should have proper comm") 238 } 239 } 240 241 func TestDebuggedProvisionerCancel(t *testing.T) { 242 mock := new(MockProvisioner) 243 prov := &DebuggedProvisioner{ 244 Provisioner: mock, 245 } 246 247 provCh := make(chan struct{}) 248 mock.ProvFunc = func() error { 249 close(provCh) 250 time.Sleep(10 * time.Millisecond) 251 return nil 252 } 253 254 // Start provisioning and wait for it to start 255 go prov.Provision(testUi(), new(MockCommunicator)) 256 <-provCh 257 258 // Cancel it 259 prov.Cancel() 260 if !mock.CancelCalled { 261 t.Fatal("cancel should be called") 262 } 263 }