github.com/gerbenjacobs/terraform@v0.9.5-0.20170630130047-e6ddd62583d8/command/hook_ui_test.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/hashicorp/terraform/terraform" 10 "github.com/mitchellh/cli" 11 "github.com/mitchellh/colorstring" 12 ) 13 14 func TestUiHookPreApply_periodicTimer(t *testing.T) { 15 ui := &cli.MockUi{ 16 InputReader: bytes.NewReader([]byte{}), 17 ErrorWriter: bytes.NewBuffer([]byte{}), 18 OutputWriter: bytes.NewBuffer([]byte{}), 19 } 20 h := &UiHook{ 21 Colorize: &colorstring.Colorize{ 22 Colors: colorstring.DefaultColors, 23 Disable: true, 24 Reset: true, 25 }, 26 Ui: ui, 27 PeriodicUiTimer: 1 * time.Second, 28 } 29 h.init() 30 h.resources = map[string]uiResourceState{ 31 "data.aws_availability_zones.available": uiResourceState{ 32 Op: uiResourceDestroy, 33 Start: time.Now(), 34 }, 35 } 36 37 n := &terraform.InstanceInfo{ 38 Id: "data.aws_availability_zones.available", 39 ModulePath: []string{"root"}, 40 Type: "aws_availability_zones", 41 } 42 43 s := &terraform.InstanceState{ 44 ID: "2017-03-05 10:56:59.298784526 +0000 UTC", 45 Attributes: map[string]string{ 46 "id": "2017-03-05 10:56:59.298784526 +0000 UTC", 47 "names.#": "4", 48 "names.0": "us-east-1a", 49 "names.1": "us-east-1b", 50 "names.2": "us-east-1c", 51 "names.3": "us-east-1d", 52 }, 53 } 54 d := &terraform.InstanceDiff{ 55 Destroy: true, 56 } 57 58 action, err := h.PreApply(n, s, d) 59 if err != nil { 60 t.Fatal(err) 61 } 62 if action != terraform.HookActionContinue { 63 t.Fatalf("Expected hook to continue, given: %#v", action) 64 } 65 66 time.Sleep(3100 * time.Millisecond) 67 68 // stop the background writer 69 uiState := h.resources[n.HumanId()] 70 close(uiState.DoneCh) 71 <-uiState.done 72 73 expectedOutput := `data.aws_availability_zones.available: Destroying... (ID: 2017-03-05 10:56:59.298784526 +0000 UTC) 74 data.aws_availability_zones.available: Still destroying... (ID: 2017-03-05 10:56:59.298784526 +0000 UTC, 1s elapsed) 75 data.aws_availability_zones.available: Still destroying... (ID: 2017-03-05 10:56:59.298784526 +0000 UTC, 2s elapsed) 76 data.aws_availability_zones.available: Still destroying... (ID: 2017-03-05 10:56:59.298784526 +0000 UTC, 3s elapsed) 77 ` 78 output := ui.OutputWriter.String() 79 if output != expectedOutput { 80 t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) 81 } 82 83 expectedErrOutput := "" 84 errOutput := ui.ErrorWriter.String() 85 if errOutput != expectedErrOutput { 86 t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) 87 } 88 } 89 90 func TestUiHookPreApply_destroy(t *testing.T) { 91 ui := &cli.MockUi{ 92 InputReader: bytes.NewReader([]byte{}), 93 ErrorWriter: bytes.NewBuffer([]byte{}), 94 OutputWriter: bytes.NewBuffer([]byte{}), 95 } 96 h := &UiHook{ 97 Colorize: &colorstring.Colorize{ 98 Colors: colorstring.DefaultColors, 99 Disable: true, 100 Reset: true, 101 }, 102 Ui: ui, 103 } 104 h.init() 105 h.resources = map[string]uiResourceState{ 106 "data.aws_availability_zones.available": uiResourceState{ 107 Op: uiResourceDestroy, 108 Start: time.Now(), 109 }, 110 } 111 112 n := &terraform.InstanceInfo{ 113 Id: "data.aws_availability_zones.available", 114 ModulePath: []string{"root"}, 115 Type: "aws_availability_zones", 116 } 117 118 s := &terraform.InstanceState{ 119 ID: "2017-03-05 10:56:59.298784526 +0000 UTC", 120 Attributes: map[string]string{ 121 "id": "2017-03-05 10:56:59.298784526 +0000 UTC", 122 "names.#": "4", 123 "names.0": "us-east-1a", 124 "names.1": "us-east-1b", 125 "names.2": "us-east-1c", 126 "names.3": "us-east-1d", 127 }, 128 } 129 d := &terraform.InstanceDiff{ 130 Destroy: true, 131 } 132 133 action, err := h.PreApply(n, s, d) 134 if err != nil { 135 t.Fatal(err) 136 } 137 if action != terraform.HookActionContinue { 138 t.Fatalf("Expected hook to continue, given: %#v", action) 139 } 140 141 expectedOutput := "data.aws_availability_zones.available: Destroying... (ID: 2017-03-05 10:56:59.298784526 +0000 UTC)\n" 142 output := ui.OutputWriter.String() 143 if output != expectedOutput { 144 t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) 145 } 146 147 expectedErrOutput := "" 148 errOutput := ui.ErrorWriter.String() 149 if errOutput != expectedErrOutput { 150 t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) 151 } 152 } 153 154 func TestUiHookPostApply_emptyState(t *testing.T) { 155 ui := &cli.MockUi{ 156 InputReader: bytes.NewReader([]byte{}), 157 ErrorWriter: bytes.NewBuffer([]byte{}), 158 OutputWriter: bytes.NewBuffer([]byte{}), 159 } 160 h := &UiHook{ 161 Colorize: &colorstring.Colorize{ 162 Colors: colorstring.DefaultColors, 163 Disable: true, 164 Reset: true, 165 }, 166 Ui: ui, 167 } 168 h.init() 169 h.resources = map[string]uiResourceState{ 170 "data.google_compute_zones.available": uiResourceState{ 171 Op: uiResourceDestroy, 172 Start: time.Now(), 173 }, 174 } 175 176 n := &terraform.InstanceInfo{ 177 Id: "data.google_compute_zones.available", 178 ModulePath: []string{"root"}, 179 Type: "google_compute_zones", 180 } 181 action, err := h.PostApply(n, nil, nil) 182 if err != nil { 183 t.Fatal(err) 184 } 185 if action != terraform.HookActionContinue { 186 t.Fatalf("Expected hook to continue, given: %#v", action) 187 } 188 189 expectedOutput := "data.google_compute_zones.available: Destruction complete\n" 190 output := ui.OutputWriter.String() 191 if output != expectedOutput { 192 t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) 193 } 194 195 expectedErrOutput := "" 196 errOutput := ui.ErrorWriter.String() 197 if errOutput != expectedErrOutput { 198 t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) 199 } 200 } 201 202 func TestTruncateId(t *testing.T) { 203 testCases := []struct { 204 Input string 205 Expected string 206 MaxLen int 207 }{ 208 { 209 Input: "Hello world", 210 Expected: "H...d", 211 MaxLen: 3, 212 }, 213 { 214 Input: "Hello world", 215 Expected: "H...d", 216 MaxLen: 5, 217 }, 218 { 219 Input: "Hello world", 220 Expected: "He...d", 221 MaxLen: 6, 222 }, 223 { 224 Input: "Hello world", 225 Expected: "He...ld", 226 MaxLen: 7, 227 }, 228 { 229 Input: "Hello world", 230 Expected: "Hel...ld", 231 MaxLen: 8, 232 }, 233 { 234 Input: "Hello world", 235 Expected: "Hel...rld", 236 MaxLen: 9, 237 }, 238 { 239 Input: "Hello world", 240 Expected: "Hell...rld", 241 MaxLen: 10, 242 }, 243 { 244 Input: "Hello world", 245 Expected: "Hello world", 246 MaxLen: 11, 247 }, 248 { 249 Input: "Hello world", 250 Expected: "Hello world", 251 MaxLen: 12, 252 }, 253 } 254 for i, tc := range testCases { 255 testName := fmt.Sprintf("%d", i) 256 t.Run(testName, func(t *testing.T) { 257 out := truncateId(tc.Input, tc.MaxLen) 258 if out != tc.Expected { 259 t.Fatalf("Expected %q to be shortened to %d as %q (given: %q)", 260 tc.Input, tc.MaxLen, tc.Expected, out) 261 } 262 }) 263 } 264 }