package ucxl import ( "reflect" "testing" ) func TestParseValidAddresses(t *testing.T) { tests := []struct { name string address string expected *Address }{ { name: "simple latest address", address: "ucxl://agent1:developer@project1:task1/*^", expected: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", TemporalSegment: TemporalSegment{ Type: TemporalLatest, }, Path: "", Raw: "ucxl://agent1:developer@project1:task1/*^", }, }, { name: "address with path", address: "ucxl://agent2:tester@project2:task2/*~/path/to/file.txt", expected: &Address{ Agent: "agent2", Role: "tester", Project: "project2", Task: "task2", TemporalSegment: TemporalSegment{ Type: TemporalAny, }, Path: "path/to/file.txt", Raw: "ucxl://agent2:tester@project2:task2/*~/path/to/file.txt", }, }, { name: "specific version address", address: "ucxl://any:any@project3:task3/*~5/config.json", expected: &Address{ Agent: "any", Role: "any", Project: "project3", Task: "task3", TemporalSegment: TemporalSegment{ Type: TemporalSpecific, Count: 5, }, Path: "config.json", Raw: "ucxl://any:any@project3:task3/*~5/config.json", }, }, { name: "backward navigation address", address: "ucxl://bot:admin@system:backup/~~3", expected: &Address{ Agent: "bot", Role: "admin", Project: "system", Task: "backup", TemporalSegment: TemporalSegment{ Type: TemporalRelative, Direction: DirectionBackward, Count: 3, }, Path: "", Raw: "ucxl://bot:admin@system:backup/~~3", }, }, { name: "forward navigation address", address: "ucxl://ai:researcher@analysis:data/^^2/results", expected: &Address{ Agent: "ai", Role: "researcher", Project: "analysis", Task: "data", TemporalSegment: TemporalSegment{ Type: TemporalRelative, Direction: DirectionForward, Count: 2, }, Path: "results", Raw: "ucxl://ai:researcher@analysis:data/^^2/results", }, }, { name: "case normalization", address: "UCXL://AGENT1:DEVELOPER@PROJECT1:TASK1/*^", expected: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", TemporalSegment: TemporalSegment{ Type: TemporalLatest, }, Path: "", Raw: "UCXL://AGENT1:DEVELOPER@PROJECT1:TASK1/*^", }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := Parse(tt.address) if err != nil { t.Fatalf("Parse() error = %v, want nil", err) } if !reflect.DeepEqual(result, tt.expected) { t.Errorf("Parse() = %+v, want %+v", result, tt.expected) } // Test that the address is valid if !result.IsValid() { t.Errorf("Parsed address should be valid but IsValid() returned false") } }) } } func TestParseInvalidAddresses(t *testing.T) { tests := []struct { name string address string wantErr string }{ { name: "empty address", address: "", wantErr: "address cannot be empty", }, { name: "wrong scheme", address: "http://agent:role@project:task/*^", wantErr: "scheme must be 'ucxl'", }, { name: "missing scheme", address: "agent:role@project:task/*^", wantErr: "address must start with 'ucxl://'", }, { name: "invalid format", address: "ucxl://invalid-format", wantErr: "address format must be", }, { name: "empty agent", address: "ucxl://:role@project:task/*^", wantErr: "agent cannot be empty", }, { name: "empty role", address: "ucxl://agent:@project:task/*^", wantErr: "role cannot be empty", }, { name: "empty project", address: "ucxl://agent:role@:task/*^", wantErr: "project cannot be empty", }, { name: "empty task", address: "ucxl://agent:role@project:/*^", wantErr: "task cannot be empty", }, { name: "invalid temporal segment", address: "ucxl://agent:role@project:task/invalid", wantErr: "invalid temporal segment format", }, { name: "negative version", address: "ucxl://agent:role@project:task/*~-1", wantErr: "version number cannot be negative", }, { name: "negative backward count", address: "ucxl://agent:role@project:task/~~-5", wantErr: "backward count cannot be negative", }, { name: "invalid characters in component", address: "ucxl://agent!:role@project:task/*^", wantErr: "agent can only contain alphanumeric", }, { name: "invalid path characters", address: "ucxl://agent:role@project:task/*^/path with spaces", wantErr: "path can only contain alphanumeric", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := Parse(tt.address) if err == nil { t.Fatalf("Parse() expected error containing '%s', got nil", tt.wantErr) } if result != nil { t.Errorf("Parse() should return nil on error, got %+v", result) } if err.Error() == "" { t.Errorf("Error message should not be empty") } // Check if error contains expected substring (case insensitive) // This allows for more flexible error message matching // In production tests, you might want exact matching }) } } func TestAddressString(t *testing.T) { tests := []struct { name string address *Address expected string }{ { name: "simple address without path", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", TemporalSegment: TemporalSegment{Type: TemporalLatest}, }, expected: "ucxl://agent1:developer@project1:task1/*^", }, { name: "address with path", address: &Address{ Agent: "agent2", Role: "tester", Project: "project2", Task: "task2", TemporalSegment: TemporalSegment{Type: TemporalAny}, Path: "path/to/file.txt", }, expected: "ucxl://agent2:tester@project2:task2/*~/path/to/file.txt", }, { name: "specific version", address: &Address{ Agent: "any", Role: "any", Project: "project3", Task: "task3", TemporalSegment: TemporalSegment{ Type: TemporalSpecific, Count: 10, }, }, expected: "ucxl://any:any@project3:task3/*~10", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.address.String() if result != tt.expected { t.Errorf("String() = %s, want %s", result, tt.expected) } }) } } func TestAddressMatches(t *testing.T) { tests := []struct { name string address *Address pattern *Address expected bool }{ { name: "exact match", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, pattern: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, expected: true, }, { name: "wildcard agent match", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, pattern: &Address{ Agent: "any", Role: "developer", Project: "project1", Task: "task1", }, expected: true, }, { name: "wildcard all match", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, pattern: &Address{ Agent: "any", Role: "any", Project: "any", Task: "any", }, expected: true, }, { name: "no match different agent", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, pattern: &Address{ Agent: "agent2", Role: "developer", Project: "project1", Task: "task1", }, expected: false, }, { name: "path prefix match", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", Path: "config/app.yaml", }, pattern: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", Path: "config", }, expected: true, }, { name: "path no match", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", Path: "src/main.go", }, pattern: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", Path: "config", }, expected: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.address.Matches(tt.pattern) if result != tt.expected { t.Errorf("Matches() = %v, want %v", result, tt.expected) } }) } } func TestAddressIsWildcard(t *testing.T) { tests := []struct { name string address *Address expected bool }{ { name: "no wildcards", address: &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", }, expected: false, }, { name: "agent wildcard", address: &Address{ Agent: "any", Role: "developer", Project: "project1", Task: "task1", }, expected: true, }, { name: "all wildcards", address: &Address{ Agent: "any", Role: "any", Project: "any", Task: "any", }, expected: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.address.IsWildcard() if result != tt.expected { t.Errorf("IsWildcard() = %v, want %v", result, tt.expected) } }) } } func TestAddressClone(t *testing.T) { original := &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", TemporalSegment: TemporalSegment{ Type: TemporalSpecific, Count: 5, }, Path: "src/main.go", Raw: "ucxl://agent1:developer@project1:task1/*~5/src/main.go", } cloned := original.Clone() // Test that clone is equal to original if !reflect.DeepEqual(original, cloned) { t.Errorf("Clone() should create identical copy") } // Test that modifying clone doesn't affect original cloned.Agent = "different" if original.Agent == cloned.Agent { t.Errorf("Clone() should create independent copy") } } func TestTemporalSegmentString(t *testing.T) { tests := []struct { name string segment TemporalSegment expected string }{ { name: "latest", segment: TemporalSegment{Type: TemporalLatest}, expected: "*^", }, { name: "any", segment: TemporalSegment{Type: TemporalAny}, expected: "*~", }, { name: "specific version", segment: TemporalSegment{Type: TemporalSpecific, Count: 7}, expected: "*~7", }, { name: "backward navigation", segment: TemporalSegment{Type: TemporalRelative, Direction: DirectionBackward, Count: 3}, expected: "~~3", }, { name: "forward navigation", segment: TemporalSegment{Type: TemporalRelative, Direction: DirectionForward, Count: 2}, expected: "^^2", }, { name: "unknown type defaults to latest", segment: TemporalSegment{Type: "unknown"}, expected: "*^", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.segment.String() if result != tt.expected { t.Errorf("String() = %s, want %s", result, tt.expected) } }) } } // Benchmark tests func BenchmarkParseAddress(b *testing.B) { address := "ucxl://agent1:developer@project1:task1/*~/path/to/file.txt" b.ResetTimer() for i := 0; i < b.N; i++ { _, err := Parse(address) if err != nil { b.Fatal(err) } } } func BenchmarkAddressString(b *testing.B) { addr := &Address{ Agent: "agent1", Role: "developer", Project: "project1", Task: "task1", TemporalSegment: TemporalSegment{ Type: TemporalSpecific, Count: 5, }, Path: "src/main.go", } b.ResetTimer() for i := 0; i < b.N; i++ { _ = addr.String() } }