fixing tests internal/command/init, view and argumento

tf-init-json
UKEME BASSEY 2 years ago
parent ba8386b8a2
commit 0ea25e3b40

@ -0,0 +1,136 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package arguments
import (
"flag"
"io"
"strings"
"testing"
"time"
"github.com/google/go-cmp/cmp"
)
func TestParseInit_basicValid(t *testing.T) {
testCases := map[string]struct {
args []string
want *Init
}{
"with default options": {
nil,
&Init{
FromModule: "",
Lockfile: "",
TestsDirectory: "tests",
ViewType: ViewHuman,
Backend: true,
Cloud: true,
Get: true,
ForceInitCopy: false,
StateLock: true,
StateLockTimeout: 0,
Reconfigure: false,
MigrateState: false,
Upgrade: false,
Json: false,
IgnoreRemoteVersion: false,
},
},
"setting multiple options": {
[]string{"-backend=false", "-force-copy=true",
"-from-module=./main-dir", "-json", "-get=false",
"-lock=false", "-lock-timeout=10s", "-reconfigure=true",
"-upgrade=true", "-lockfile=readonly",
"-ignore-remote-version=true", "-test-directory=./test-dir"},
&Init{
FromModule: "./main-dir",
Lockfile: "readonly",
TestsDirectory: "./test-dir",
ViewType: ViewJSON,
Backend: false,
Cloud: false,
Get: false,
ForceInitCopy: true,
StateLock: false,
StateLockTimeout: time.Duration(10) * time.Second,
Reconfigure: true,
MigrateState: false,
Upgrade: true,
Json: true,
IgnoreRemoteVersion: true,
},
},
"with cloud option": {
[]string{"-cloud=false"},
&Init{
FromModule: "",
Lockfile: "",
TestsDirectory: "tests",
ViewType: ViewHuman,
Backend: false,
Cloud: false,
Get: true,
ForceInitCopy: false,
StateLock: true,
StateLockTimeout: 0,
Reconfigure: false,
MigrateState: false,
Upgrade: false,
Json: false,
IgnoreRemoteVersion: false,
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
cmdFlags := flag.NewFlagSet("init", flag.ContinueOnError)
cmdFlags.SetOutput(io.Discard)
got, diags := ParseInit(tc.args, cmdFlags)
if len(diags) > 0 {
t.Fatalf("unexpected diags: %v", diags)
}
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("unexpected result\n%s", diff)
}
})
}
}
func TestParseInit_invalid(t *testing.T) {
testCases := map[string]struct {
args []string
wantErr string
}{
"with unsupported options": {
args: []string{"-raw"},
wantErr: "flag provided but not defined",
},
"with both -backend and -cloud options set": {
args: []string{"-backend=false", "-cloud=false"},
wantErr: "The -backend and -cloud options are aliases of one another and mutually-exclusive in their use",
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
cmdFlags := flag.NewFlagSet("init", flag.ContinueOnError)
cmdFlags.SetOutput(io.Discard)
got, diags := ParseInit(tc.args, cmdFlags)
if len(diags) == 0 {
t.Fatal("expected diags but got none")
}
if got, want := diags.Err().Error(), tc.wantErr; !strings.Contains(got, want) {
t.Fatalf("wrong diags\n got: %s\nwant: %s", got, want)
}
if got.ViewType != ViewHuman {
t.Fatalf("wrong view type, got %#v, want %#v", got.ViewType, ViewHuman)
}
})
}
}

@ -148,7 +148,7 @@ func (c *InitCommand) Run(args []string) int {
view.Output(views.CopyingConfigurationMessage, src)
header = true
hooks := uiModuleInstallHooks{ // here check to verify if downloading prints text, update to handle view type
hooks := uiModuleInstallHooks{
Ui: c.Ui,
ShowLocalPaths: false, // since they are in a weird location for init
View: view,

File diff suppressed because it is too large Load Diff

@ -59,7 +59,7 @@ func TestProvidersSchema_output(t *testing.T) {
p := providersSchemaFixtureProvider()
ui := new(cli.MockUi)
view, _ := testView(t)
view, done := testView(t)
m := Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
@ -72,12 +72,9 @@ func TestProvidersSchema_output(t *testing.T) {
Meta: m,
}
if code := ic.Run([]string{}); code != 0 {
t.Fatalf("init failed\n%s", ui.ErrorWriter)
t.Fatalf("init failed\n%s", done(t).Stderr())
}
// flush the init output from the mock ui
ui.OutputWriter.Reset()
// `terraform provider schemas` command
pc := &ProvidersSchemaCommand{Meta: m}
if code := pc.Run([]string{"-json"}); code != 0 {

@ -1710,7 +1710,21 @@ func TestTest_SensitiveInputValues(t *testing.T) {
t.Errorf("expected status code 0 but got %d", code)
}
expected := `main.tftest.hcl... in progress
expected := `Initializing the backend...
Initializing modules...
- test.main.setup in setup
Initializing provider plugins...
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
main.tftest.hcl... in progress
run "setup"... pass
run "test"... pass
@ -1915,7 +1929,20 @@ func TestTest_InvalidOverrides(t *testing.T) {
t.Errorf("expected status code 0 but got %d", code)
}
expected := `
expected := `Initializing the backend...
Initializing modules...
- setup in setup
- test.main.setup in setup
Initializing provider plugins...
- Finding latest version of hashicorp/test...
- Installing hashicorp/test v1.0.0...
- Installed hashicorp/test v1.0.0 (verified checksum)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Warning: Incomplete lock file information for providers
Due to your customized provider installation methods, Terraform was forced to
@ -1929,6 +1956,15 @@ providers.
To calculate additional checksums for another platform, run:
terraform providers lock -platform=linux_amd64
(where linux_amd64 is the platform to generate)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
main.tftest.hcl... in progress
run "setup"... pass
@ -2023,7 +2059,19 @@ func TestTest_RunBlocksInProviders(t *testing.T) {
t.Errorf("expected status code 0 but got %d", code)
}
expected := `
expected := `Initializing the backend...
Initializing modules...
- test.main.setup in setup
Initializing provider plugins...
- Finding latest version of hashicorp/test...
- Installing hashicorp/test v1.0.0...
- Installed hashicorp/test v1.0.0 (verified checksum)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Warning: Incomplete lock file information for providers
Due to your customized provider installation methods, Terraform was forced to
@ -2037,6 +2085,15 @@ providers.
To calculate additional checksums for another platform, run:
terraform providers lock -platform=linux_amd64
(where linux_amd64 is the platform to generate)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
main.tftest.hcl... in progress
run "setup"... pass
run "main"... pass
@ -2098,7 +2155,17 @@ func TestTest_RunBlocksInProviders_BadReferences(t *testing.T) {
t.Errorf("expected status code 1 but got %d", code)
}
expectedOut := `
expectedOut := `Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/test...
- Installing hashicorp/test v1.0.0...
- Installed hashicorp/test v1.0.0 (verified checksum)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Warning: Incomplete lock file information for providers
Due to your customized provider installation methods, Terraform was forced to
@ -2112,6 +2179,15 @@ providers.
To calculate additional checksums for another platform, run:
terraform providers lock -platform=linux_amd64
(where linux_amd64 is the platform to generate)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
missing_run_block.tftest.hcl... in progress
run "main"... fail
missing_run_block.tftest.hcl... tearing down

@ -0,0 +1,8 @@
{"@level":"info","@message":"Terraform 1.9.0-dev","@module":"terraform.ui","terraform":"1.9.0-dev","type":"version","ui":"1.2"}
{"@level":"info","@message":"Initializing the backend...","@module":"terraform.ui","type":"init_output"}
{"@level":"info","@message":"Initializing modules...","@module":"terraform.ui","type":"init_output"}
{"@level":"info","@message":"- foo in foo","@module":"terraform.ui","type":"log"}
{"@level":"info","@message":"Initializing provider plugins...","@module":"terraform.ui","type":"init_output"}
{"@level":"info","@message":"","@module":"terraform.ui","type":"init_output"}
{"@level":"info","@message":"Terraform has been successfully initialized!","@module":"terraform.ui","type":"init_output"}
{"@level":"info","@message":"You may now begin working with Terraform. Try running \"terraform plan\" to see\nany changes that are required for your infrastructure. All Terraform commands\nshould now work.\n\nIf you ever set or change modules or backend configuration for Terraform,\nrerun this command to reinitialize your working directory. If you forget, other\ncommands will detect it and remind you to do so if necessary.","@module":"terraform.ui","type":"init_output"}

@ -0,0 +1,2 @@
{"@level":"info","@message":"Terraform 1.9.0-dev","@module":"terraform.ui","terraform":"1.9.0-dev","type":"version","ui":"1.2"}
{"@level":"error","@message":"Error: The -migrate-state and -json options are mutually-exclusive","@module":"terraform.ui","diagnostic":{"severity":"error","summary":"The -migrate-state and -json options are mutually-exclusive","detail":"Terraform cannot ask for interactive approval when -json is set. To use the -migrate-state option, disable the -json option."},"type":"diagnostic"}

@ -1,2 +0,0 @@
{"@level":"info","@message":"Terraform 1.9.0-dev","@module":"terraform.ui","terraform":"1.9.0-dev","type":"version","ui":"1.2"}
{"@level":"error","@message":"Error: Failed to query available provider packages","@module":"terraform.ui","diagnostic":{"severity":"error","summary":"Failed to query available provider packages","detail":"Could not retrieve the list of available versions for provider hashicorp/test: no available releases match the given constraints 1.0.1, 1.0.2"},"type":"diagnostic"}

@ -361,7 +361,20 @@ func TestValidateWithInvalidOverrides(t *testing.T) {
}
actual := output.All()
expected := `
expected := `Initializing the backend...
Initializing modules...
- setup in setup
- test.main.setup in setup
Initializing provider plugins...
- Finding latest version of hashicorp/test...
- Installing hashicorp/test v1.0.0...
- Installed hashicorp/test v1.0.0 (verified checksum)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Warning: Incomplete lock file information for providers
Due to your customized provider installation methods, Terraform was forced to
@ -375,6 +388,15 @@ providers.
To calculate additional checksums for another platform, run:
terraform providers lock -platform=linux_amd64
(where linux_amd64 is the platform to generate)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Warning: Invalid override target

@ -85,7 +85,7 @@ func (v *InitJSON) Diagnostics(diags tfdiags.Diagnostics) {
}
func (v *InitJSON) Output(messageCode string, params ...any) {
current_timestamp := time.Now().Format(time.RFC3339)
current_timestamp := time.Now().UTC().Format(time.RFC3339)
json_data := map[string]string{
"@level": "info",
@ -315,49 +315,6 @@ If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.
`
// providerProtocolTooOld is a message sent to the CLI UI if the provider's
// supported protocol versions are too old for the user's version of terraform,
// but a newer version of the provider is compatible.
const providerProtocolTooOld = `Provider %q v%s is not compatible with Terraform %s.
Provider version %s is the latest compatible version. Select it with the following version constraint:
version = %q
Terraform checked all of the plugin versions matching the given constraint:
%s
Consult the documentation for this provider for more information on compatibility between provider and Terraform versions.
`
// providerProtocolTooNew is a message sent to the CLI UI if the provider's
// supported protocol versions are too new for the user's version of terraform,
// and the user could either upgrade terraform or choose an older version of the
// provider.
const providerProtocolTooNew = `Provider %q v%s is not compatible with Terraform %s.
You need to downgrade to v%s or earlier. Select it with the following constraint:
version = %q
Terraform checked all of the plugin versions matching the given constraint:
%s
Consult the documentation for this provider for more information on compatibility between provider and Terraform versions.
Alternatively, upgrade to the latest version of Terraform for compatibility with newer provider releases.
`
// incompleteLockFileInformationHeader is the summary displayed to users when
// the lock file has only recorded local hashes.
const incompleteLockFileInformationHeader = `Incomplete lock file information for providers`
// incompleteLockFileInformationBody is the body of text displayed to users when
// the lock file has only recorded local hashes.
const incompleteLockFileInformationBody = `Due to your customized provider installation methods, Terraform was forced to calculate lock file checksums locally for the following providers:
- %s
The current .terraform.lock.hcl file only includes checksums for %s, so Terraform running on another platform will fail to install these providers.
To calculate additional checksums for another platform, run:
terraform providers lock -platform=linux_amd64
(where linux_amd64 is the platform to generate)`
const previousLockInfoHuman = `
Terraform has created a lock file [bold].terraform.lock.hcl[reset] to record the provider
selections it made above. Include this file in your version control repository

@ -8,6 +8,7 @@ import (
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/internal/command/arguments"
"github.com/hashicorp/terraform/internal/terminal"
@ -15,7 +16,7 @@ import (
tfversion "github.com/hashicorp/terraform/version"
)
func TestNewInit_jsonView(t *testing.T) {
func TestNewInit_jsonViewDiagnostics(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
@ -64,7 +65,7 @@ func TestNewInit_jsonView(t *testing.T) {
testJSONViewOutputEqualsFull(t, actual, want)
}
func TestNewInit_humanView(t *testing.T) {
func TestNewInit_humanViewDiagnostics(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
@ -82,7 +83,7 @@ func TestNewInit_humanView(t *testing.T) {
}
}
func TestNewInit_unsupportedView(t *testing.T) {
func TestNewInit_unsupportedViewDiagnostics(t *testing.T) {
defer func() {
r := recover()
if r == nil {
@ -118,3 +119,233 @@ func getTestDiags(t *testing.T) tfdiags.Diagnostics {
return diags
}
func TestNewInit_jsonViewOutput(t *testing.T) {
t.Run("no param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
messageCode := "initializing_provider_plugin_message"
newInit.Output(messageCode)
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": "Initializing provider plugins...",
"@module": "terraform.ui",
"type": "init_output",
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
t.Run("single param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
packageName := "hashicorp/aws"
messageCode := "finding_latest_version_message"
newInit.Output(messageCode, packageName)
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("- Finding latest version of %s...", packageName),
"@module": "terraform.ui",
"type": "init_output",
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
t.Run("variable length params", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
var packageName, packageVersion = "hashicorp/aws", "3.0.0"
messageCode := "provider_already_installed_message"
newInit.Output(messageCode, packageName, packageVersion)
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("- Using previously-installed %s v%s", packageName, packageVersion),
"@module": "terraform.ui",
"type": "init_output",
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
})
}
func TestNewInit_jsonViewLog(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
messageCode := "initializing_provider_plugin_message"
newInit.Log(messageCode)
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": "Initializing provider plugins...",
"@module": "terraform.ui",
"type": "log",
},
}
actual := done(t).Stdout()
testJSONViewOutputEqualsFull(t, actual, want)
}
func TestNewInit_jsonViewPrepareMessage(t *testing.T) {
t.Run("message code that does not exists", func(t *testing.T) {
streams, _ := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
messageCode := "Terraform has been successfully initialized!"
want := messageCode
actual := newInit.PrepareMessage(messageCode)
if !cmp.Equal(want, actual) {
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
}
})
t.Run("existing message code", func(t *testing.T) {
streams, _ := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewJSON, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitJSON); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
messageCode := "initializing_modules_message"
want := "Initializing modules..."
actual := newInit.PrepareMessage(messageCode)
if !cmp.Equal(want, actual) {
t.Errorf("unexpected output: %s", cmp.Diff(want, actual))
}
})
}
func TestNewInit_humanViewOutput(t *testing.T) {
t.Run("no param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitHuman); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
messageCode := "initializing_provider_plugin_message"
newInit.Output(messageCode)
actual := done(t).All()
expected := "Initializing provider plugins..."
if !strings.Contains(actual, expected) {
t.Fatalf("expected output to contain: %s, but got %s", expected, actual)
}
})
t.Run("single param", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitHuman); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
packageName := "hashicorp/aws"
messageCode := "finding_latest_version_message"
newInit.Output(messageCode, packageName)
actual := done(t).All()
expected := "Finding latest version of hashicorp/aws"
if !strings.Contains(actual, expected) {
t.Fatalf("expected output to contain: %s, but got %s", expected, actual)
}
})
t.Run("variable length params", func(t *testing.T) {
streams, done := terminal.StreamsForTesting(t)
newInit := NewInit(arguments.ViewHuman, NewView(streams).SetRunningInAutomation(true))
if _, ok := newInit.(*InitHuman); !ok {
t.Fatalf("unexpected return type %t", newInit)
}
var packageName, packageVersion = "hashicorp/aws", "3.0.0"
messageCode := "provider_already_installed_message"
newInit.Output(messageCode, packageName, packageVersion)
actual := done(t).All()
expected := "- Using previously-installed hashicorp/aws v3.0.0"
if !strings.Contains(actual, expected) {
t.Fatalf("expected output to contain: %s, but got %s", expected, actual)
}
})
}

@ -410,7 +410,7 @@ func testJSONViewOutputEqualsFull(t *testing.T, output string, want []map[string
delete(gotStruct, "@timestamp")
// Verify the timestamp format
if _, err := time.Parse("2006-01-02T15:04:05.000000Z07:00", timestamp.(string)); err != nil {
if _, err := time.Parse(time.RFC3339, timestamp.(string)); err != nil {
t.Errorf("error parsing timestamp on line %d: %s", i, err)
}
}

Loading…
Cancel
Save