Skip to content

Commit 2bb8b9e

Browse files
committed
updates
1 parent 24ed447 commit 2bb8b9e

File tree

3 files changed

+225
-9
lines changed

3 files changed

+225
-9
lines changed

cmd/root_test.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,8 @@ func TestNoColorLog(t *testing.T) {
3030
t.Fatalf("Failed to get current working directory: %v", err)
3131
}
3232

33-
// Change back to original directory IMMEDIATELY to ensure paths work.
34-
// Previous tests may have left us in a temp directory.
35-
if err := os.Chdir(originalWd); err != nil {
36-
t.Fatalf("Failed to restore working directory: %v", err)
37-
}
38-
39-
t.Cleanup(func() {
40-
_ = os.Chdir(originalWd)
41-
})
33+
// Change back to original directory and automatically restore when test ends.
34+
t.Chdir(originalWd)
4235

4336
// Ensure ATMOS_CHDIR is not set BEFORE anything else.
4437
// Previous tests may have set it, and we need to clear it before RootCmd.Execute().

pkg/config/load_config_test.go

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/stretchr/testify/assert"
99
"github.com/stretchr/testify/require"
1010

11+
errUtils "github.com/cloudposse/atmos/errors"
1112
"github.com/cloudposse/atmos/pkg/schema"
1213
)
1314

@@ -175,3 +176,220 @@ func TestConnectPaths_WindowsPaths(t *testing.T) {
175176
})
176177
}
177178
}
179+
180+
// TestValidatedIsFiles_EdgeCases tests edge cases for file validation.
181+
func TestValidatedIsFiles_EdgeCases(t *testing.T) {
182+
tmpDir := t.TempDir()
183+
validFile := filepath.Join(tmpDir, "test.yaml")
184+
require.NoError(t, os.WriteFile(validFile, []byte("test: value"), 0o644))
185+
186+
tests := []struct {
187+
name string
188+
files []string
189+
wantError string
190+
checkErr error
191+
}{
192+
{
193+
name: "empty file path",
194+
files: []string{""},
195+
wantError: "requires a non-empty file path",
196+
checkErr: errUtils.ErrEmptyConfigFile,
197+
},
198+
{
199+
name: "directory instead of file",
200+
files: []string{tmpDir},
201+
wantError: "",
202+
checkErr: errUtils.ErrExpectedFile,
203+
},
204+
{
205+
name: "multiple files with one invalid",
206+
files: []string{validFile, ""},
207+
wantError: "requires a non-empty file path",
208+
checkErr: errUtils.ErrEmptyConfigFile,
209+
},
210+
}
211+
212+
for _, tt := range tests {
213+
t.Run(tt.name, func(t *testing.T) {
214+
err := validatedIsFiles(tt.files)
215+
assert.Error(t, err)
216+
if tt.wantError != "" {
217+
assert.Contains(t, err.Error(), tt.wantError)
218+
}
219+
if tt.checkErr != nil {
220+
assert.ErrorIs(t, err, tt.checkErr)
221+
}
222+
})
223+
}
224+
}
225+
226+
// TestValidatedIsDirs_EdgeCases tests edge cases for directory validation.
227+
func TestValidatedIsDirs_EdgeCases(t *testing.T) {
228+
tmpDir := t.TempDir()
229+
validDir := filepath.Join(tmpDir, "valid")
230+
require.NoError(t, os.Mkdir(validDir, 0o755))
231+
232+
testFile := filepath.Join(tmpDir, "file.txt")
233+
require.NoError(t, os.WriteFile(testFile, []byte("test"), 0o644))
234+
235+
tests := []struct {
236+
name string
237+
dirs []string
238+
wantError string
239+
checkErr error
240+
}{
241+
{
242+
name: "empty directory path",
243+
dirs: []string{""},
244+
wantError: "requires a non-empty directory path",
245+
checkErr: errUtils.ErrEmptyConfigPath,
246+
},
247+
{
248+
name: "file instead of directory",
249+
dirs: []string{testFile},
250+
wantError: "requires a directory but found a file",
251+
checkErr: errUtils.ErrAtmosDirConfigNotFound,
252+
},
253+
{
254+
name: "non-existent directory",
255+
dirs: []string{filepath.Join(tmpDir, "nonexistent")},
256+
wantError: "does not exist",
257+
checkErr: errUtils.ErrAtmosDirConfigNotFound,
258+
},
259+
{
260+
name: "multiple dirs with one invalid",
261+
dirs: []string{validDir, ""},
262+
wantError: "requires a non-empty directory path",
263+
checkErr: errUtils.ErrEmptyConfigPath,
264+
},
265+
}
266+
267+
for _, tt := range tests {
268+
t.Run(tt.name, func(t *testing.T) {
269+
err := validatedIsDirs(tt.dirs)
270+
assert.Error(t, err)
271+
if tt.wantError != "" {
272+
assert.Contains(t, err.Error(), tt.wantError)
273+
}
274+
if tt.checkErr != nil {
275+
assert.ErrorIs(t, err, tt.checkErr)
276+
}
277+
})
278+
}
279+
}
280+
281+
// TestMergeConfigFromDirectories_ConfigFileVariants tests finding both atmos.yaml and .atmos.yaml.
282+
func TestMergeConfigFromDirectories_ConfigFileVariants(t *testing.T) {
283+
tmpDir := t.TempDir()
284+
285+
// Directory with atmos.yaml
286+
dir1 := filepath.Join(tmpDir, "dir1")
287+
require.NoError(t, os.Mkdir(dir1, 0o755))
288+
require.NoError(t, os.WriteFile(
289+
filepath.Join(dir1, "atmos.yaml"),
290+
[]byte("base_path: /test1"),
291+
0o644,
292+
))
293+
294+
// Directory with .atmos.yaml
295+
dir2 := filepath.Join(tmpDir, "dir2")
296+
require.NoError(t, os.Mkdir(dir2, 0o755))
297+
require.NoError(t, os.WriteFile(
298+
filepath.Join(dir2, ".atmos.yaml"),
299+
[]byte("base_path: /test2"),
300+
0o644,
301+
))
302+
303+
// Directory with no config file
304+
emptyDir := filepath.Join(tmpDir, "empty")
305+
require.NoError(t, os.Mkdir(emptyDir, 0o755))
306+
307+
tests := []struct {
308+
name string
309+
dirs []string
310+
expectError bool
311+
expectedDirs int
312+
}{
313+
{
314+
name: "finds atmos.yaml",
315+
dirs: []string{dir1},
316+
expectError: false,
317+
expectedDirs: 1,
318+
},
319+
{
320+
name: "finds .atmos.yaml",
321+
dirs: []string{dir2},
322+
expectError: false,
323+
expectedDirs: 1,
324+
},
325+
{
326+
name: "finds both variants in different directories",
327+
dirs: []string{dir1, dir2},
328+
expectError: false,
329+
expectedDirs: 2,
330+
},
331+
{
332+
name: "fails for directory without config",
333+
dirs: []string{emptyDir},
334+
expectError: true,
335+
},
336+
}
337+
338+
for _, tt := range tests {
339+
t.Run(tt.name, func(t *testing.T) {
340+
configInfo := schema.ConfigAndStacksInfo{
341+
AtmosConfigDirsFromArg: tt.dirs,
342+
}
343+
344+
_, err := InitCliConfig(configInfo, false)
345+
346+
if tt.expectError {
347+
assert.Error(t, err)
348+
} else {
349+
assert.NoError(t, err)
350+
}
351+
})
352+
}
353+
}
354+
355+
// TestLoadConfigFromCLIArgs_ErrorPaths tests error paths in config loading.
356+
func TestLoadConfigFromCLIArgs_ErrorPaths(t *testing.T) {
357+
tmpDir := t.TempDir()
358+
359+
// Create invalid YAML file
360+
invalidYaml := filepath.Join(tmpDir, "invalid.yaml")
361+
require.NoError(t, os.WriteFile(invalidYaml, []byte("invalid: [unclosed"), 0o644))
362+
363+
tests := []struct {
364+
name string
365+
files []string
366+
dirs []string
367+
expectError bool
368+
description string
369+
}{
370+
{
371+
name: "invalid YAML syntax",
372+
files: []string{invalidYaml},
373+
dirs: []string{},
374+
expectError: true,
375+
description: "Should fail for invalid YAML syntax",
376+
},
377+
}
378+
379+
for _, tt := range tests {
380+
t.Run(tt.name, func(t *testing.T) {
381+
configInfo := schema.ConfigAndStacksInfo{
382+
AtmosConfigFilesFromArg: tt.files,
383+
AtmosConfigDirsFromArg: tt.dirs,
384+
}
385+
386+
_, err := InitCliConfig(configInfo, false)
387+
388+
if tt.expectError {
389+
assert.Error(t, err, tt.description)
390+
} else {
391+
assert.NoError(t, err, tt.description)
392+
}
393+
})
394+
}
395+
}

tools/lintroller/rule_os_chdir.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func (r *OsChdirInTestRule) Check(pass *analysis.Pass, file *ast.File) error {
2424
return nil // Only check test files.
2525
}
2626

27+
// Allow os.Chdir in test files that are explicitly testing chdir functionality.
28+
if strings.Contains(filename, "chdir_test.go") {
29+
return nil
30+
}
31+
2732
// Find benchmark functions to exclude from checks.
2833
benchmarks := findBenchmarksForChdir(file)
2934

0 commit comments

Comments
 (0)