package preproc import ( "testing" ) func TestDefineList_AddAndDefined(t *testing.T) { dl := NewDefineList() if dl.Defined("FOO") { t.Error("FOO should not be defined initially") } dl.Add("FOO", "bar") if !dl.Defined("FOO") { t.Error("FOO should be defined after Add") } } func TestDefineList_Delete(t *testing.T) { dl := NewDefineList() dl.Add("FOO", "bar") if !dl.Delete("FOO") { t.Error("Delete should return true for existing key") } if dl.Defined("FOO") { t.Error("FOO should not be defined after Delete") } if dl.Delete("NONEXISTENT") { t.Error("Delete should return false for non-existent key") } } func TestDefineList_ReplaceDefines_Simple(t *testing.T) { dl := NewDefineList() dl.Add("FOO", "replacement") tests := []struct { input string expected string }{ {"FOO", "replacement"}, {"before FOO after", "before replacement after"}, {"FOOFOO", "replacementreplacement"}, {"no match here", "no match here"}, {"", ""}, } for _, tt := range tests { got := dl.ReplaceDefines(tt.input) if got != tt.expected { t.Errorf("ReplaceDefines(%q) = %q, want %q", tt.input, got, tt.expected) } } } func TestDefineList_ReplaceDefines_LongestPrefix(t *testing.T) { dl := NewDefineList() dl.Add("FOO", "short") dl.Add("FOOBAR", "long") tests := []struct { input string expected string }{ {"FOO", "short"}, {"FOOBAR", "long"}, // longest match wins {"FOOBARBAZ", "longBAZ"}, // longest match, rest unchanged {"FOO BAR", "short BAR"}, // space breaks match } for _, tt := range tests { got := dl.ReplaceDefines(tt.input) if got != tt.expected { t.Errorf("ReplaceDefines(%q) = %q, want %q", tt.input, got, tt.expected) } } } func TestDefineList_ReplaceDefines_NoRecursion(t *testing.T) { dl := NewDefineList() dl.Add("A", "B") dl.Add("B", "C") // Should not recursively expand B->C if got := dl.ReplaceDefines("A"); got != "B" { t.Errorf("ReplaceDefines should not recurse: got %q, want %q", got, "B") } } func TestDefineList_ReplaceDefines_CaseSensitive(t *testing.T) { dl := NewDefineList() dl.Add("FOO", "bar") if got := dl.ReplaceDefines("foo"); got != "foo" { t.Errorf("Should be case-sensitive: got %q, want %q", got, "foo") } } func TestDefineList_ReplaceDefines_UTF8(t *testing.T) { dl := NewDefineList() dl.Add("🚀", "rocket") dl.Add("αβ", "alpha-beta") tests := []struct { input string expected string }{ {"🚀", "rocket"}, {"test🚀test", "testrockettest"}, {"αβγ", "alpha-betaγ"}, {"日本語FOO", "日本語FOO"}, // no match } for _, tt := range tests { got := dl.ReplaceDefines(tt.input) if got != tt.expected { t.Errorf("ReplaceDefines(%q) = %q, want %q", tt.input, got, tt.expected) } } } func TestDefineList_ReplaceDefines_MultipleReplacements(t *testing.T) { dl := NewDefineList() dl.Add("X", "1") dl.Add("Y", "2") dl.Add("Z", "3") got := dl.ReplaceDefines("X Y Z X") want := "1 2 3 1" if got != want { t.Errorf("ReplaceDefines = %q, want %q", got, want) } } func TestDefineList_ReplaceDefines_OverlappingPrefixes(t *testing.T) { dl := NewDefineList() dl.Add("A", "x") dl.Add("AB", "y") dl.Add("ABC", "z") tests := []struct { input string expected string }{ {"A", "x"}, {"AB", "y"}, {"ABC", "z"}, {"ABCD", "zD"}, {"AAA", "xxx"}, // three separate A matches {"ABABC", "yz"}, // AB, then ABC {"A-AB-ABC", "x-y-z"}, // separated by dashes } for _, tt := range tests { got := dl.ReplaceDefines(tt.input) if got != tt.expected { t.Errorf("ReplaceDefines(%q) = %q, want %q", tt.input, got, tt.expected) } } } func TestDefineList_ReplaceDefines_EmptyValue(t *testing.T) { dl := NewDefineList() dl.Add("REMOVE", "") got := dl.ReplaceDefines("before REMOVE after") want := "before after" if got != want { t.Errorf("ReplaceDefines = %q, want %q", got, want) } } func TestDefineList_ReplaceDefines_UpdateValue(t *testing.T) { dl := NewDefineList() dl.Add("FOO", "first") dl.Add("FOO", "second") // update got := dl.ReplaceDefines("FOO") if got != "second" { t.Errorf("After update: got %q, want %q", got, "second") } }