From 2d35daef4e6aa76e72cac1f7b32b92fda07ac27e Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 8 Oct 2025 16:03:38 -0400 Subject: [PATCH 1/6] Update ConfigDirectory tests to tolerate a subdirectory --- internal/teststep/directory_test.go | 57 ++++++++++++------- .../teststep/testdata/random/module/main.tf | 0 2 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 internal/teststep/testdata/random/module/main.tf diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index cb88d214f..46906a366 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -473,27 +473,31 @@ func TestConfigurationDirectory_Write(t *testing.T) { dirEntries, err := os.ReadDir(testCase.configDirectory.directory) if err != nil { - t.Errorf("error reading directory: %s", err) + t.Fatalf("error reading directory: %s", err) } tempDirEntries, err := os.ReadDir(tempDir) if err != nil { - t.Errorf("error reading temp directory: %s", err) + t.Fatalf("error reading temp directory: %s", err) } - if len(dirEntries) != len(tempDirEntries) { - t.Errorf("expected %d dir entries, got %d dir entries", dirEntries, tempDirEntries) + files := filesOnly(dirEntries) + tempDirFiles := filesOnly(tempDirEntries) + + if len(tempDirFiles)-len(files) != 0 { + t.Errorf("expected %d files, got %d files", len(files), tempDirFiles) } - for k, v := range dirEntries { - dirEntryInfo, err := v.Info() + for i, file := range files { + dirEntryInfo, err := file.Info() if err != nil { t.Errorf("error getting dir entry info: %s", err) } - tempDirEntryInfo, err := tempDirEntries[k].Info() + tempDirEntry := tempDirFiles[i] + tempDirEntryInfo, err := tempDirEntry.Info() if err != nil { t.Errorf("error getting temp dir entry info: %s", err) @@ -572,27 +576,30 @@ func TestConfigurationDirectory_Write_AbsolutePath(t *testing.T) { dirEntries, err := os.ReadDir(testCase.configDirectory.directory) if err != nil { - t.Errorf("error reading directory: %s", err) + t.Fatalf("error reading directory: %s", err) } tempDirEntries, err := os.ReadDir(tempDir) if err != nil { - t.Errorf("error reading temp directory: %s", err) + t.Fatalf("error reading temp directory: %s", err) } - if len(dirEntries) != len(tempDirEntries) { - t.Errorf("expected %d dir entries, got %d dir entries", dirEntries, tempDirEntries) + files := filesOnly(dirEntries) + tempDirFiles := filesOnly(tempDirEntries) + + if len(tempDirFiles)-len(files) != 0 { + t.Errorf("expected %d files, got %d files", len(files), tempDirFiles) } - for k, v := range dirEntries { - dirEntryInfo, err := v.Info() + for i, file := range files { + dirEntryInfo, err := file.Info() if err != nil { t.Errorf("error getting dir entry info: %s", err) } - tempDirEntryInfo, err := tempDirEntries[k].Info() + tempDirEntryInfo, err := tempDirFiles[i].Info() if err != nil { t.Errorf("error getting temp dir entry info: %s", err) @@ -641,17 +648,19 @@ func TestConfigurationDirectory_Write_WithAppendedConfig(t *testing.T) { } tempDirEntries, err := os.ReadDir(tempDir) - if err != nil { t.Errorf("error reading temp directory: %s", err) } - if len(tempDirEntries)-len(dirEntries) != 1 { - t.Errorf("expected %d dir entries, got %d dir entries", len(dirEntries)+1, tempDirEntries) + files := filesOnly(dirEntries) + tempDirFiles := filesOnly(tempDirEntries) + + if len(tempDirFiles)-len(files) != 1 { + t.Errorf("expected %d files, got %d files", len(files)+1, tempDirFiles) } - for _, entry := range dirEntries { - filename := entry.Name() + for _, file := range files { + filename := file.Name() expectedContent, err := os.ReadFile(filepath.Join(testCase.configDirectory.directory, filename)) if err != nil { t.Errorf("error reading file from config directory %s: %s", filename, err) @@ -697,3 +706,13 @@ var fileInfoComparer = cmp.Comparer(func(x, y os.FileInfo) bool { return true }) + +func filesOnly(entries []os.DirEntry) []os.DirEntry { + files := []os.DirEntry{} + for _, e := range entries { + if !e.IsDir() { + files = append(files, e) + } + } + return files +} diff --git a/internal/teststep/testdata/random/module/main.tf b/internal/teststep/testdata/random/module/main.tf new file mode 100644 index 000000000..e69de29bb From 227cd65023b649569b78b74fb440608cb6b4744f Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 8 Oct 2025 18:20:35 -0400 Subject: [PATCH 2/6] A failing test for a recursive configdirectory copy --- internal/teststep/directory.go | 1 + internal/teststep/directory_test.go | 91 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 1afc45a2d..0a15ac4d2 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -15,6 +15,7 @@ var _ Config = configurationDirectory{} type configurationDirectory struct { directory string + recursive bool // appendedConfig is a map of filenames to content appendedConfig map[string]string diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index 46906a366..161a6dd08 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -5,9 +5,11 @@ package teststep import ( "context" + "io/fs" "os" "path/filepath" "regexp" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -512,6 +514,76 @@ func TestConfigurationDirectory_Write(t *testing.T) { } } +func TestConfigurationDirectory_Write_Recursive(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + configDirectory configurationDirectory + expectedError *regexp.Regexp + }{ + "not-directory": { + configDirectory: configurationDirectory{ + directory: "testdata/empty_file/main.tf", + }, + expectedError: regexp.MustCompile(`.*not a directory`), + }, + "no-config": { + configDirectory: configurationDirectory{ + directory: "testdata/empty_dir", + }, + }, + "dir-single-file": { + configDirectory: configurationDirectory{ + directory: "testdata/random", + }, + }, + "dir-multiple-files": { + configDirectory: configurationDirectory{ + directory: "testdata/random_multiple_files", + }, + }, + "dir-recursive": { + configDirectory: configurationDirectory{ + directory: "testdata/recursive", + recursive: true, + }, + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + tempDir := t.TempDir() + + err := testCase.configDirectory.Write(context.Background(), tempDir) + if testCase.expectedError == nil && err != nil { + t.Errorf("unexpected error %s", err) + } + + if testCase.expectedError != nil && err == nil { + t.Errorf("expected error but got none") + } + + if testCase.expectedError != nil && err != nil { + if !testCase.expectedError.MatchString(err.Error()) { + t.Errorf("expected error %s, got error %s", testCase.expectedError.String(), err) + } + } + + if err == nil { + filepaths := readDirectory(t, testCase.configDirectory.directory) + tempDirEntries := readDirectory(t, tempDir) + + diff := cmp.Diff(filepaths, tempDirEntries) + if len(diff) != 0 { + t.Fatalf("expected filepaths do not match actual filepaths: %v", diff) + } + } + }) + } +} + func TestConfigurationDirectory_Write_AbsolutePath(t *testing.T) { t.Parallel() @@ -716,3 +788,22 @@ func filesOnly(entries []os.DirEntry) []os.DirEntry { } return files } + +func readDirectory(t *testing.T, root string) []string { + t.Helper() + + contents := []string{} + + err := filepath.WalkDir(root, func(path string, entry fs.DirEntry, err error) error { + if !entry.IsDir() { + contents = append(contents, strings.TrimPrefix(path, root)) + } + return nil + }) + if err != nil { + t.Fatalf("readDirectory: WalkDir: %v", err) + + } + + return contents +} From 038635ceacdebdc48e9b843fd1e41b7886ef5d42 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 8 Oct 2025 18:20:35 -0400 Subject: [PATCH 3/6] A failing test for a recursive configdirectory copy --- internal/teststep/directory_test.go | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/internal/teststep/directory_test.go b/internal/teststep/directory_test.go index 161a6dd08..a4be482f6 100644 --- a/internal/teststep/directory_test.go +++ b/internal/teststep/directory_test.go @@ -521,27 +521,6 @@ func TestConfigurationDirectory_Write_Recursive(t *testing.T) { configDirectory configurationDirectory expectedError *regexp.Regexp }{ - "not-directory": { - configDirectory: configurationDirectory{ - directory: "testdata/empty_file/main.tf", - }, - expectedError: regexp.MustCompile(`.*not a directory`), - }, - "no-config": { - configDirectory: configurationDirectory{ - directory: "testdata/empty_dir", - }, - }, - "dir-single-file": { - configDirectory: configurationDirectory{ - directory: "testdata/random", - }, - }, - "dir-multiple-files": { - configDirectory: configurationDirectory{ - directory: "testdata/random_multiple_files", - }, - }, "dir-recursive": { configDirectory: configurationDirectory{ directory: "testdata/recursive", From 0a801d49c712be841fe969ad5caf605bdb8bb443 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Wed, 8 Oct 2025 18:45:08 -0400 Subject: [PATCH 4/6] A passing test --- internal/teststep/config.go | 23 ++++++++++++++++++++++- internal/teststep/directory.go | 13 +++++++++---- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/internal/teststep/config.go b/internal/teststep/config.go index 5df477f08..85237e4fe 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -165,6 +165,27 @@ func copyFiles(path string, dstPath string) error { return nil } +// copyFilesRecursively accepts a path to a directory and a destination. +func copyFilesRecursively(rootPath string, dstPath string) error { + return filepath.WalkDir(rootPath, func(path string, d os.DirEntry, err error) error { + sortaRelativePath := strings.TrimPrefix(path, rootPath) + newPath := filepath.Join(dstPath, sortaRelativePath) + + if len(sortaRelativePath) == 0 { + return nil + } + + if d.IsDir() { + return os.Mkdir(newPath, 0700) + } else { + newDir, _ := filepath.Split(newPath) + _, err := copyFile(path, newDir) + return err + + } + }) +} + // copyFile accepts a path to a file and a destination, // copying the file from path to destination. func copyFile(path string, dstPath string) (string, error) { @@ -179,7 +200,7 @@ func copyFile(path string, dstPath string) (string, error) { di, err := os.Stat(dstPath) if err != nil { - return "", err + return "", fmt.Errorf("copyFile: os.Stat: %v", err) } if di.IsDir() { diff --git a/internal/teststep/directory.go b/internal/teststep/directory.go index 0a15ac4d2..cee38b97d 100644 --- a/internal/teststep/directory.go +++ b/internal/teststep/directory.go @@ -94,12 +94,17 @@ func (c configurationDirectory) Write(ctx context.Context, dest string) error { configDirectory = filepath.Join(pwd, configDirectory) } - err := copyFiles(configDirectory, dest) - if err != nil { - return err + if c.recursive { + if err := copyFilesRecursively(configDirectory, dest); err != nil { + return err + } + } else { + if err := copyFiles(configDirectory, dest); err != nil { + return err + } } - err = c.writeAppendedConfig(dest) + err := c.writeAppendedConfig(dest) if err != nil { return err } From d168e90809bf8ee62a585d14829f94cbd9f63d36 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Thu, 9 Oct 2025 07:32:52 -0400 Subject: [PATCH 5/6] Add testdata --- internal/teststep/testdata/recursive/module/main.tf | 0 internal/teststep/testdata/recursive/vars.tf | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 internal/teststep/testdata/recursive/module/main.tf create mode 100644 internal/teststep/testdata/recursive/vars.tf diff --git a/internal/teststep/testdata/recursive/module/main.tf b/internal/teststep/testdata/recursive/module/main.tf new file mode 100644 index 000000000..e69de29bb diff --git a/internal/teststep/testdata/recursive/vars.tf b/internal/teststep/testdata/recursive/vars.tf new file mode 100644 index 000000000..e69de29bb From c40a364fb54ad5d26ca3ba38703a0689530a26c6 Mon Sep 17 00:00:00 2001 From: Baraa Basata Date: Tue, 28 Oct 2025 08:05:09 -0400 Subject: [PATCH 6/6] tidy --- internal/teststep/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/teststep/config.go b/internal/teststep/config.go index 85237e4fe..02fc37e6a 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -167,7 +167,7 @@ func copyFiles(path string, dstPath string) error { // copyFilesRecursively accepts a path to a directory and a destination. func copyFilesRecursively(rootPath string, dstPath string) error { - return filepath.WalkDir(rootPath, func(path string, d os.DirEntry, err error) error { + return filepath.WalkDir(rootPath, func(path string, entry os.DirEntry, err error) error { sortaRelativePath := strings.TrimPrefix(path, rootPath) newPath := filepath.Join(dstPath, sortaRelativePath) @@ -175,7 +175,7 @@ func copyFilesRecursively(rootPath string, dstPath string) error { return nil } - if d.IsDir() { + if entry.IsDir() { return os.Mkdir(newPath, 0700) } else { newDir, _ := filepath.Split(newPath)