package protocol import ( "testing" ) func TestParseBzzzURI(t *testing.T) { tests := []struct { name string uri string expectError bool expected *BzzzURI }{ { name: "valid basic URI", uri: "bzzz://claude:frontend@chorus:implement/src/main.go", expected: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "/src/main.go", Raw: "bzzz://claude:frontend@chorus:implement/src/main.go", }, }, { name: "URI with wildcards", uri: "bzzz://any:*@*:test", expected: &BzzzURI{ Agent: "any", Role: "*", Project: "*", Task: "test", Raw: "bzzz://any:*@*:test", }, }, { name: "URI with query and fragment", uri: "bzzz://claude:backend@bzzz:debug/api/handler.go?type=error#line123", expected: &BzzzURI{ Agent: "claude", Role: "backend", Project: "bzzz", Task: "debug", Path: "/api/handler.go", Query: "type=error", Fragment: "line123", Raw: "bzzz://claude:backend@bzzz:debug/api/handler.go?type=error#line123", }, }, { name: "URI without path", uri: "bzzz://any:architect@project:review", expected: &BzzzURI{ Agent: "any", Role: "architect", Project: "project", Task: "review", Raw: "bzzz://any:architect@project:review", }, }, { name: "invalid scheme", uri: "http://claude:frontend@chorus:implement", expectError: true, }, { name: "missing role", uri: "bzzz://claude@chorus:implement", expectError: true, }, { name: "missing task", uri: "bzzz://claude:frontend@chorus", expectError: true, }, { name: "empty URI", uri: "", expectError: true, }, { name: "invalid format", uri: "bzzz://invalid", expectError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := ParseBzzzURI(tt.uri) if tt.expectError { if err == nil { t.Errorf("expected error but got none") } return } if err != nil { t.Errorf("unexpected error: %v", err) return } if result == nil { t.Errorf("result is nil") return } // Compare components if result.Agent != tt.expected.Agent { t.Errorf("Agent: expected %s, got %s", tt.expected.Agent, result.Agent) } if result.Role != tt.expected.Role { t.Errorf("Role: expected %s, got %s", tt.expected.Role, result.Role) } if result.Project != tt.expected.Project { t.Errorf("Project: expected %s, got %s", tt.expected.Project, result.Project) } if result.Task != tt.expected.Task { t.Errorf("Task: expected %s, got %s", tt.expected.Task, result.Task) } if result.Path != tt.expected.Path { t.Errorf("Path: expected %s, got %s", tt.expected.Path, result.Path) } if result.Query != tt.expected.Query { t.Errorf("Query: expected %s, got %s", tt.expected.Query, result.Query) } if result.Fragment != tt.expected.Fragment { t.Errorf("Fragment: expected %s, got %s", tt.expected.Fragment, result.Fragment) } }) } } func TestBzzzURIValidation(t *testing.T) { tests := []struct { name string uri *BzzzURI expectError bool }{ { name: "valid URI", uri: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "/src/main.go", }, expectError: false, }, { name: "empty agent", uri: &BzzzURI{ Agent: "", Role: "frontend", Project: "chorus", Task: "implement", }, expectError: true, }, { name: "invalid agent format", uri: &BzzzURI{ Agent: "invalid@agent", Role: "frontend", Project: "chorus", Task: "implement", }, expectError: true, }, { name: "wildcard components", uri: &BzzzURI{ Agent: "*", Role: "any", Project: "*", Task: "*", }, expectError: false, }, { name: "invalid path", uri: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "invalid-path", // Should start with / }, expectError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.uri.Validate() if tt.expectError && err == nil { t.Errorf("expected error but got none") } if !tt.expectError && err != nil { t.Errorf("unexpected error: %v", err) } }) } } func TestBzzzURINormalize(t *testing.T) { uri := &BzzzURI{ Agent: "Claude", Role: "Frontend", Project: "CHORUS", Task: "Implement", Path: "src/main.go", // Missing leading slash } uri.Normalize() expected := &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "/src/main.go", } if uri.Agent != expected.Agent { t.Errorf("Agent: expected %s, got %s", expected.Agent, uri.Agent) } if uri.Role != expected.Role { t.Errorf("Role: expected %s, got %s", expected.Role, uri.Role) } if uri.Project != expected.Project { t.Errorf("Project: expected %s, got %s", expected.Project, uri.Project) } if uri.Task != expected.Task { t.Errorf("Task: expected %s, got %s", expected.Task, uri.Task) } if uri.Path != expected.Path { t.Errorf("Path: expected %s, got %s", expected.Path, uri.Path) } } func TestBzzzURIMatches(t *testing.T) { tests := []struct { name string uri1 *BzzzURI uri2 *BzzzURI expected bool }{ { name: "exact match", uri1: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, uri2: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, expected: true, }, { name: "wildcard agent match", uri1: &BzzzURI{Agent: "*", Role: "frontend", Project: "chorus", Task: "implement"}, uri2: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, expected: true, }, { name: "any role match", uri1: &BzzzURI{Agent: "claude", Role: "any", Project: "chorus", Task: "implement"}, uri2: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, expected: true, }, { name: "no match", uri1: &BzzzURI{Agent: "claude", Role: "backend", Project: "chorus", Task: "implement"}, uri2: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, expected: false, }, { name: "nil comparison", uri1: &BzzzURI{Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement"}, uri2: nil, expected: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.uri1.Matches(tt.uri2) if result != tt.expected { t.Errorf("expected %v, got %v", tt.expected, result) } }) } } func TestBzzzURIString(t *testing.T) { tests := []struct { name string uri *BzzzURI expected string }{ { name: "basic URI", uri: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "/src/main.go", }, expected: "bzzz://claude:frontend@chorus:implement/src/main.go", }, { name: "URI with query and fragment", uri: &BzzzURI{ Agent: "claude", Role: "backend", Project: "bzzz", Task: "debug", Path: "/api/handler.go", Query: "type=error", Fragment: "line123", }, expected: "bzzz://claude:backend@bzzz:debug/api/handler.go?type=error#line123", }, { name: "URI without path", uri: &BzzzURI{ Agent: "any", Role: "architect", Project: "project", Task: "review", }, expected: "bzzz://any:architect@project:review", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.uri.String() if result != tt.expected { t.Errorf("expected %s, got %s", tt.expected, result) } }) } } func TestGetSelectorPriority(t *testing.T) { tests := []struct { name string uri *BzzzURI expected int }{ { name: "all specific", uri: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", Path: "/src/main.go", }, expected: 8 + 4 + 2 + 1 + 1, // All components + path }, { name: "some wildcards", uri: &BzzzURI{ Agent: "*", Role: "frontend", Project: "*", Task: "implement", }, expected: 4 + 1, // Role + Task }, { name: "all wildcards", uri: &BzzzURI{ Agent: "*", Role: "any", Project: "*", Task: "*", }, expected: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := tt.uri.GetSelectorPriority() if result != tt.expected { t.Errorf("expected %d, got %d", tt.expected, result) } }) } } func TestParseAddress(t *testing.T) { tests := []struct { name string addr string expectError bool expected *BzzzURI }{ { name: "valid address", addr: "claude:frontend@chorus:implement", expected: &BzzzURI{ Agent: "claude", Role: "frontend", Project: "chorus", Task: "implement", }, }, { name: "invalid address", addr: "invalid-format", expectError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result, err := ParseAddress(tt.addr) if tt.expectError { if err == nil { t.Errorf("expected error but got none") } return } if err != nil { t.Errorf("unexpected error: %v", err) return } if result.Agent != tt.expected.Agent { t.Errorf("Agent: expected %s, got %s", tt.expected.Agent, result.Agent) } if result.Role != tt.expected.Role { t.Errorf("Role: expected %s, got %s", tt.expected.Role, result.Role) } if result.Project != tt.expected.Project { t.Errorf("Project: expected %s, got %s", tt.expected.Project, result.Project) } if result.Task != tt.expected.Task { t.Errorf("Task: expected %s, got %s", tt.expected.Task, result.Task) } }) } } func TestIsWildcard(t *testing.T) { tests := []struct { component string expected bool }{ {"*", true}, {"any", true}, {"claude", false}, {"frontend", false}, {"", false}, } for _, tt := range tests { t.Run(tt.component, func(t *testing.T) { result := IsWildcard(tt.component) if result != tt.expected { t.Errorf("expected %v, got %v", tt.expected, result) } }) } } func TestValidateBzzzURIString(t *testing.T) { tests := []struct { name string uri string expectError bool }{ { name: "valid URI", uri: "bzzz://claude:frontend@chorus:implement/src/main.go", expectError: false, }, { name: "invalid scheme", uri: "http://claude:frontend@chorus:implement", expectError: true, }, { name: "empty URI", uri: "", expectError: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := ValidateBzzzURIString(tt.uri) if tt.expectError && err == nil { t.Errorf("expected error but got none") } if !tt.expectError && err != nil { t.Errorf("unexpected error: %v", err) } }) } }