package context import ( "context" "strings" "testing" ) func TestNewChineseBundle_ImplementsPromptBundle(t *testing.T) { var _ PromptBundle = NewChineseBundle() } func TestChineseBundle_StaticSectionsCount(t *testing.T) { bundle := NewChineseBundle() sections := bundle.StaticSections() // 与 DefaultBundle 相同数量(9 个静态段落) if len(sections) != 9 { t.Errorf("expected 9 static sections, got %d", len(sections)) } } func TestChineseBundle_StaticSectionsAreInChinese(t *testing.T) { bundle := NewChineseBundle() for _, s := range bundle.StaticSections() { if s.Text == "" { t.Errorf("section %q has empty text", s.Name) continue } // 验证至少包含中文字符(检查几个关键段落) switch s.Name { case "intro", "doing_tasks", "actions", "using_tools", "git_protocol": if !containsChinese(s.Text) { t.Errorf("section %q should contain Chinese characters", s.Name) } } // 静态 section 必须标记为 Static=true if !s.Static { t.Errorf("section %q should have Static=true", s.Name) } } } func TestChineseBundle_DynamicSectionsInherited(t *testing.T) { chinese := NewChineseBundle() def := NewDefaultBundle() chDyn := chinese.DynamicSections() defDyn := def.DynamicSections() // 动态 section 数量应与 DefaultBundle 相同 if len(chDyn) != len(defDyn) { t.Errorf("dynamic sections count: chinese=%d default=%d", len(chDyn), len(defDyn)) } // 动态 section 的 Name 应与 DefaultBundle 一致 for i := range defDyn { if i >= len(chDyn) { break } if chDyn[i].Name != defDyn[i].Name { t.Errorf("dynamic[%d]: chinese=%q default=%q", i, chDyn[i].Name, defDyn[i].Name) } } } func TestChineseBundle_BuildPromptBlocksWorks(t *testing.T) { bundle := NewChineseBundle() ctx := context.Background() reg := NewSectionRegistry() blocks := BuildPromptBlocks(ctx, bundle, reg, false) if len(blocks) == 0 { t.Fatal("BuildPromptBlocks returned empty blocks") } combined := BlocksToString(blocks) if combined == "" { t.Fatal("combined prompt is empty") } // 验证中文内容出现在输出中 if !containsChinese(combined) { t.Error("combined prompt should contain Chinese characters") } } func TestChineseBundleKeys(t *testing.T) { keys := ChineseBundleKeys() if len(keys) == 0 { t.Fatal("ChineseBundleKeys returned empty") } // 所有 key 都应有非空的 ModelFamily 和 Scenario for _, k := range keys { if k.ModelFamily == "" { t.Errorf("key has empty ModelFamily: %+v", k) } if k.Scenario == "" { t.Errorf("key has empty Scenario: %+v", k) } } // 必须包含 qwen+programming found := false for _, k := range keys { if k.ModelFamily == "qwen" && k.Scenario == "programming" { found = true } } if !found { t.Error("ChineseBundleKeys should include {qwen, programming}") } } func TestRegisterChineseBundle(t *testing.T) { reg := NewBundleRegistry() RegisterChineseBundle(reg) for _, key := range ChineseBundleKeys() { bundle := reg.Resolve(key) if bundle == nil { t.Errorf("key %+v not registered", key) } } } func TestChineseBundle_SectionNames(t *testing.T) { bundle := NewChineseBundle() want := []string{"intro", "system", "doing_tasks", "actions", "using_tools", "search_code", "tone_and_style", "output_efficiency", "git_protocol"} got := make([]string, 0) for _, s := range bundle.StaticSections() { got = append(got, s.Name) } if len(got) != len(want) { t.Fatalf("section count: got %d, want %d", len(got), len(want)) } for i, name := range want { if got[i] != name { t.Errorf("section[%d]: got %q, want %q", i, got[i], name) } } } func TestChineseBundle_NoEnglishOnlyPhrases(t *testing.T) { // 验证英文版中的关键措辞被替换为中文版 bundle := NewChineseBundle() for _, s := range bundle.StaticSections() { // 关键英文段落开头不应出现在中文版中 if s.Name == "doing_tasks" && strings.HasPrefix(s.Text, "# Doing tasks") { t.Errorf("doing_tasks section should not start with English '# Doing tasks'") } if s.Name == "intro" && strings.HasPrefix(s.Text, "You are an interactive agent") { t.Errorf("intro section should not start with English text") } } } // containsChinese 检查字符串是否包含中文字符(Unicode CJK 范围). func containsChinese(s string) bool { for _, r := range s { if r >= 0x4E00 && r <= 0x9FFF { return true } } return false }