Skip to content

Commit

Permalink
views: add tests for cloud view
Browse files Browse the repository at this point in the history
Signed-off-by: Bruno Schaatsbergen <[email protected]>
  • Loading branch information
bschaatsbergen committed Nov 6, 2024
1 parent f4fbb62 commit fc57ccc
Showing 1 changed file with 186 additions and 37 deletions.
223 changes: 186 additions & 37 deletions internal/command/views/cloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,83 @@ package views

import (
"fmt"
"net/http"
"strings"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/internal/command/arguments"
"github.com/hashicorp/terraform/internal/terminal"
"github.com/hashicorp/terraform/internal/tfdiags"
tfversion "github.com/hashicorp/terraform/version"
)

func TestNewCloudHuman_RetryLog(t *testing.T) {
t.Run("first retry, no output", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
cloudHuman, ok := newCloud.(*CloudHuman)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudHuman.RetryLog(0, nil)
output := done(t).All()
if output != "" {
t.Fatalf("expected no output for the first retry attempt, but got: %s", output)
}
})

t.Run("second retry, server error", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
cloudHuman, ok := newCloud.(*CloudHuman)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudHuman.RetryLog(1, &http.Response{StatusCode: 500})
output := done(t).All()
expected := "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."
if !strings.Contains(output, expected) {
t.Fatalf("expected output to contain: %s, but got %s", expected, output)
}
})

t.Run("subsequent retry with elapsed time", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
cloudHuman, ok := newCloud.(*CloudHuman)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudHuman.lastRetry = time.Now().Add(-2 * time.Second) // Simulate a delay of 2 seconds
cloudHuman.RetryLog(2, &http.Response{StatusCode: 500})
output := done(t).All()
expected := "Still trying to restore the connection... (2s elapsed)"
if !strings.Contains(output, expected) {
t.Fatalf("expected output to contain: %s, but got %s", expected, output)
}
})

t.Run("retry with 429 status, no output", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
cloudHuman, ok := newCloud.(*CloudHuman)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudHuman.RetryLog(2, &http.Response{StatusCode: 429})
output := done(t).All()
if output != "" {
t.Fatalf("expected no output for status code 429, but got: %s", output)
}
})
}

func TestNewCloud_unsupportedViewDiagnostics(t *testing.T) {
defer func() {
r := recover()
Expand Down Expand Up @@ -67,24 +132,6 @@ func TestNewCloud_humanViewOutput(t *testing.T) {
})
}

func TestNewCloud_humanViewPrepareMessage(t *testing.T) {
t.Run("existing message code", func(t *testing.T) {
streams, _ := terminal.StreamsForTesting(t)

newCloud := NewCloud(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
if _, ok := newCloud.(*CloudHuman); !ok {
t.Fatalf("unexpected return type %t", newCloud)
}

want := "\nThere was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."

actual := newCloud.PrepareMessage(InitialRetryErrorMessage)
if !cmp.Equal(want, actual) {
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
}
})
}

func TestNewCloud_humanViewDiagnostics(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)

Expand All @@ -103,16 +150,41 @@ func TestNewCloud_humanViewDiagnostics(t *testing.T) {
}
}

func TestNewCloud_jsonViewOutput(t *testing.T) {
t.Run("no param", func(t *testing.T) {
func TestNewCloudJSON_RetryLog(t *testing.T) {
t.Run("attempt 0, no output", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
cloudJSON, ok := newCloud.(*CloudJSON)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudJSON.RetryLog(0, nil)

version := tfversion.String()
want := []map[string]interface{}{
{
"@level": "info",
"@message": fmt.Sprintf("Terraform %s", version),
"@module": "terraform.ui",
"terraform": version,
"type": "version",
"ui": JSON_UI_VERSION,
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})

t.Run("attempt 1, server error", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newCloud.(*CloudJSON); !ok {
t.Fatalf("unexpected return type %t", newCloud)
cloudJSON, ok := newCloud.(*CloudJSON)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

newCloud.Output(InitialRetryErrorMessage)
cloudJSON.RetryLog(1, &http.Response{StatusCode: 500})

version := tfversion.String()
want := []map[string]interface{}{
Expand All @@ -132,21 +204,82 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
"type": "cloud_output",
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})

t.Run("subsequent retry with elapsed time", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
cloudJSON, ok := newCloud.(*CloudJSON)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudJSON.lastRetry = time.Now().Add(-2 * time.Second) // Simulate a delay of 2 seconds
cloudJSON.RetryLog(2, &http.Response{StatusCode: 500})

version := tfversion.String()
want := []map[string]interface{}{
{
"@level": "info",
"@message": fmt.Sprintf("Terraform %s", version),
"@module": "terraform.ui",
"terraform": version,
"type": "version",
"ui": JSON_UI_VERSION,
},
{
"@level": "info",
"@message": "Still trying to restore the connection... (2s elapsed)",
"message_code": "repeated_retry_error_message",
"@module": "terraform.ui",
"type": "cloud_output",
},
}

actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})

t.Run("single param", func(t *testing.T) {
t.Run("retry with 429 status, no output", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
cloudJSON, ok := newCloud.(*CloudJSON)
if !ok {
t.Fatalf("unexpected return type %T", newCloud)
}

cloudJSON.RetryLog(0, &http.Response{
StatusCode: http.StatusTooManyRequests, // HTTP: 429
})

version := tfversion.String()
want := []map[string]interface{}{
{
"@level": "info",
"@message": fmt.Sprintf("Terraform %s", version),
"@module": "terraform.ui",
"terraform": version,
"type": "version",
"ui": JSON_UI_VERSION,
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
}

func TestNewCloud_jsonViewOutput(t *testing.T) {
t.Run("no param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)

newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newCloud.(*CloudJSON); !ok {
t.Fatalf("unexpected return type %t", newCloud)
}

duration := 5 * time.Second
newCloud.Output(RepeatedRetryErrorMessage, duration)
newCloud.Output(InitialRetryErrorMessage)

version := tfversion.String()
want := []map[string]interface{}{
Expand All @@ -160,33 +293,49 @@ func TestNewCloud_jsonViewOutput(t *testing.T) {
},
{
"@level": "info",
"@message": fmt.Sprintf("Still trying to restore the connection... (%s elapsed)", duration),
"@message": "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection...",
"message_code": "initial_retry_error_message",
"@module": "terraform.ui",
"message_code": "repeated_retry_error_message",
"type": "cloud_output",
},
}

actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
}

func TestNewCloud_jsonViewPrepareMessage(t *testing.T) {
t.Run("existing message code", func(t *testing.T) {
streams, _ := terminal.StreamsForTesting(t)
t.Run("single param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)

newCloud := NewCloud(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newCloud.(*CloudJSON); !ok {
t.Fatalf("unexpected return type %t", newCloud)
}

want := "There was an error connecting to HCP Terraform. Please do not exit\nTerraform to prevent data loss! Trying to restore the connection..."
duration := 5 * time.Second
newCloud.Output(RepeatedRetryErrorMessage, duration)

actual := newCloud.PrepareMessage(InitialRetryErrorMessage)
if !cmp.Equal(want, actual) {
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
version := tfversion.String()
want := []map[string]interface{}{
{
"@level": "info",
"@message": fmt.Sprintf("Terraform %s", version),
"@module": "terraform.ui",
"terraform": version,
"type": "version",
"ui": JSON_UI_VERSION,
},
{
"@level": "info",
"@message": fmt.Sprintf("Still trying to restore the connection... (%s elapsed)", duration),
"@module": "terraform.ui",
"message_code": "repeated_retry_error_message",
"type": "cloud_output",
},
}

actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
}

Expand Down

0 comments on commit fc57ccc

Please sign in to comment.