opentofu/internal/configs/parser_config_dir_test.go
Lars Lehtonen ebe331fdd3
internal/configs: deprecate io/ioutil (#333)
Signed-off-by: Lars Lehtonen <lars.lehtonen@gmail.com>
2023-09-08 01:12:25 +02:00

268 lines
7.4 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package configs
import (
"fmt"
"os"
"path/filepath"
"testing"
"github.com/hashicorp/hcl/v2"
)
// TestParseLoadConfigDirSuccess is a simple test that just verifies that
// a number of test configuration directories (in testdata/valid-modules)
// can be parsed without raising any diagnostics.
//
// It also re-tests the individual files in testdata/valid-files as if
// they were single-file modules, to ensure that they can be bundled into
// modules correctly.
//
// This test does not verify that reading these modules produces the correct
// module element contents. More detailed assertions may be made on some subset
// of these configuration files in other tests.
func TestParserLoadConfigDirSuccess(t *testing.T) {
dirs, err := os.ReadDir("testdata/valid-modules")
if err != nil {
t.Fatal(err)
}
for _, info := range dirs {
name := info.Name()
t.Run(name, func(t *testing.T) {
parser := NewParser(nil)
path := filepath.Join("testdata/valid-modules", name)
mod, diags := parser.LoadConfigDir(path)
if len(diags) != 0 && len(mod.ActiveExperiments) != 0 {
// As a special case to reduce churn while we're working
// through experimental features, we'll ignore the warning
// that an experimental feature is active if the module
// intentionally opted in to that feature.
// If you want to explicitly test for the feature warning
// to be generated, consider using testdata/warning-files
// instead.
filterDiags := make(hcl.Diagnostics, 0, len(diags))
for _, diag := range diags {
if diag.Severity != hcl.DiagWarning {
continue
}
match := false
for exp := range mod.ActiveExperiments {
allowedSummary := fmt.Sprintf("Experimental feature %q is active", exp.Keyword())
if diag.Summary == allowedSummary {
match = true
break
}
}
if !match {
filterDiags = append(filterDiags, diag)
}
}
diags = filterDiags
}
if len(diags) != 0 {
t.Errorf("unexpected diagnostics")
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
if mod.SourceDir != path {
t.Errorf("wrong SourceDir value %q; want %s", mod.SourceDir, path)
}
if len(mod.Tests) > 0 {
// We only load tests when requested, and we didn't request this
// time.
t.Errorf("should not have loaded tests, but found %d", len(mod.Tests))
}
})
}
// The individual files in testdata/valid-files should also work
// when loaded as modules.
files, err := os.ReadDir("testdata/valid-files")
if err != nil {
t.Fatal(err)
}
for _, info := range files {
name := info.Name()
t.Run(fmt.Sprintf("%s as module", name), func(t *testing.T) {
src, err := os.ReadFile(filepath.Join("testdata/valid-files", name))
if err != nil {
t.Fatal(err)
}
parser := testParser(map[string]string{
"mod/" + name: string(src),
})
_, diags := parser.LoadConfigDir("mod")
if diags.HasErrors() {
t.Errorf("unexpected error diagnostics")
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
})
}
}
func TestParserLoadConfigDirWithTests(t *testing.T) {
directories := []string{
"testdata/valid-modules/with-tests",
"testdata/valid-modules/with-tests-expect-failures",
"testdata/valid-modules/with-tests-nested",
"testdata/valid-modules/with-tests-very-nested",
"testdata/valid-modules/with-tests-json",
}
for _, directory := range directories {
t.Run(directory, func(t *testing.T) {
testDirectory := DefaultTestDirectory
if directory == "testdata/valid-modules/with-tests-very-nested" {
testDirectory = "very/nested"
}
parser := NewParser(nil)
mod, diags := parser.LoadConfigDirWithTests(directory, testDirectory)
if len(diags) > 0 { // We don't want any warnings or errors.
t.Errorf("unexpected diagnostics")
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
if len(mod.Tests) != 2 {
t.Errorf("incorrect number of test files found: %d", len(mod.Tests))
}
})
}
}
func TestParserLoadConfigDirWithTests_ReturnsWarnings(t *testing.T) {
parser := NewParser(nil)
mod, diags := parser.LoadConfigDirWithTests("testdata/valid-modules/with-tests", "not_real")
if len(diags) != 1 {
t.Errorf("expected exactly 1 diagnostic, but found %d", len(diags))
} else {
if diags[0].Severity != hcl.DiagWarning {
t.Errorf("expected warning severity but found %d", diags[0].Severity)
}
if diags[0].Summary != "Test directory does not exist" {
t.Errorf("expected summary to be \"Test directory does not exist\" but was \"%s\"", diags[0].Summary)
}
if diags[0].Detail != "Requested test directory testdata/valid-modules/with-tests/not_real does not exist." {
t.Errorf("expected detail to be \"Requested test directory testdata/valid-modules/with-tests/not_real does not exist.\" but was \"%s\"", diags[0].Detail)
}
}
// Despite the warning, should still have loaded the tests in the
// configuration directory.
if len(mod.Tests) != 2 {
t.Errorf("incorrect number of test files found: %d", len(mod.Tests))
}
}
// TestParseLoadConfigDirFailure is a simple test that just verifies that
// a number of test configuration directories (in testdata/invalid-modules)
// produce diagnostics when parsed.
//
// It also re-tests the individual files in testdata/invalid-files as if
// they were single-file modules, to ensure that their errors are still
// detected when loading as part of a module.
//
// This test does not verify that reading these modules produces any
// diagnostics in particular. More detailed assertions may be made on some subset
// of these configuration files in other tests.
func TestParserLoadConfigDirFailure(t *testing.T) {
dirs, err := os.ReadDir("testdata/invalid-modules")
if err != nil {
t.Fatal(err)
}
for _, info := range dirs {
name := info.Name()
t.Run(name, func(t *testing.T) {
parser := NewParser(nil)
path := filepath.Join("testdata/invalid-modules", name)
_, diags := parser.LoadConfigDir(path)
if !diags.HasErrors() {
t.Errorf("no errors; want at least one")
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
})
}
// The individual files in testdata/valid-files should also work
// when loaded as modules.
files, err := os.ReadDir("testdata/invalid-files")
if err != nil {
t.Fatal(err)
}
for _, info := range files {
name := info.Name()
t.Run(fmt.Sprintf("%s as module", name), func(t *testing.T) {
src, err := os.ReadFile(filepath.Join("testdata/invalid-files", name))
if err != nil {
t.Fatal(err)
}
parser := testParser(map[string]string{
"mod/" + name: string(src),
})
_, diags := parser.LoadConfigDir("mod")
if !diags.HasErrors() {
t.Errorf("no errors; want at least one")
for _, diag := range diags {
t.Logf("- %s", diag)
}
}
})
}
}
func TestIsEmptyDir(t *testing.T) {
val, err := IsEmptyDir(filepath.Join("testdata", "valid-files"))
if err != nil {
t.Fatalf("err: %s", err)
}
if val {
t.Fatal("should not be empty")
}
}
func TestIsEmptyDir_noExist(t *testing.T) {
val, err := IsEmptyDir(filepath.Join("testdata", "nopenopenope"))
if err != nil {
t.Fatalf("err: %s", err)
}
if !val {
t.Fatal("should be empty")
}
}
func TestIsEmptyDir_noConfigs(t *testing.T) {
val, err := IsEmptyDir(filepath.Join("testdata", "dir-empty"))
if err != nil {
t.Fatalf("err: %s", err)
}
if !val {
t.Fatal("should be empty")
}
}