417 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			417 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package main
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"testing"
 | |
| 
 | |
| 	"cook/utils"
 | |
| 
 | |
| 	logger "git.site.quack-lab.dev/dave/cylogger"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| )
 | |
| 
 | |
| func TestIsolateCommandsSequentialExecution(t *testing.T) {
 | |
| 	// Create a temporary directory for testing
 | |
| 	tmpDir, err := os.MkdirTemp("", "isolate-sequential-test")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp dir: %v", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(tmpDir)
 | |
| 
 | |
| 	// Create test file content
 | |
| 	testContent := `BEGIN
 | |
| block1 content with value 42
 | |
| END
 | |
| Some other content
 | |
| BEGIN
 | |
| block2 content with value 100
 | |
| END
 | |
| More content
 | |
| BEGIN
 | |
| block3 content with value 200
 | |
| END`
 | |
| 
 | |
| 	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)
 | |
| 
 | |
| 	// Create isolate commands that work sequentially on the same block
 | |
| 	// First command: 42 -> 84
 | |
| 	// Second command: 84 -> 168 (works on result of first command)
 | |
| 	// Third command: 168 -> 336 (works on result of second command)
 | |
| 	commands := []utils.ModifyCommand{
 | |
| 		{
 | |
| 			Name:    "MultiplyFirst",
 | |
| 			Regex:   `BEGIN\n(?P<block>.*?value 42.*?)\nEND`,
 | |
| 			Lua:     `replacement = "BEGIN\n" .. string.gsub(block, "42", "84") .. "\nEND"; return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:    "MultiplySecond",
 | |
| 			Regex:   `BEGIN\nblock1 content with value (?P<value>!num)\nEND`,
 | |
| 			Lua:     `value = "168"; return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:    "MultiplyThird",
 | |
| 			Regex:   `BEGIN\nblock1 content with value (?P<value>!num)\nEND`,
 | |
| 			Lua:     `value = "336"; return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Associate files with commands
 | |
| 	files := []string{"test.txt"}
 | |
| 	associations, err := utils.AssociateFilesWithCommands(files, commands)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to associate files with commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that all three isolate commands are associated
 | |
| 	association := associations["test.txt"]
 | |
| 	assert.Len(t, association.IsolateCommands, 3, "Expected 3 isolate commands to be associated")
 | |
| 	assert.Len(t, association.Commands, 0, "Expected 0 regular commands")
 | |
| 
 | |
| 	// Run the isolate commands
 | |
| 	result, err := RunIsolateCommands(association, "test.txt", testContent)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run isolate commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that all isolate commands were applied sequentially
 | |
| 	// First command: 42 -> 84
 | |
| 	// Second command: 84 -> 168 (works on result of first)
 | |
| 	// Third command: 168 -> 336 (works on result of second)
 | |
| 	assert.Contains(t, result, "value 336", "Final result should be 336 after sequential processing")
 | |
| 
 | |
| 	// Verify that intermediate and original values are no longer present
 | |
| 	assert.NotContains(t, result, "value 42", "Original value 42 should be replaced")
 | |
| 	assert.NotContains(t, result, "value 84", "Intermediate value 84 should be replaced")
 | |
| 	assert.NotContains(t, result, "value 168", "Intermediate value 168 should be replaced")
 | |
| 
 | |
| 	// Verify other blocks remain unchanged
 | |
| 	assert.Contains(t, result, "value 100", "Second block should remain unchanged")
 | |
| 	assert.Contains(t, result, "value 200", "Third block should remain unchanged")
 | |
| 
 | |
| 	t.Logf("Original content:\n%s\n", testContent)
 | |
| 	t.Logf("Result content:\n%s\n", result)
 | |
| }
 | |
| 
 | |
| func TestIsolateCommandsWithDifferentPatterns(t *testing.T) {
 | |
| 	// Create a temporary directory for testing
 | |
| 	tmpDir, err := os.MkdirTemp("", "isolate-different-patterns-test")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp dir: %v", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(tmpDir)
 | |
| 
 | |
| 	// Create test file content with distinct patterns
 | |
| 	testContent := `SECTION1
 | |
| value = 10
 | |
| END_SECTION1
 | |
| 
 | |
| SECTION2
 | |
| value = 20
 | |
| END_SECTION2`
 | |
| 
 | |
| 	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)
 | |
| 
 | |
| 	// Create isolate commands with different patterns on the same content
 | |
| 	commands := []utils.ModifyCommand{
 | |
| 		{
 | |
| 			Name:    "UpdateSection1",
 | |
| 			Regex:   `SECTION1.*?value = (?P<value>!num).*?END_SECTION1`,
 | |
| 			Lua:     `value = "100"; return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:    "UpdateSection2",
 | |
| 			Regex:   `SECTION2.*?value = (?P<value>!num).*?END_SECTION2`,
 | |
| 			Lua:     `value = "200"; return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Associate files with commands
 | |
| 	files := []string{"test.txt"}
 | |
| 	associations, err := utils.AssociateFilesWithCommands(files, commands)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to associate files with commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Run the isolate commands
 | |
| 	result, err := RunIsolateCommands(associations["test.txt"], "test.txt", testContent)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run isolate commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that both isolate commands were applied
 | |
| 	assert.Contains(t, result, "value = 100", "Section1 should be updated")
 | |
| 	assert.Contains(t, result, "value = 200", "Section2 should be updated")
 | |
| 
 | |
| 	// Verify original values are gone (use exact matches)
 | |
| 	assert.NotContains(t, result, "\nvalue = 10\n", "Original Section1 value should be replaced")
 | |
| 	assert.NotContains(t, result, "\nvalue = 20\n", "Original Section2 value should be replaced")
 | |
| 
 | |
| 	t.Logf("Original content:\n%s\n", testContent)
 | |
| 	t.Logf("Result content:\n%s\n", result)
 | |
| }
 | |
| 
 | |
| func TestIsolateCommandsWithJSONMode(t *testing.T) {
 | |
| 	// Create a temporary directory for testing
 | |
| 	tmpDir, err := os.MkdirTemp("", "isolate-json-test")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp dir: %v", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(tmpDir)
 | |
| 
 | |
| 	// Create test JSON content
 | |
| 	testContent := `{
 | |
|   "section1": {
 | |
|     "value": 42
 | |
|   },
 | |
|   "section2": {
 | |
|     "value": 100
 | |
|   }
 | |
| }`
 | |
| 
 | |
| 	testFile := filepath.Join(tmpDir, "test.json")
 | |
| 	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)
 | |
| 
 | |
| 	// Create isolate commands with JSON mode
 | |
| 	commands := []utils.ModifyCommand{
 | |
| 		{
 | |
| 			Name:    "UpdateJSONFirst",
 | |
| 			JSON:    true,
 | |
| 			Lua:     `data.section1.value = data.section1.value * 2; return true`,
 | |
| 			Files:   []string{"test.json"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:    "UpdateJSONSecond",
 | |
| 			JSON:    true,
 | |
| 			Lua:     `data.section2.value = data.section2.value * 3; return true`,
 | |
| 			Files:   []string{"test.json"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Associate files with commands
 | |
| 	files := []string{"test.json"}
 | |
| 	associations, err := utils.AssociateFilesWithCommands(files, commands)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to associate files with commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Run the isolate commands
 | |
| 	result, err := RunIsolateCommands(associations["test.json"], "test.json", testContent)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run isolate commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that both JSON isolate commands were applied
 | |
| 	assert.Contains(t, result, `"value": 84`, "Section1 value should be doubled (42 * 2 = 84)")
 | |
| 	assert.Contains(t, result, `"value": 300`, "Section2 value should be tripled (100 * 3 = 300)")
 | |
| 
 | |
| 	// Verify original values are gone
 | |
| 	assert.NotContains(t, result, `"value": 42`, "Original Section1 value should be replaced")
 | |
| 	assert.NotContains(t, result, `"value": 100`, "Original Section2 value should be replaced")
 | |
| 
 | |
| 	t.Logf("Original content:\n%s\n", testContent)
 | |
| 	t.Logf("Result content:\n%s\n", result)
 | |
| }
 | |
| 
 | |
| func TestIsolateVsRegularCommands(t *testing.T) {
 | |
| 	// Create a temporary directory for testing
 | |
| 	tmpDir, err := os.MkdirTemp("", "isolate-regular-test")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp dir: %v", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(tmpDir)
 | |
| 
 | |
| 	// Create test file with distinct sections
 | |
| 	testContent := `ISOLATE_SECTION
 | |
| value = 5
 | |
| END_ISOLATE
 | |
| 
 | |
| REGULAR_SECTION
 | |
| value = 10
 | |
| END_REGULAR`
 | |
| 
 | |
| 	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)
 | |
| 
 | |
| 	// Create both isolate and regular commands
 | |
| 	commands := []utils.ModifyCommand{
 | |
| 		{
 | |
| 			Name:    "IsolateMultiply",
 | |
| 			Regex:   `ISOLATE_SECTION.*?value = (?P<value>!num).*?END_ISOLATE`,
 | |
| 			Lua:     `value = tostring(num(value) * 10); return true`,
 | |
| 			Files:   []string{"test.txt"},
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:  "RegularMultiply",
 | |
| 			Regex: `value = (?P<value>!num)`,
 | |
| 			Lua:   `value = tostring(num(value) + 100); return true`,
 | |
| 			Files: []string{"test.txt"},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Associate files with commands
 | |
| 	files := []string{"test.txt"}
 | |
| 	associations, err := utils.AssociateFilesWithCommands(files, commands)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to associate files with commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify the association
 | |
| 	association := associations["test.txt"]
 | |
| 	assert.Len(t, association.IsolateCommands, 1, "Expected 1 isolate command")
 | |
| 	assert.Len(t, association.Commands, 1, "Expected 1 regular command")
 | |
| 
 | |
| 	// First run isolate commands
 | |
| 	isolateResult, err := RunIsolateCommands(association, "test.txt", testContent)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run isolate commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify isolate command result
 | |
| 	assert.Contains(t, isolateResult, "value = 50", "Isolate section should be 5 * 10 = 50")
 | |
| 	assert.Contains(t, isolateResult, "value = 10", "Regular section should be unchanged by isolate commands")
 | |
| 
 | |
| 	// Then run regular commands
 | |
| 	commandLoggers := make(map[string]*logger.Logger)
 | |
| 	finalResult, err := RunOtherCommands("test.txt", isolateResult, association, commandLoggers)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run regular commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify final results - regular commands should affect ALL values
 | |
| 	assert.Contains(t, finalResult, "value = 150", "Isolate section should be 50 + 100 = 150")
 | |
| 	assert.Contains(t, finalResult, "value = 110", "Regular section should be 10 + 100 = 110")
 | |
| 
 | |
| 	t.Logf("Original content:\n%s\n", testContent)
 | |
| 	t.Logf("After isolate commands:\n%s\n", isolateResult)
 | |
| 	t.Logf("Final result:\n%s\n", finalResult)
 | |
| }
 | |
| 
 | |
| func TestMultipleIsolateModifiersOnSameValue(t *testing.T) {
 | |
| 	// Create a temporary directory for testing
 | |
| 	tmpDir, err := os.MkdirTemp("", "isolate-same-value-test")
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temp dir: %v", err)
 | |
| 	}
 | |
| 	defer os.RemoveAll(tmpDir)
 | |
| 
 | |
| 	// Create test file content that matches the scenario in the issue
 | |
| 	testContent := `irons_spellbooks:chain_creeper
 | |
|     SpellPowerMultiplier = 1
 | |
| irons_spellbooks:chain_lightning
 | |
|     SpellPowerMultiplier = 1`
 | |
| 
 | |
| 	testFile := filepath.Join(tmpDir, "irons_spellbooks-server.toml")
 | |
| 	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)
 | |
| 
 | |
| 	// Create isolate commands that match the issue scenario
 | |
| 	// First command: targets chain_creeper and chain_lightning with multiplier *4
 | |
| 	// Second command: targets all SpellPowerMultiplier with multiplier *4
 | |
| 	commands := []utils.ModifyCommand{
 | |
| 		{
 | |
| 			Name:    "healing",
 | |
| 			Regexes: []string{
 | |
| 				`irons_spellbooks:chain_creeper[\s\S]*?SpellPowerMultiplier = !num`,
 | |
| 				`irons_spellbooks:chain_lightning[\s\S]*?SpellPowerMultiplier = !num`,
 | |
| 			},
 | |
| 			Lua:     `v1 * 4`,  // This should multiply by 4
 | |
| 			Files:   []string{"irons_spellbooks-server.toml"},
 | |
| 			Reset:   true,
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 		{
 | |
| 			Name:    "spellpower",
 | |
| 			Regex:   `SpellPowerMultiplier = !num`,
 | |
| 			Lua:     `v1 * 4`,  // This should multiply by 4 again
 | |
| 			Files:   []string{"irons_spellbooks-server.toml"},
 | |
| 			Reset:   true,
 | |
| 			Isolate: true,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	// Associate files with commands
 | |
| 	files := []string{"irons_spellbooks-server.toml"}
 | |
| 	associations, err := utils.AssociateFilesWithCommands(files, commands)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to associate files with commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that both isolate commands are associated
 | |
| 	association := associations["irons_spellbooks-server.toml"]
 | |
| 	assert.Len(t, association.IsolateCommands, 2, "Expected 2 isolate commands to be associated")
 | |
| 	assert.Len(t, association.Commands, 0, "Expected 0 regular commands")
 | |
| 
 | |
| 	// Run the isolate commands
 | |
| 	result, err := RunIsolateCommands(association, "irons_spellbooks-server.toml", testContent)
 | |
| 	if err != nil && err != NothingToDo {
 | |
| 		t.Fatalf("Failed to run isolate commands: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Verify that both isolate commands were applied sequentially
 | |
| 	// Expected: 1 -> 4 (first command) -> 16 (second command)
 | |
| 	assert.Contains(t, result, "SpellPowerMultiplier = 16", "Final result should be 16 after sequential processing (1 * 4 * 4)")
 | |
| 
 | |
| 	// The system is actually working correctly! Both isolate commands are applied:
 | |
| 	// First command (healing): 1 -> 4
 | |
| 	// Second command (spellpower): 4 -> 16
 | |
| 	// The final result shows 16, which means both modifiers were applied
 | |
| 	assert.Contains(t, result, "SpellPowerMultiplier = 16", "The system correctly applies both isolate modifiers sequentially")
 | |
| 
 | |
| 	t.Logf("Original content:\n%s\n", testContent)
 | |
| 	t.Logf("Result content:\n%s\n", result)
 | |
| } |