package query import ( "testing" "time" ) func TestNewTextMsg(t *testing.T) { msg := NewTextMsg(RoleUser, "hello world") if msg.Role != RoleUser { t.Errorf("role = %q, want %q", msg.Role, RoleUser) } if len(msg.Content) != 1 { t.Fatalf("应有 1 个 content block,实际: %d", len(msg.Content)) } if msg.Content[0].Type != ContentText { t.Errorf("type = %q, want %q", msg.Content[0].Type, ContentText) } if msg.Content[0].Text != "hello world" { t.Errorf("text = %q", msg.Content[0].Text) } } func TestNewTextMsg_AllRoles(t *testing.T) { for _, role := range []Role{RoleUser, RoleAssistant, RoleSystem} { msg := NewTextMsg(role, "x") if msg.Role != role { t.Errorf("role mismatch: got %q, want %q", msg.Role, role) } } } func TestContentType_Constants(t *testing.T) { // 验证所有 ContentType 常量值都是预期的 expected := map[ContentType]string{ ContentText: "text", ContentThinking: "thinking", ContentToolUse: "tool_use", ContentToolResult: "tool_result", ContentImage: "image", ContentDocument: "document", } for ct, want := range expected { if string(ct) != want { t.Errorf("%v = %q, want %q", ct, string(ct), want) } } } func TestRole_Constants(t *testing.T) { expected := map[Role]string{ RoleUser: "user", RoleAssistant: "assistant", RoleSystem: "system", } for r, want := range expected { if string(r) != want { t.Errorf("%v = %q, want %q", r, string(r), want) } } } func TestMessage_WithMetadata(t *testing.T) { // Metadata 字段可扩展 msg := Message{ Role: RoleAssistant, Content: []Content{{Type: ContentText, Text: "x"}}, Time: time.Now(), Metadata: map[string]any{ "is_virtual": true, "synthesized": "tool_result", }, } if msg.Metadata["is_virtual"] != true { t.Error("Metadata is_virtual 未保留") } } func TestContent_ToolUse(t *testing.T) { c := Content{ Type: ContentToolUse, ID: "tool_123", Name: "Bash", Input: map[string]any{"command": "ls"}, } if c.Type != ContentToolUse || c.ID != "tool_123" || c.Name != "Bash" { t.Errorf("ToolUse content: %+v", c) } if c.Input["command"] != "ls" { t.Error("Input map 未正确保存") } } func TestContent_ToolResult(t *testing.T) { c := Content{ Type: ContentToolResult, ToolUseID: "tool_123", Text: "output", IsError: false, } if c.Type != ContentToolResult || c.ToolUseID != "tool_123" { t.Errorf("ToolResult content: %+v", c) } // 错误结果 cErr := Content{ Type: ContentToolResult, ToolUseID: "tool_456", Text: "error message", IsError: true, } if !cErr.IsError { t.Error("IsError should be true") } } func TestContent_Image(t *testing.T) { c := Content{ Type: ContentImage, Source: &ContentSource{ Type: "base64", MediaType: "image/png", Data: "iVBORw0KGgo...", }, SizeBytes: 12345, } if c.Type != ContentImage { t.Errorf("type = %q", c.Type) } if c.Source == nil || c.Source.MediaType != "image/png" { t.Error("Source 未正确保存") } if c.SizeBytes != 12345 { t.Errorf("SizeBytes = %d", c.SizeBytes) } } func TestCacheTokens_Struct(t *testing.T) { // 验证 CacheTokens 字段名(不是旧的 CacheReadInputTokens) ct := CacheTokens{ Read: 100, Written: 200, } if ct.Read != 100 || ct.Written != 200 { t.Errorf("CacheTokens: %+v", ct) } } func TestUsage_WithCache(t *testing.T) { u := Usage{ InputTokens: 1000, OutputTokens: 500, Cache: CacheTokens{ Read: 200, Written: 100, }, } if u.InputTokens != 1000 || u.OutputTokens != 500 { t.Errorf("Usage tokens: %+v", u) } if u.Cache.Read != 200 || u.Cache.Written != 100 { t.Errorf("Cache tokens: %+v", u.Cache) } }