Ensure we're cleaning up after our tests

This commit is contained in:
2025-10-16 15:56:56 +02:00
parent 59faaa181d
commit 25a8e2b65a

View File

@@ -6,25 +6,92 @@ import (
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
// Test helper to create a temporary test directory WITHIN the project
func createTestDir(t *testing.T) string {
// Get the project directory (current working directory)
// TestMain runs setup and teardown for all tests
func TestMain(m *testing.M) {
// Setup: create test_temp directory
projectDir, err := os.Getwd()
if err != nil {
fmt.Printf("Failed to get working directory: %v\n", err)
os.Exit(1)
}
testDir := filepath.Join(projectDir, "test_temp")
// Clean up any existing test_temp directory first
if _, err := os.Stat(testDir); err == nil {
if wd, _ := os.Getwd(); strings.HasPrefix(wd, testDir) {
_ = os.Chdir(projectDir)
}
_ = os.RemoveAll(testDir)
}
// Create fresh test_temp directory
err = os.MkdirAll(testDir, 0755)
if err != nil {
fmt.Printf("Failed to create test directory: %v\n", err)
os.Exit(1)
}
// Run tests
code := m.Run()
// Teardown: remove test_temp directory
if wd, _ := os.Getwd(); strings.HasPrefix(wd, testDir) {
_ = os.Chdir(projectDir)
}
err = os.RemoveAll(testDir)
if err != nil {
fmt.Printf("Warning: failed to remove test directory: %v\n", err)
}
os.Exit(code)
}
// Test helper to get the shared test_temp directory
func getTestDir(t *testing.T) string {
projectDir, err := os.Getwd()
assert.NoError(t, err)
// Create test directory WITHIN the project
testDir := filepath.Join(projectDir, "test_temp")
err = os.MkdirAll(testDir, 0755)
assert.NoError(t, err)
// Ensure test_temp exists (it should be created by TestMain)
if _, err := os.Stat(testDir); os.IsNotExist(err) {
t.Fatalf("test_temp directory does not exist - TestMain should have created it")
}
return testDir
}
// Global counter for unique directory names
var dirCounter int64
// Test helper to create a unique subdirectory for a specific test
func getTestSubDir(t *testing.T) string {
testDir := getTestDir(t)
// For complete isolation, create a unique directory using test name, timestamp, and counter
// This ensures even subtests within the same parent test are isolated
testName := t.Name()
timestamp := time.Now().UnixNano()
counter := atomic.AddInt64(&dirCounter, 1)
// Create a unique directory name
uniqueDirName := fmt.Sprintf("%s_%d_%d", testName, timestamp, counter)
subDirPath := filepath.Join(testDir, uniqueDirName)
err := os.MkdirAll(subDirPath, 0755)
assert.NoError(t, err)
return subDirPath
}
// Test helper to ensure we're working within the project directory
func ensureInProjectDir(t *testing.T, testDir string) {
// Get current working directory (should be project directory)
@@ -43,21 +110,9 @@ func ensureInProjectDir(t *testing.T, testDir string) {
}
}
// Test helper to clean up test directory
func cleanupTestDir(t *testing.T, testDir string) {
// If current working dir is inside the testDir, move out before removal (Windows locks directories in use)
if wd, _ := os.Getwd(); strings.HasPrefix(wd, testDir) {
_ = os.Chdir(filepath.Dir(testDir))
}
// We MUST remove the directory - this is critical for test isolation
err := os.RemoveAll(testDir)
assert.NoError(t, err, "Failed to remove test directory %s", testDir)
}
func TestParseInstruction(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -161,9 +216,8 @@ func TestParseInstruction(t *testing.T) {
}
func TestLinkInstruction_RunAsync(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -295,9 +349,9 @@ func TestLinkInstruction_RunAsync(t *testing.T) {
}
func TestLinkInstruction_Undo(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -354,9 +408,8 @@ func TestLinkInstruction_Undo(t *testing.T) {
}
func TestGlobPatterns(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -766,9 +819,8 @@ func createGlobTestStructure(t *testing.T, testDir string) {
}
func TestParseYAMLFile(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -874,9 +926,8 @@ func TestParseYAMLFile(t *testing.T) {
}
func TestExpandPattern(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -948,9 +999,8 @@ func TestExpandPattern(t *testing.T) {
}
func TestGetSyncFilesRecursively(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1012,9 +1062,8 @@ func TestGetSyncFilesRecursively(t *testing.T) {
}
func TestReadFromFile(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1101,9 +1150,8 @@ func TestReadFromFile(t *testing.T) {
// Test main.go functions that are completely missing coverage
func TestMainFunctions(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1201,9 +1249,8 @@ func TestMainFunctions(t *testing.T) {
// Test 1:1 destination mapping for glob patterns
func TestDestinationPathMapping(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1407,9 +1454,9 @@ func TestDestinationPathMapping(t *testing.T) {
// Test missing instruction.go paths
func TestInstructionEdgeCases(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1685,9 +1732,8 @@ func TestInstructionEdgeCases(t *testing.T) {
// Test missing util.go paths
func TestUtilEdgeCases(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -1895,9 +1941,8 @@ func TestPathFormattingFunctions(t *testing.T) {
// Test missing instruction.go YAML parsing paths
func TestYAMLEdgeCases(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -2031,9 +2076,8 @@ func TestYAMLEdgeCases(t *testing.T) {
// Test the untested error paths in ReadFromFile and ReadFromStdin
func TestErrorPaths(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -2381,9 +2425,8 @@ func TestErrorPaths(t *testing.T) {
// Test main.go functions that are currently at 0% coverage
func TestMainFunctionsCoverage(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -2666,9 +2709,10 @@ func TestMainFunctionsCoverage(t *testing.T) {
// Test Unicode filename support
func TestUnicodeFilenames(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Clean up any files from previous tests to prevent interference
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -2858,9 +2902,10 @@ func TestUnicodeFilenames(t *testing.T) {
// Test very long path handling (within project limits)
func TestLongPaths(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Clean up any files from previous tests to prevent interference
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -3065,8 +3110,7 @@ func TestLongPaths(t *testing.T) {
// Test special characters in filenames
func TestSpecialCharacters(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -3077,6 +3121,7 @@ func TestSpecialCharacters(t *testing.T) {
os.Chdir(testDir)
t.Run("Special characters in filenames", func(t *testing.T) {
// Test various special characters
specialFiles := []string{
"file-with-dashes.txt",
@@ -3159,6 +3204,12 @@ func TestSpecialCharacters(t *testing.T) {
assert.Contains(t, instruction.Target, "target with spaces.txt")
})
// Clean up files from previous subtests to prevent interference
files, _ := os.ReadDir(testDir)
for _, file := range files {
_ = os.Remove(filepath.Join(testDir, file.Name()))
}
t.Run("Special characters in glob patterns", func(t *testing.T) {
// Create files with special characters for glob testing
globFiles := []string{
@@ -3357,9 +3408,10 @@ func TestSpecialCharacters(t *testing.T) {
// Test mixed source type integration tests
func TestMixedSourceTypes(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Clean up any files from previous tests to prevent interference
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -3650,9 +3702,10 @@ func TestMixedSourceTypes(t *testing.T) {
// Test rollback scenario tests
func TestRollbackScenarios(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Clean up any files from previous tests to prevent interference
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)
@@ -3988,9 +4041,8 @@ func TestRollbackScenarios(t *testing.T) {
// Test YAMLConfig "From" functionality
func TestYAMLConfigFrom(t *testing.T) {
testDir := createTestDir(t)
defer cleanupTestDir(t, testDir)
testDir := getTestSubDir(t)
// Ensure we're working within the project directory
ensureInProjectDir(t, testDir)