package reflux import ( "reflect" "sort" "testing" ) // Keys() 的 map 分支现在按键类型分支: 字符串键直接取, 其余仍走 fmt.Sprint。 // 这一组守的是"分支之后行为不变" —— 尤其是非字符串键不能退化成 // k.String() 的 "" 占位串。 type keyStr string func TestKeysMatchesLegacy(t *testing.T) { type inner struct{ A, B string } cases := []struct { name string val func() any }{ {"string 键 map", func() any { return &map[string]int{"b": 2, "a": 1, "c": 3} }}, {"具名 string 键 map", func() any { return &map[keyStr]int{"b": 2, "a": 1} }}, {"int 键 map", func() any { return &map[int]string{2: "b", 1: "a", 10: "j"} }}, {"int64 键 map", func() any { return &map[int64]string{7: "x"} }}, {"float 键 map", func() any { return &map[float64]string{1.5: "x"} }}, {"bool 键 map", func() any { return &map[bool]string{true: "t", false: "f"} }}, {"空 map", func() any { return &map[string]int{} }}, {"nil map", func() any { var m map[string]int; return &m }}, {"struct", func() any { return &inner{} }}, {"切片(两边都不支持)", func() any { return &[]string{"a"} }}, {"map 里的 map", func() any { return &map[string]any{"sub": map[string]any{"x": 1}} }}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { want := newLegacy(c.val()).Keys() got := New(c.val()).Keys() // map 迭代顺序随机, 比较前排序 sort.Strings(want) sort.Strings(got) if !reflect.DeepEqual(want, got) { t.Fatalf("Keys() 不一致\n 旧 = %#v\n 新 = %#v", want, got) } }) } } // 经路径取到的 map / interface 包着的 map 也要正确 func TestKeysThroughPath(t *testing.T) { doc := &struct { Meta map[string]string Any any Ptr *map[string]string }{ Meta: map[string]string{"k1": "v", "k2": "v"}, Any: map[string]string{"a1": "v"}, } m := map[string]string{"p1": "v"} doc.Ptr = &m r, l := New(doc), newLegacy(doc) for _, p := range []string{"Meta", "Any", "Ptr"} { t.Run(p, func(t *testing.T) { want, got := l.Get(p).Keys(), r.Get(p).Keys() sort.Strings(want) sort.Strings(got) if !reflect.DeepEqual(want, got) { t.Fatalf("Get(%q).Keys() 不一致\n 旧 = %#v\n 新 = %#v", p, want, got) } if len(got) == 0 { t.Fatalf("Get(%q).Keys() 不该为空", p) } }) } } // 非字符串键必须是键本身的值, 不能是 "" 这种占位串 func TestKeysNonStringKeysAreReal(t *testing.T) { got := New(&map[int]string{42: "x"}).Keys() if len(got) != 1 || got[0] != "42" { t.Fatalf("int 键的 Keys() = %#v, 期望 [\"42\"]", got) } if got := New(&map[bool]string{true: "x"}).Keys(); len(got) != 1 || got[0] != "true" { t.Fatalf("bool 键的 Keys() = %#v, 期望 [\"true\"]", got) } }