blob: 431105fa5deb7eed503cc5e62223b0dabd99bc1d [file] [log] [blame] [edit]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package command
import (
"encoding/json"
"os"
"reflect"
"runtime"
"sort"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/cli"
"github.com/hashicorp/terraform/internal/moduleref"
)
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, 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()
expectedOutputHuman := `
Modules declared by configuration:
.
├── "other"[./mods/other]
└── "test"[./mods/test]
└── "test2"[./test2]
└── "test3"[./test3]
`
if runtime.GOOS == "windows" {
expectedOutputHuman = `
Modules declared by configuration:
.
├── "other"[.\mods\other]
└── "test"[.\mods\test]
└── "test2"[.\test2]
└── "test3"[.\test3]
`
}
if diff := cmp.Diff(expectedOutputHuman, actual); diff != "" {
t.Fatalf("unexpected output:\n%s\n", diff)
}
}
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-nested-dependencies"), dir)
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{"-json"}
code := cmd.Run(args)
if code != 0 {
t.Fatalf("Got a non-zero exit code: %d\n", code)
}
output := done(t).All()
compareJSONOutput(t, output, expectedOutputJSON)
}
func TestModules_fullCmd_unreferencedEntries(t *testing.T) {
dir := t.TempDir()
os.MkdirAll(dir, 0755)
testCopyDir(t, testFixturePath("modules-unreferenced-entries"), dir)
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{"-json"}
code := cmd.Run(args)
if code != 0 {
t.Fatalf("Got a non-zero exit code: %d\n", code)
}
output := done(t).All()
compareJSONOutput(t, output, expectedOutputJSON)
}
func TestModules_uninstalledModules(t *testing.T) {
dir := t.TempDir()
os.MkdirAll(dir, 0755)
testCopyDir(t, testFixturePath("modules-uninstalled-entries"), dir)
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{"-json"}
code := cmd.Run(args)
if code == 0 {
t.Fatal("Expected a non-zero exit code\n")
}
output := done(t).All()
if !strings.Contains(output, "Module not installed") {
t.Fatalf("expected to see a `not installed` error message: %s\n", output)
}
if !strings.Contains(output, `Run "terraform init"`) {
t.Fatalf("expected error message to ask user to run terraform init: %s\n", output)
}
}
func compareJSONOutput(t *testing.T, got string, want string) {
var expected, actual moduleref.Manifest
if err := json.Unmarshal([]byte(got), &actual); err != nil {
t.Fatalf("Failed to unmarshal actual JSON: %v", err)
}
if err := json.Unmarshal([]byte(want), &expected); err != nil {
t.Fatalf("Failed to unmarshal expected JSON: %v", err)
}
sort.Slice(actual.Records, func(i, j int) bool {
return actual.Records[i].Key < actual.Records[j].Key
})
sort.Slice(expected.Records, func(i, j int) bool {
return expected.Records[i].Key < expected.Records[j].Key
})
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("unexpected output, got: %s\n, want:%s\n", got, want)
}
}
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":""}]}`