From 4d6242dfe0a834d0ccdba8436343a796fac5386b Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Mon, 13 Mar 2017 20:09:25 +0000 Subject: [PATCH] command: Add tests for UiHook (#12447) --- command/hook_ui.go | 12 ++- command/hook_ui_test.go | 189 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 4 deletions(-) diff --git a/command/hook_ui.go b/command/hook_ui.go index 1ebcc578d..25a91ab47 100644 --- a/command/hook_ui.go +++ b/command/hook_ui.go @@ -15,14 +15,15 @@ import ( "github.com/mitchellh/colorstring" ) -const periodicUiTimer = 10 * time.Second +const defaultPeriodicUiTimer = 10 * time.Second const maxIdLen = 20 type UiHook struct { terraform.NilHook - Colorize *colorstring.Colorize - Ui cli.Ui + Colorize *colorstring.Colorize + Ui cli.Ui + PeriodicUiTimer time.Duration l sync.Mutex once sync.Once @@ -163,7 +164,7 @@ func (h *UiHook) stillApplying(state uiResourceState) { case <-state.DoneCh: return - case <-time.After(periodicUiTimer): + case <-time.After(h.PeriodicUiTimer): // Timer up, show status } @@ -330,6 +331,9 @@ func (h *UiHook) init() { if h.Colorize == nil { panic("colorize not given") } + if h.PeriodicUiTimer == 0 { + h.PeriodicUiTimer = defaultPeriodicUiTimer + } h.resources = make(map[string]uiResourceState) diff --git a/command/hook_ui_test.go b/command/hook_ui_test.go index 1c6476efe..0d9f36563 100644 --- a/command/hook_ui_test.go +++ b/command/hook_ui_test.go @@ -1,10 +1,199 @@ package command import ( + "bytes" "fmt" "testing" + "time" + + "github.com/hashicorp/terraform/terraform" + "github.com/mitchellh/cli" + "github.com/mitchellh/colorstring" ) +func TestUiHookPreApply_periodicTimer(t *testing.T) { + ui := &cli.MockUi{ + InputReader: bytes.NewReader([]byte{}), + ErrorWriter: bytes.NewBuffer([]byte{}), + OutputWriter: bytes.NewBuffer([]byte{}), + } + h := &UiHook{ + Colorize: &colorstring.Colorize{ + Colors: colorstring.DefaultColors, + Disable: true, + Reset: true, + }, + Ui: ui, + PeriodicUiTimer: 1 * time.Second, + } + h.init() + h.resources = map[string]uiResourceState{ + "data.aws_availability_zones.available": uiResourceState{ + Op: uiResourceDestroy, + Start: time.Now(), + }, + } + + n := &terraform.InstanceInfo{ + Id: "data.aws_availability_zones.available", + ModulePath: []string{"root"}, + Type: "aws_availability_zones", + } + + s := &terraform.InstanceState{ + ID: "2017-03-05 10:56:59.298784526 +0000 UTC", + Attributes: map[string]string{ + "id": "2017-03-05 10:56:59.298784526 +0000 UTC", + "names.#": "4", + "names.0": "us-east-1a", + "names.1": "us-east-1b", + "names.2": "us-east-1c", + "names.3": "us-east-1d", + }, + } + d := &terraform.InstanceDiff{ + Destroy: true, + } + + action, err := h.PreApply(n, s, d) + if err != nil { + t.Fatal(err) + } + if action != terraform.HookActionContinue { + t.Fatalf("Expected hook to continue, given: %#v", action) + } + + time.Sleep(3100 * time.Millisecond) + + expectedOutput := `data.aws_availability_zones.available: Destroying... (ID: 2017-03-0...0000 UTC) +data.aws_availability_zones.available: Still destroying... (ID: 2017-03-0...0000 UTC, 1s elapsed) +data.aws_availability_zones.available: Still destroying... (ID: 2017-03-0...0000 UTC, 2s elapsed) +data.aws_availability_zones.available: Still destroying... (ID: 2017-03-0...0000 UTC, 3s elapsed) +` + output := ui.OutputWriter.String() + if output != expectedOutput { + t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) + } + + expectedErrOutput := "" + errOutput := ui.ErrorWriter.String() + if errOutput != expectedErrOutput { + t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) + } +} + +func TestUiHookPreApply_destroy(t *testing.T) { + ui := &cli.MockUi{ + InputReader: bytes.NewReader([]byte{}), + ErrorWriter: bytes.NewBuffer([]byte{}), + OutputWriter: bytes.NewBuffer([]byte{}), + } + h := &UiHook{ + Colorize: &colorstring.Colorize{ + Colors: colorstring.DefaultColors, + Disable: true, + Reset: true, + }, + Ui: ui, + } + h.init() + h.resources = map[string]uiResourceState{ + "data.aws_availability_zones.available": uiResourceState{ + Op: uiResourceDestroy, + Start: time.Now(), + }, + } + + n := &terraform.InstanceInfo{ + Id: "data.aws_availability_zones.available", + ModulePath: []string{"root"}, + Type: "aws_availability_zones", + } + + s := &terraform.InstanceState{ + ID: "2017-03-05 10:56:59.298784526 +0000 UTC", + Attributes: map[string]string{ + "id": "2017-03-05 10:56:59.298784526 +0000 UTC", + "names.#": "4", + "names.0": "us-east-1a", + "names.1": "us-east-1b", + "names.2": "us-east-1c", + "names.3": "us-east-1d", + }, + } + d := &terraform.InstanceDiff{ + Destroy: true, + } + + action, err := h.PreApply(n, s, d) + if err != nil { + t.Fatal(err) + } + if action != terraform.HookActionContinue { + t.Fatalf("Expected hook to continue, given: %#v", action) + } + + expectedOutput := "data.aws_availability_zones.available: Destroying... (ID: 2017-03-0...0000 UTC)\n" + output := ui.OutputWriter.String() + if output != expectedOutput { + t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) + } + + expectedErrOutput := "" + errOutput := ui.ErrorWriter.String() + if errOutput != expectedErrOutput { + t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) + } +} + +func TestUiHookPostApply_emptyState(t *testing.T) { + ui := &cli.MockUi{ + InputReader: bytes.NewReader([]byte{}), + ErrorWriter: bytes.NewBuffer([]byte{}), + OutputWriter: bytes.NewBuffer([]byte{}), + } + h := &UiHook{ + Colorize: &colorstring.Colorize{ + Colors: colorstring.DefaultColors, + Disable: true, + Reset: true, + }, + Ui: ui, + } + h.init() + h.resources = map[string]uiResourceState{ + "data.google_compute_zones.available": uiResourceState{ + Op: uiResourceDestroy, + Start: time.Now(), + }, + } + + n := &terraform.InstanceInfo{ + Id: "data.google_compute_zones.available", + ModulePath: []string{"root"}, + Type: "google_compute_zones", + } + action, err := h.PostApply(n, nil, nil) + if err != nil { + t.Fatal(err) + } + if action != terraform.HookActionContinue { + t.Fatalf("Expected hook to continue, given: %#v", action) + } + + expectedOutput := "data.google_compute_zones.available: Destruction complete\n" + output := ui.OutputWriter.String() + if output != expectedOutput { + t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output) + } + + expectedErrOutput := "" + errOutput := ui.ErrorWriter.String() + if errOutput != expectedErrOutput { + t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput) + } +} + func TestTruncateId(t *testing.T) { testCases := []struct { Input string