From b2a90cf5878541d6b8a8e47e0abce6a3881e662e Mon Sep 17 00:00:00 2001 From: Mark DeCrane Date: Mon, 18 Nov 2024 16:21:03 -0500 Subject: [PATCH] Testing updates --- internal/command/modules_test.go | 56 +++++++-- .../.terraform/modules/modules.json | 29 +++++ .../modules-nested-dependencies/main.tf | 7 ++ .../mods/other/main.tf | 5 + .../mods/test/main.tf | 3 + .../mods/test/test2/main.tf | 3 + .../mods/test/test2/test3/main.tf | 5 + .../terraform.tfstate | 0 internal/moduleref/resolver_test.go | 111 +++++++++++++++--- 9 files changed, 189 insertions(+), 30 deletions(-) create mode 100644 internal/command/testdata/modules-nested-dependencies/.terraform/modules/modules.json create mode 100644 internal/command/testdata/modules-nested-dependencies/main.tf create mode 100644 internal/command/testdata/modules-nested-dependencies/mods/other/main.tf create mode 100644 internal/command/testdata/modules-nested-dependencies/mods/test/main.tf create mode 100644 internal/command/testdata/modules-nested-dependencies/mods/test/test2/main.tf create mode 100644 internal/command/testdata/modules-nested-dependencies/mods/test/test2/test3/main.tf create mode 100644 internal/command/testdata/modules-nested-dependencies/terraform.tfstate diff --git a/internal/command/modules_test.go b/internal/command/modules_test.go index 702cf61309..ec30972d16 100644 --- a/internal/command/modules_test.go +++ b/internal/command/modules_test.go @@ -11,6 +11,8 @@ import ( "strings" "testing" + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/cli" "github.com/hashicorp/terraform/internal/moduleref" ) @@ -18,8 +20,9 @@ import ( func TestModules_noJsonFlag(t *testing.T) { dir := t.TempDir() os.MkdirAll(dir, 0755) + testCopyDir(t, testFixturePath("modules-nested-dependencies"), dir) ui := new(cli.MockUi) - view, _ := testView(t) + view, done := testView(t) defer testChdir(t, dir)() cmd := &ModulesCommand{ @@ -32,24 +35,51 @@ func TestModules_noJsonFlag(t *testing.T) { args := []string{} code := cmd.Run(args) - if code == 0 { - t.Fatal("expected an non zero exit status\n") + if code != 0 { + t.Fatalf("Got a non-zero exit code: %d\n", code) } - output := ui.ErrorWriter.String() - if !strings.Contains(output, "The `terraform modules` command requires the `-json` flag.\n") { - t.Fatal("expected an error message about requiring -json flag.\n") + actual := done(t).All() + + for _, part := range expectedOutputHuman { + if !strings.Contains(actual, part) { + t.Fatalf("unexpected output: %s\n", part) + } } +} - if !strings.Contains(output, modulesCommandHelp) { - t.Fatal("expected the modules command help to be displayed\n") +func TestModules_noJsonFlag_noModules(t *testing.T) { + dir := t.TempDir() + os.MkdirAll(dir, 0755) + ui := new(cli.MockUi) + view, done := testView(t) + defer testChdir(t, dir)() + + cmd := &ModulesCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + View: view, + }, + } + + args := []string{} + code := cmd.Run(args) + if code != 0 { + t.Fatalf("Got a non-zero exit code: %d\n", code) + } + + actual := done(t).All() + + if diff := cmp.Diff("No modules found in configuration.\n", actual); diff != "" { + t.Fatalf("unexpected output (-want +got):\n%s", diff) } } func TestModules_fullCmd(t *testing.T) { dir := t.TempDir() os.MkdirAll(dir, 0755) - testCopyDir(t, testFixturePath("modules"), dir) + testCopyDir(t, testFixturePath("modules-nested-dependencies"), dir) ui := new(cli.MockUi) view, done := testView(t) @@ -70,7 +100,7 @@ func TestModules_fullCmd(t *testing.T) { } output := done(t).All() - compareJSONOutput(t, output, expectedOutput) + compareJSONOutput(t, output, expectedOutputJSON) } func TestModules_fullCmd_unreferencedEntries(t *testing.T) { @@ -96,7 +126,7 @@ func TestModules_fullCmd_unreferencedEntries(t *testing.T) { t.Fatalf("Got a non-zero exit code: %d\n", code) } output := done(t).All() - compareJSONOutput(t, output, expectedOutput) + compareJSONOutput(t, output, expectedOutputJSON) } func TestModules_uninstalledModules(t *testing.T) { @@ -154,4 +184,6 @@ func compareJSONOutput(t *testing.T, got string, want string) { } } -var expectedOutput = `{"format_version":"1.0","modules":[{"key":"child","source":"./child","version":""},{"key":"count_child","source":"./child","version":""}]}` +var expectedOutputJSON = `{"format_version":"1.0","modules":[{"key":"test","source":"./mods/test","version":""},{"key":"test2","source":"./test2","version":""},{"key":"test3","source":"./test3","version":""},{"key":"other","source":"./mods/other","version":""}]}` + +var expectedOutputHuman = []string{"── \"other\"[./mods/other]", "── \"test\"[./mods/test]\n └── \"test2\"[./test2]\n └── \"test3\"[./test3]"} diff --git a/internal/command/testdata/modules-nested-dependencies/.terraform/modules/modules.json b/internal/command/testdata/modules-nested-dependencies/.terraform/modules/modules.json new file mode 100644 index 0000000000..a4f71c7b2b --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/.terraform/modules/modules.json @@ -0,0 +1,29 @@ +{ + "Modules": [ + { + "Key": "", + "Source": "", + "Dir": "." + }, + { + "Key": "other", + "Source": "./mods/other", + "Dir": "mods/other" + }, + { + "Key": "test", + "Source": "./mods/test", + "Dir": "mods/test" + }, + { + "Key": "test.test2", + "Source": "./test2", + "Dir": "mods/test/test2" + }, + { + "Key": "test.test2.test3", + "Source": "./test3", + "Dir": "mods/test/test2/test3" + } + ] +} \ No newline at end of file diff --git a/internal/command/testdata/modules-nested-dependencies/main.tf b/internal/command/testdata/modules-nested-dependencies/main.tf new file mode 100644 index 0000000000..77bf763519 --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/main.tf @@ -0,0 +1,7 @@ +module "test" { + source = "./mods/test" +} + +module "other" { + source = "./mods/other" +} diff --git a/internal/command/testdata/modules-nested-dependencies/mods/other/main.tf b/internal/command/testdata/modules-nested-dependencies/mods/other/main.tf new file mode 100644 index 0000000000..f059e25f9e --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/mods/other/main.tf @@ -0,0 +1,5 @@ +resource "test_instance" "test" { +} +output "myoutput" { + value = "bar" +} diff --git a/internal/command/testdata/modules-nested-dependencies/mods/test/main.tf b/internal/command/testdata/modules-nested-dependencies/mods/test/main.tf new file mode 100644 index 0000000000..9e17562a61 --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/mods/test/main.tf @@ -0,0 +1,3 @@ +module "test2" { + source = "./test2" +} diff --git a/internal/command/testdata/modules-nested-dependencies/mods/test/test2/main.tf b/internal/command/testdata/modules-nested-dependencies/mods/test/test2/main.tf new file mode 100644 index 0000000000..ecbfa4be19 --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/mods/test/test2/main.tf @@ -0,0 +1,3 @@ +module "test3" { + source = "./test3" +} diff --git a/internal/command/testdata/modules-nested-dependencies/mods/test/test2/test3/main.tf b/internal/command/testdata/modules-nested-dependencies/mods/test/test2/test3/main.tf new file mode 100644 index 0000000000..f059e25f9e --- /dev/null +++ b/internal/command/testdata/modules-nested-dependencies/mods/test/test2/test3/main.tf @@ -0,0 +1,5 @@ +resource "test_instance" "test" { +} +output "myoutput" { + value = "bar" +} diff --git a/internal/command/testdata/modules-nested-dependencies/terraform.tfstate b/internal/command/testdata/modules-nested-dependencies/terraform.tfstate new file mode 100644 index 0000000000..e69de29bb2 diff --git a/internal/moduleref/resolver_test.go b/internal/moduleref/resolver_test.go index 93ec551192..eaa9f0a925 100644 --- a/internal/moduleref/resolver_test.go +++ b/internal/moduleref/resolver_test.go @@ -19,6 +19,18 @@ func TestResolver_Resolve(t *testing.T) { }, } + cfg.Children = map[string]*configs.Config{ + "foo": &configs.Config{ + Path: addrs.Module{"foo"}, + Parent: cfg, + Children: make(map[string]*configs.Config), + SourceAddr: addrs.ModuleSourceLocal("./foo"), + Module: &configs.Module{ + ModuleCalls: map[string]*configs.ModuleCall{}, + }, + }, + } + manifest := modsdir.Manifest{ "foo": modsdir.Record{ Key: "foo", @@ -48,12 +60,27 @@ func TestResolver_ResolveNestedChildren(t *testing.T) { cfg.Children = make(map[string]*configs.Config) cfg.Module = &configs.Module{ ModuleCalls: map[string]*configs.ModuleCall{ - "foo": {Name: "foo"}, + "foo": {Name: "foo"}, + "fellowship": {Name: "fellowship"}, + }, + } + + cfg.Children["foo"] = &configs.Config{ + Path: addrs.Module{"foo"}, + Parent: cfg, + SourceAddr: addrs.ModuleSourceLocal("./foo"), + Children: make(map[string]*configs.Config), + Module: &configs.Module{ + ModuleCalls: map[string]*configs.ModuleCall{}, }, } - childCfg := &configs.Config{ - Path: addrs.Module{"fellowship"}, + childCfgFellowship := &configs.Config{ + Path: addrs.Module{"fellowship"}, + Parent: cfg, + SourceAddr: addrs.ModuleSourceRemote{ + Package: addrs.ModulePackage("fellowship"), + }, Children: make(map[string]*configs.Config), Module: &configs.Module{ ModuleCalls: map[string]*configs.ModuleCall{ @@ -61,9 +88,26 @@ func TestResolver_ResolveNestedChildren(t *testing.T) { }, }, } + cfg.Children["fellowship"] = childCfgFellowship + + childCfgFellowship.Children["frodo"] = &configs.Config{ + Path: addrs.Module{"fellowship", "frodo"}, + Parent: childCfgFellowship, + SourceAddr: addrs.ModuleSourceRemote{ + Package: addrs.ModulePackage("fellowship/frodo"), + }, + Children: make(map[string]*configs.Config), + Module: &configs.Module{ + ModuleCalls: map[string]*configs.ModuleCall{}, + }, + } - childCfg2 := &configs.Config{ - Path: addrs.Module{"fellowship", "weapons"}, + childCfgWeapons := &configs.Config{ + Path: addrs.Module{"fellowship", "weapons"}, + Parent: childCfgFellowship, + SourceAddr: addrs.ModuleSourceRemote{ + Package: addrs.ModulePackage("fellowship/weapons"), + }, Children: make(map[string]*configs.Config), Module: &configs.Module{ ModuleCalls: map[string]*configs.ModuleCall{ @@ -71,9 +115,19 @@ func TestResolver_ResolveNestedChildren(t *testing.T) { }, }, } + childCfgFellowship.Children["weapons"] = childCfgWeapons - cfg.Children["fellowship"] = childCfg - childCfg.Children["weapons"] = childCfg2 + childCfgWeapons.Children["sting"] = &configs.Config{ + Path: addrs.Module{"fellowship", "weapons", "sting"}, + Parent: childCfgWeapons, + SourceAddr: addrs.ModuleSourceRemote{ + Package: addrs.ModulePackage("fellowship/weapons/sting"), + }, + Children: make(map[string]*configs.Config), + Module: &configs.Module{ + ModuleCalls: map[string]*configs.ModuleCall{}, + }, + } manifest := modsdir.Manifest{ "foo": modsdir.Record{ @@ -84,10 +138,18 @@ func TestResolver_ResolveNestedChildren(t *testing.T) { Key: "bar", SourceAddr: "./bar", }, + "fellowship": modsdir.Record{ + Key: "fellowship", + SourceAddr: "fellowship", + }, "fellowship.frodo": modsdir.Record{ Key: "fellowship.frodo", SourceAddr: "fellowship/frodo", }, + "fellowship.weapons": modsdir.Record{ + Key: "fellowship.weapons", + SourceAddr: "fellowship/weapons", + }, "fellowship.weapons.sting": modsdir.Record{ Key: "fellowship.weapons.sting", SourceAddr: "fellowship/weapons/sting", @@ -100,23 +162,36 @@ func TestResolver_ResolveNestedChildren(t *testing.T) { resolver := NewResolver(manifest) result := resolver.Resolve(cfg) - - if len(result.Records) != 3 { - t.Fatalf("expected the resolved number of entries to equal 3, got: %d", len(result.Records)) + recordsCount, sources := countAndListSources(result.Records) + if recordsCount != 5 { + t.Fatalf("expected the resolved number of entries to equal 5, got: %d", recordsCount) } assertions := map[string]bool{ - "foo": true, - "bar": false, - "fellowship.frodo": true, - "fellowship.weapons.sting": true, - "fellowship.weapons.anduril": false, + "./foo": true, + "./bar": false, + "fellowship": true, + "fellowship/frodo": true, + "fellowship/weapons": true, + "fellowship/weapons/sting": true, + "fellowship/weapons/anduril": false, } - for _, record := range result.Records { - referenced, ok := assertions[record.Key] + for _, source := range sources { + referenced, ok := assertions[source] if !ok || !referenced { - t.Fatalf("expected to find referenced entry with key: %s", record.Key) + t.Fatalf("expected to find referenced entry with key: %s", source) } } } + +func countAndListSources(records []*Record) (count int, sources []string) { + for _, record := range records { + sources = append(sources, record.Source.String()) + count++ + childCount, childSources := countAndListSources(record.Children) + count += childCount + sources = append(sources, childSources...) + } + return +}