diff --git a/toml_test.go b/toml_test.go new file mode 100644 index 0000000..2141f42 --- /dev/null +++ b/toml_test.go @@ -0,0 +1,425 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "cook/utils" + + "github.com/stretchr/testify/assert" +) + +func TestTOMLLoadBasic(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-basic-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create a simple TOML test file + tomlContent := `[[commands]] +name = "SimpleTest" +regex = "test = !num" +lua = "v1 * 2" +files = ["test.txt"] + +[[commands]] +name = "AnotherTest" +regex = "value = (!num)" +lua = "v1 + 10" +files = ["*.txt"] +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test loading TOML commands + commands, err := utils.LoadCommandsFromTomlFiles("test.toml") + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 2, "Should load 2 commands from TOML") + + // Verify first command + assert.Equal(t, "SimpleTest", commands[0].Name, "First command name should match") + assert.Equal(t, "test = !num", commands[0].Regex, "First command regex should match") + assert.Equal(t, "v1 * 2", commands[0].Lua, "First command Lua should match") + assert.Equal(t, []string{"test.txt"}, commands[0].Files, "First command files should match") + + // Verify second command + assert.Equal(t, "AnotherTest", commands[1].Name, "Second command name should match") + assert.Equal(t, "value = (!num)", commands[1].Regex, "Second command regex should match") + assert.Equal(t, "v1 + 10", commands[1].Lua, "Second command Lua should match") + assert.Equal(t, []string{"*.txt"}, commands[1].Files, "Second command files should match") +} + +func TestTOMLGlobalModifiers(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-global-modifiers-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create TOML content with global modifiers + tomlContent := `[[commands]] +modifiers = { multiplier = 3, prefix = "TEST_", enabled = true } + +[[commands]] +name = "UseGlobalModifiers" +regex = "value = !num" +lua = "v1 * multiplier; s1 = prefix .. s1" +files = ["test.txt"] +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test loading TOML commands + commands, err := utils.LoadCommandsFromTomlFiles("test.toml") + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 2, "Should load 2 commands from TOML") + + // Verify global modifiers command (first command should have only modifiers) + assert.Empty(t, commands[0].Name, "Global modifiers command should have no name") + assert.Empty(t, commands[0].Regex, "Global modifiers command should have no regex") + assert.Empty(t, commands[0].Lua, "Global modifiers command should have no lua") + assert.Empty(t, commands[0].Files, "Global modifiers command should have no files") + assert.Len(t, commands[0].Modifiers, 3, "Global modifiers command should have 3 modifiers") + assert.Equal(t, int64(3), commands[0].Modifiers["multiplier"], "Multiplier should be 3") + assert.Equal(t, "TEST_", commands[0].Modifiers["prefix"], "Prefix should be TEST_") + assert.Equal(t, true, commands[0].Modifiers["enabled"], "Enabled should be true") + + // Verify regular command + assert.Equal(t, "UseGlobalModifiers", commands[1].Name, "Regular command name should match") + assert.Equal(t, "value = !num", commands[1].Regex, "Regular command regex should match") +} + +func TestTOMLMultilineRegex(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-multiline-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create TOML content with multiline regex using literal strings + tomlContent := `[[commands]] +modifiers = { factor = 2.5 } + +[[commands]] +name = "MultilineTest" +regex = ''' +\[config\.settings\] + + depth = !num + + width = !num + + height = !num''' +lua = "v1 * factor" +files = ["test.conf"] +isolate = true +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Create test file that matches the multiline pattern + testContent := `[config.settings] + + depth = 10 + + width = 20 + + height = 30 +` + + testFile := filepath.Join(tmpDir, "test.conf") + err = os.WriteFile(testFile, []byte(testContent), 0644) + if err != nil { + t.Fatalf("Failed to write test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test loading TOML commands + commands, err := utils.LoadCommandsFromTomlFiles("test.toml") + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 2, "Should load 2 commands from TOML") + + // Verify the multiline regex command + multilineCmd := commands[1] + assert.Equal(t, "MultilineTest", multilineCmd.Name, "Command name should match") + assert.Contains(t, multilineCmd.Regex, "\\[config\\.settings\\]", "Regex should contain escaped brackets") + assert.Contains(t, multilineCmd.Regex, "depth = !num", "Regex should contain depth pattern") + assert.Contains(t, multilineCmd.Regex, "width = !num", "Regex should contain width pattern") + assert.Contains(t, multilineCmd.Regex, "height = !num", "Regex should contain height pattern") + assert.Contains(t, multilineCmd.Regex, "\n", "Regex should contain newlines") + assert.True(t, multilineCmd.Isolate, "Isolate should be true") + + // Verify the regex preserves proper structure + expectedLines := []string{ + "\\[config\\.settings\\]", + "depth = !num", + "width = !num", + "height = !num", + } + + for _, line := range expectedLines { + assert.Contains(t, multilineCmd.Regex, line, "Regex should contain: "+line) + } +} + +func TestTOMLComplexRegexPatterns(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-complex-regex-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create TOML content with complex regex patterns + tomlContent := `[[commands]] +name = "ComplexPatterns" +regexes = [ + "\\[section\\.([^\\]]+)\\]", + "(?P\\w+)\\s*=\\s*(?P\\d+\\.\\d+)", + "network\\.(\\w+)\\.(enable|disable)" +] +lua = "if is_number(value) then value = num(value) * 1.1 end; return true" +files = ["*.conf", "*.ini"] +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test loading TOML commands + commands, err := utils.LoadCommandsFromTomlFiles("test.toml") + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 1, "Should load 1 command from TOML") + + // Verify the complex regex command + cmd := commands[0] + assert.Equal(t, "ComplexPatterns", cmd.Name, "Command name should match") + assert.Len(t, cmd.Regexes, 3, "Should have 3 regex patterns") + + // Verify each regex pattern + assert.Equal(t, `\[section\.([^\]]+)\]`, cmd.Regexes[0], "First regex should match section pattern") + assert.Equal(t, `(?P\w+)\s*=\s*(?P\d+\.\d+)`, cmd.Regexes[1], "Second regex should match key-value pattern") + assert.Equal(t, `network\.(\w+)\.(enable|disable)`, cmd.Regexes[2], "Third regex should match network pattern") + + assert.Equal(t, []string{"*.conf", "*.ini"}, cmd.Files, "Files should match") +} + +func TestTOMLJSONMode(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-json-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create TOML content with JSON mode commands + tomlContent := `[[commands]] +name = "JSONMultiply" +json = true +lua = "for i, item in ipairs(data.items) do data.items[i].value = item.value * 2 end; return true" +files = ["data.json"] + +[[commands]] +name = "JSONObjectUpdate" +json = true +lua = "data.version = '2.0.0'; data.enabled = true; return true" +files = ["config.json"] +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test loading TOML commands + commands, err := utils.LoadCommandsFromTomlFiles("test.toml") + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 2, "Should load 2 commands from TOML") + + // Verify first JSON command + cmd1 := commands[0] + assert.Equal(t, "JSONMultiply", cmd1.Name, "First command name should match") + assert.True(t, cmd1.JSON, "First command should have JSON mode enabled") + assert.Equal(t, "for i, item in ipairs(data.items) do data.items[i].value = item.value * 2 end; return true", cmd1.Lua, "First command Lua should match") + assert.Equal(t, []string{"data.json"}, cmd1.Files, "First command files should match") + + // Verify second JSON command + cmd2 := commands[1] + assert.Equal(t, "JSONObjectUpdate", cmd2.Name, "Second command name should match") + assert.True(t, cmd2.JSON, "Second command should have JSON mode enabled") + assert.Equal(t, "data.version = '2.0.0'; data.enabled = true; return true", cmd2.Lua, "Second command Lua should match") + assert.Equal(t, []string{"config.json"}, cmd2.Files, "Second command files should match") +} + +func TestTOMLEndToEndIntegration(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-integration-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Create comprehensive TOML content + tomlContent := `[[commands]] +modifiers = { multiplier = 4, base_value = 100 } + +[[commands]] +name = "IntegrationTest" +regex = ''' +\[kinetics\.stressValues\.v2\.capacity\] + + steam_engine = !num + + water_wheel = !num + + copper_valve_handle = !num''' +lua = "v1 * multiplier" +files = ["test.txt"] +isolate = true + +[[commands]] +name = "SimplePattern" +regex = "enabled = (true|false)" +lua = "= false" +files = ["test.txt"] +` + + tomlFile := filepath.Join(tmpDir, "test.toml") + err = os.WriteFile(tomlFile, []byte(tomlContent), 0644) + if err != nil { + t.Fatalf("Failed to write TOML test file: %v", err) + } + + // Create test file that matches the patterns + testContent := `[kinetics.stressValues.v2.capacity] + + steam_engine = 256 + + water_wheel = 64 + + copper_valve_handle = 16 + +some_other_setting = enabled = true +` + + testFile := filepath.Join(tmpDir, "test.txt") + err = os.WriteFile(testFile, []byte(testContent), 0644) + if err != nil { + t.Fatalf("Failed to write test file: %v", err) + } + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test the complete workflow using the main function + commands, err := utils.LoadCommands([]string{"test.toml"}) + assert.NoError(t, err, "Should load TOML commands without error") + assert.Len(t, commands, 3, "Should load 3 commands total (including global modifiers)") + + // Associate files with commands + files := []string{"test.txt"} + associations, err := utils.AssociateFilesWithCommands(files, commands) + assert.NoError(t, err, "Should associate files with commands") + + // Verify associations + association := associations["test.txt"] + assert.Len(t, association.IsolateCommands, 1, "Should have 1 isolate command") + assert.Len(t, association.Commands, 1, "Should have 1 regular command") + assert.Equal(t, "IntegrationTest", association.IsolateCommands[0].Name, "Isolate command should match") + assert.Equal(t, "SimplePattern", association.Commands[0].Name, "Regular command should match") + + t.Logf("TOML integration test completed successfully") + t.Logf("Loaded %d commands from TOML", len(commands)) + t.Logf("Associated commands: %d isolate, %d regular", + len(association.IsolateCommands), len(association.Commands)) +} + +func TestTOMLErrorHandling(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "toml-error-test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tmpDir) + + // Change to temp directory + origDir, _ := os.Getwd() + defer os.Chdir(origDir) + os.Chdir(tmpDir) + + // Test 1: Invalid TOML syntax + invalidTOML := `[[commands]] +name = "Invalid" +regex = "test = !num" +lua = "v1 * 2" +files = ["test.txt" +# Missing closing bracket +` + + invalidFile := filepath.Join(tmpDir, "invalid.toml") + err = os.WriteFile(invalidFile, []byte(invalidTOML), 0644) + + commands, err := utils.LoadCommandsFromTomlFiles("invalid.toml") + assert.Error(t, err, "Should return error for invalid TOML syntax") + assert.Nil(t, commands, "Should return nil commands for invalid TOML") + assert.Contains(t, err.Error(), "failed to unmarshal TOML file", "Error should mention TOML unmarshaling") + + // Test 2: Non-existent file + commands, err = utils.LoadCommandsFromTomlFiles("nonexistent.toml") + assert.NoError(t, err, "Should handle non-existent file without error") + assert.Empty(t, commands, "Should return empty commands for non-existent file") + + // Test 3: Empty TOML file creates an error (this is expected behavior) + emptyFile := filepath.Join(tmpDir, "empty.toml") + err = os.WriteFile(emptyFile, []byte(""), 0644) + + commands, err = utils.LoadCommandsFromTomlFiles("empty.toml") + assert.Error(t, err, "Should return error for empty TOML file") + assert.Nil(t, commands, "Should return nil commands for empty TOML") +} \ No newline at end of file