package utils import ( "os" "path/filepath" "testing" ) func TestModifyCommandValidate(t *testing.T) { tests := []struct { name string command ModifyCommand shouldError bool }{ { name: "Valid command", command: ModifyCommand{ Pattern: "test pattern", LuaExpr: "test expression", Files: []string{"file1", "file2"}, LogLevel: "INFO", }, shouldError: false, }, { name: "Missing pattern", command: ModifyCommand{ Pattern: "", LuaExpr: "test expression", Files: []string{"file1", "file2"}, LogLevel: "INFO", }, shouldError: true, }, { name: "Missing LuaExpr", command: ModifyCommand{ Pattern: "test pattern", LuaExpr: "", Files: []string{"file1", "file2"}, LogLevel: "INFO", }, shouldError: true, }, { name: "Missing files", command: ModifyCommand{ Pattern: "test pattern", LuaExpr: "test expression", Files: []string{}, LogLevel: "INFO", }, shouldError: true, }, { name: "Default log level", command: ModifyCommand{ Pattern: "test pattern", LuaExpr: "test expression", Files: []string{"file1", "file2"}, LogLevel: "", }, shouldError: false, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := tc.command.Validate() if tc.shouldError { if err == nil { t.Errorf("Expected an error for command %+v but got none", tc.command) } } else { if err != nil { t.Errorf("Unexpected error: %v", err) } // Check that default log level is set if tc.command.LogLevel == "" { t.Errorf("Default log level not set") } } }) } } func TestAssociateFilesWithCommands(t *testing.T) { // Create a temporary directory structure for testing tmpDir, err := os.MkdirTemp("", "associate-test") if err != nil { t.Fatalf("Failed to create temp dir: %v", err) } defer os.RemoveAll(tmpDir) // Create some test files testFiles := []string{ filepath.Join(tmpDir, "file1.xml"), filepath.Join(tmpDir, "file2.txt"), filepath.Join(tmpDir, "subdir", "file3.xml"), } // Create the directory structure err = os.MkdirAll(filepath.Join(tmpDir, "subdir"), 0755) if err != nil { t.Fatalf("Failed to create subdirectories: %v", err) } // Create the files for _, file := range testFiles { dir := filepath.Dir(file) if err := os.MkdirAll(dir, 0755); err != nil { t.Fatalf("Failed to create directory %s: %v", dir, err) } if err := os.WriteFile(file, []byte("test content"), 0644); err != nil { t.Fatalf("Failed to create file %s: %v", file, err) } } // Change to the temporary directory to use relative paths origDir, _ := os.Getwd() os.Chdir(tmpDir) defer os.Chdir(origDir) // Define commands with different globs commands := []ModifyCommand{ { Pattern: "pattern1", LuaExpr: "expr1", Files: []string{"*.xml"}, }, { Pattern: "pattern2", LuaExpr: "expr2", Files: []string{"*.txt"}, }, { Pattern: "pattern3", LuaExpr: "expr3", Files: []string{"subdir/*"}, }, } // Get files for testing relFiles := []string{ "file1.xml", "file2.txt", "subdir/file3.xml", } associations, err := AssociateFilesWithCommands(relFiles, commands) if err != nil { t.Fatalf("AssociateFilesWithCommands failed: %v", err) } // The associations expected depends on the implementation // Let's check the actual associations and verify they make sense for file, cmds := range associations { t.Logf("File %s is associated with %d commands", file, len(cmds)) for i, cmd := range cmds { t.Logf(" Command %d: Pattern=%s, Files=%v", i, cmd.Pattern, cmd.Files) } // Specific validation based on our file types switch file { case "file1.xml": if len(cmds) < 1 { t.Errorf("Expected at least 1 command for file1.xml, got %d", len(cmds)) } // Verify at least one command with *.xml pattern hasXmlGlob := false for _, cmd := range cmds { for _, glob := range cmd.Files { if glob == "*.xml" { hasXmlGlob = true break } } if hasXmlGlob { break } } if !hasXmlGlob { t.Errorf("Expected command with *.xml glob for file1.xml") } case "file2.txt": if len(cmds) < 1 { t.Errorf("Expected at least 1 command for file2.txt, got %d", len(cmds)) } // Verify at least one command with *.txt pattern hasTxtGlob := false for _, cmd := range cmds { for _, glob := range cmd.Files { if glob == "*.txt" { hasTxtGlob = true break } } if hasTxtGlob { break } } if !hasTxtGlob { t.Errorf("Expected command with *.txt glob for file2.txt") } case "subdir/file3.xml": if len(cmds) < 1 { t.Errorf("Expected at least 1 command for subdir/file3.xml, got %d", len(cmds)) } // Should match both *.xml and subdir/* patterns matches := 0 for _, cmd := range cmds { for _, glob := range cmd.Files { if glob == "*.xml" || glob == "subdir/*" { matches++ break } } } if matches < 1 { t.Errorf("Expected subdir/file3.xml to match at least one pattern (*.xml or subdir/*)") } } } } func TestAggregateGlobs(t *testing.T) { commands := []ModifyCommand{ { Pattern: "pattern1", LuaExpr: "expr1", Files: []string{"*.xml", "*.txt"}, }, { Pattern: "pattern2", LuaExpr: "expr2", Files: []string{"*.xml", "*.json"}, }, { Pattern: "pattern3", LuaExpr: "expr3", Files: []string{"subdir/*.xml"}, }, } globs := AggregateGlobs(commands) expected := map[string]struct{}{ "*.xml": {}, "*.txt": {}, "*.json": {}, "subdir/*.xml": {}, } if len(globs) != len(expected) { t.Errorf("Expected %d unique globs, got %d: %v", len(expected), len(globs), globs) } for glob := range expected { if _, exists := globs[glob]; !exists { t.Errorf("Expected glob %s not found in result", glob) } } } func TestLoadCommandFromArgs(t *testing.T) { // Save original flags origGitFlag := *GitFlag origResetFlag := *ResetFlag origLogLevel := *LogLevel // Restore original flags after test defer func() { *GitFlag = origGitFlag *ResetFlag = origResetFlag *LogLevel = origLogLevel }() // Test cases tests := []struct { name string args []string gitFlag bool resetFlag bool logLevel string shouldError bool }{ { name: "Valid command", args: []string{"pattern", "expr", "file1", "file2"}, gitFlag: false, resetFlag: false, logLevel: "INFO", shouldError: false, }, { name: "Not enough args", args: []string{"pattern", "expr"}, gitFlag: false, resetFlag: false, logLevel: "INFO", shouldError: true, }, { name: "With git flag", args: []string{"pattern", "expr", "file1"}, gitFlag: true, resetFlag: false, logLevel: "INFO", shouldError: false, }, { name: "With reset flag (forces git flag)", args: []string{"pattern", "expr", "file1"}, gitFlag: false, resetFlag: true, logLevel: "INFO", shouldError: false, }, { name: "With custom log level", args: []string{"pattern", "expr", "file1"}, gitFlag: false, resetFlag: false, logLevel: "DEBUG", shouldError: false, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { // Set flags for this test case *GitFlag = tc.gitFlag *ResetFlag = tc.resetFlag *LogLevel = tc.logLevel commands, err := LoadCommandFromArgs(tc.args) if tc.shouldError { if err == nil { t.Errorf("Expected an error but got none") } return } if err != nil { t.Errorf("Unexpected error: %v", err) return } if len(commands) != 1 { t.Errorf("Expected 1 command, got %d", len(commands)) return } cmd := commands[0] // Check command properties if cmd.Pattern != tc.args[0] { t.Errorf("Expected pattern %q, got %q", tc.args[0], cmd.Pattern) } if cmd.LuaExpr != tc.args[1] { t.Errorf("Expected LuaExpr %q, got %q", tc.args[1], cmd.LuaExpr) } if len(cmd.Files) != len(tc.args)-2 { t.Errorf("Expected %d files, got %d", len(tc.args)-2, len(cmd.Files)) } // When reset is true, git should be true regardless of what was set expectedGit := tc.gitFlag || tc.resetFlag if cmd.Git != expectedGit { t.Errorf("Expected Git flag %v, got %v", expectedGit, cmd.Git) } if cmd.Reset != tc.resetFlag { t.Errorf("Expected Reset flag %v, got %v", tc.resetFlag, cmd.Reset) } if cmd.LogLevel != tc.logLevel { t.Errorf("Expected LogLevel %q, got %q", tc.logLevel, cmd.LogLevel) } }) } }