package reflux import ( "encoding/json" "reflect" "testing" "git.fsdpf.net/go/reflux/valuex" ) // 测试用的结构体 type Person struct { Name string Age int Email string Address Address Tags []string Meta map[string]string } type Address struct { City string Street string ZipCode int } // TestNew 测试 New 函数 func TestNew(t *testing.T) { t.Run("New with pointer", func(t *testing.T) { // 测试传入指针 - 修改应该影响原始数据 p := Person{Name: "Alice", Age: 30} rfx := New(&p) rfx.Set("Name", "Bob") if p.Name != "Bob" { t.Errorf("Expected original value to be modified, got '%s'", p.Name) } }) t.Run("New with value", func(t *testing.T) { // 测试传入值 - 修改不应该影响原始数据 p := Person{Name: "Alice", Age: 30} rfx := New(p) rfx.Set("Name", "Bob") // 原始值不应该被修改 if p.Name != "Alice" { t.Errorf("Expected original value to remain 'Alice', got '%s'", p.Name) } // rfx 内部的值应该已经修改 if rfx.Get("Name").String() != "Bob" { t.Errorf("Expected rfx value to be 'Bob', got '%s'", rfx.Get("Name").String()) } }) t.Run("New with map pointer", func(t *testing.T) { m := map[string]any{"name": "Alice"} rfx := New(&m) rfx.Set("name", "Bob") if m["name"] != "Bob" { t.Errorf("Expected map to be modified, got '%v'", m["name"]) } }) t.Run("New with map value", func(t *testing.T) { m := map[string]any{"name": "Alice"} rfx := New(m) rfx.Set("name", "Bob") // 原始 map 不应该被修改 if m["name"] != "Alice" { t.Errorf("Expected original map to remain 'Alice', got '%v'", m["name"]) } }) t.Run("New with slice pointer", func(t *testing.T) { s := []string{"a", "b", "c"} rfx := New(&s) rfx.Set("0", "x") if s[0] != "x" { t.Errorf("Expected slice to be modified, got '%s'", s[0]) } }) t.Run("New with slice value", func(t *testing.T) { s := []string{"a", "b", "c"} rfx := New(s) rfx.Set("0", "x") // 原始切片不应该被修改 if s[0] != "a" { t.Errorf("Expected original slice to remain 'a', got '%s'", s[0]) } }) t.Run("New with array value", func(t *testing.T) { a := [3]string{"a", "b", "c"} rfx := New(a) rfx.Set("0", "x") // 原始数组不应该被修改 if a[0] != "a" { t.Errorf("Expected original array to remain 'a', got '%s'", a[0]) } }) t.Run("New with nil pointer", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Expected panic with nil pointer") } }() var p *Person New(p) }) t.Run("New with unsupported type", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Expected panic with unsupported type") } }() New(42) // int 不支持 }) t.Run("New with interface wrapping map", func(t *testing.T) { // 测试 interface{} 包装的 map var data any = map[string]string{"name": "Alice"} rfx := New(data) if rfx.Get("name").String() != "Alice" { t.Errorf("Expected 'Alice', got '%s'", rfx.Get("name").String()) } // 修改不应该影响原始数据(因为是值传递) rfx.Set("name", "Bob") originalMap := data.(map[string]string) if originalMap["name"] != "Alice" { t.Error("Original map should not be modified") } }) t.Run("New with interface wrapping struct", func(t *testing.T) { // 测试 interface{} 包装的 struct var data any = Person{Name: "Alice", Age: 30} rfx := New(data) if rfx.Get("Name").String() != "Alice" { t.Errorf("Expected 'Alice', got '%s'", rfx.Get("Name").String()) } }) t.Run("New with interface wrapping pointer", func(t *testing.T) { // 测试 interface{} 包装的指针 person := Person{Name: "Alice", Age: 30} var data any = &person rfx := New(data) rfx.Set("Name", "Bob") // 原始数据应该被修改(因为是指针) if person.Name != "Bob" { t.Errorf("Expected original to be modified, got '%s'", person.Name) } }) t.Run("New with nil interface", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Expected panic with nil interface") } }() var data any New(data) }) } // TestNewWithPointer 测试传入指针的情况 func TestNewWithPointer(t *testing.T) { p := Person{Name: "Alice", Age: 30} // 测试传入指针值 rfx := New(&p) if rfx == nil { t.Fatal("New() with pointer returned nil") } } // TestGet 测试 Get 方法 func TestGet(t *testing.T) { p := Person{ Name: "Bob", Age: 25, Address: Address{ City: "Beijing", Street: "Main St", }, Tags: []string{"developer", "gopher"}, } rfx := New(&p) // 测试获取顶层字段 name := rfx.Get("Name").String() if name != "Bob" { t.Errorf("Expected 'Bob', got '%s'", name) } // 测试获取嵌套字段 city := rfx.Get("Address", "City").String() if city != "Beijing" { t.Errorf("Expected 'Beijing', got '%s'", city) } // 测试获取切片元素 tag := rfx.Get("Tags", "0").String() if tag != "developer" { t.Errorf("Expected 'developer', got '%s'", tag) } } // TestScope 测试 Scope 方法 func TestScope(t *testing.T) { p := Person{ Address: Address{ City: "Shanghai", Street: "Park Ave", ZipCode: 200000, }, } rfx := New(&p) addressScope := rfx.Scope("Address") // 测试通过 Scope 获取值 city := addressScope.Get("City").String() if city != "Shanghai" { t.Errorf("Expected 'Shanghai', got '%s'", city) } // 测试通过 Scope 设置值后,原对象不应该被修改(因为是深度克隆) addressScope.Set("City", "Beijing") // 验证原对象的值没有改变(深度克隆) if p.Address.City != "Shanghai" { t.Errorf("Expected original object's City to remain 'Shanghai', got '%s'", p.Address.City) } // 验证 Scope 内的值已改变 scopeCity := addressScope.Get("City").String() if scopeCity != "Beijing" { t.Errorf("Expected scope's City to be 'Beijing', got '%s'", scopeCity) } // 验证通过原 rfx 对象获取的值仍然是原值 cityFromOriginal := rfx.Get("Address", "City").String() if cityFromOriginal != "Shanghai" { t.Errorf("Expected 'Shanghai' from original rfx, got '%s'", cityFromOriginal) } // 测试在 Scope 上设置多个字段 addressScope.Set("Street", "New Street").Set("ZipCode", 100000) // 验证原对象的值都没有改变 if p.Address.Street != "Park Ave" { t.Errorf("Expected original Street to remain 'Park Ave', got '%s'", p.Address.Street) } if p.Address.ZipCode != 200000 { t.Errorf("Expected original ZipCode to remain 200000, got %d", p.Address.ZipCode) } // 验证 Scope 内的值已经改变 scopeStreet := addressScope.Get("Street").String() scopeZipCode := addressScope.Get("ZipCode").Int() if scopeStreet != "New Street" { t.Errorf("Expected scope's Street to be 'New Street', got '%s'", scopeStreet) } if scopeZipCode != 100000 { t.Errorf("Expected scope's ZipCode to be 100000, got %d", scopeZipCode) } // 再次验证 Scope 的值与原对象不同(证明是深度克隆) if scopeCity == p.Address.City { t.Error("Scope should have independent copy, not reference to original") } } // TestSet 测试 Set 方法 func TestSet(t *testing.T) { p := Person{ Name: "Charlie", Age: 30, Address: Address{ City: "Guangzhou", }, Meta: make(map[string]string), } rfx := New(&p) // 测试设置顶层字段 rfx.Set("Name", "David") if p.Name != "David" { t.Errorf("Expected 'David', got '%s'", p.Name) } // 测试设置嵌套字段 rfx.Set("Address.City", "Shenzhen") if p.Address.City != "Shenzhen" { t.Errorf("Expected 'Shenzhen', got '%s'", p.Address.City) } // 测试设置 map 值 rfx.Set("Meta.key1", "value1") if p.Meta["key1"] != "value1" { t.Errorf("Expected 'value1', got '%s'", p.Meta["key1"]) } // 测试类型转换 rfx.Set("Age", int32(35)) if p.Age != 35 { t.Errorf("Expected 35, got %d", p.Age) } // 测试设置整个 Address 结构体 newAddress := Address{ City: "Shanghai", Street: "Nanjing Road", ZipCode: 200000, } rfx.Set("Address", newAddress) if p.Address.City != "Shanghai" { t.Errorf("Expected City 'Shanghai', got '%s'", p.Address.City) } if p.Address.Street != "Nanjing Road" { t.Errorf("Expected Street 'Nanjing Road', got '%s'", p.Address.Street) } if p.Address.ZipCode != 200000 { t.Errorf("Expected ZipCode 200000, got %d", p.Address.ZipCode) } // 测试设置 Address 结构体后再修改其字段 rfx.Set("Address.ZipCode", 200001) if p.Address.ZipCode != 200001 { t.Errorf("Expected ZipCode 200001, got %d", p.Address.ZipCode) } } // TestDelete 测试 Delete 方法 func TestDelete(t *testing.T) { meta := map[string]string{ "key1": "value1", "key2": "value2", } p := Person{ Meta: meta, Tags: []string{"tag1", "tag2", "tag3"}, } rfx := New(&p) // 测试删除 map 键 rfx.Delete("Meta", "key1") if _, exists := p.Meta["key1"]; exists { t.Error("key1 should have been deleted") } // 测试删除切片元素 rfx.Delete("Tags", "1") if len(p.Tags) != 2 || p.Tags[1] != "tag3" { t.Errorf("Expected Tags to be ['tag1', 'tag3'], got %v", p.Tags) } } // TestExists 测试 Exists 方法 func TestExists(t *testing.T) { p := Person{ Name: "Eve", Address: Address{ City: "Hangzhou", }, } rfx := New(&p) // 测试存在的字段 if !rfx.Exists("Name") { t.Error("Name should exist") } // 测试嵌套字段 if !rfx.Exists("Address", "City") { t.Error("Address.City should exist") } // 测试不存在的字段 if rfx.Exists("NonExistent") { t.Error("NonExistent should not exist") } // 测试空字段 if rfx.Exists("Email") { // Email 是空字符串,但字段存在 email := rfx.Get("Email").String() if email != "" { t.Error("Email should be empty string") } } } // TestArray 测试 Array 方法 func TestArray(t *testing.T) { tags := []string{"go", "rust", "python"} p := Person{ Tags: tags, } rfx := New(&p) arr := rfx.Get("Tags").Array() if len(arr) != 3 { t.Errorf("Expected array length 3, got %d", len(arr)) } if arr[0].String() != "go" { t.Errorf("Expected 'go', got '%s'", arr[0].String()) } } // TestKeys 测试 keys 方法 func TestKeys(t *testing.T) { meta := map[string]string{ "key1": "value1", "key2": "value2", "key3": "value3", } p := Person{ Meta: meta, } rfx := New(&p) keys := rfx.Get("Meta").Keys() if len(keys) != 3 { t.Errorf("Expected 3 keys, got %d", len(keys)) } // 检查键是否存在 keyMap := make(map[string]bool) for _, k := range keys { keyMap[k] = true } if !keyMap["key1"] || !keyMap["key2"] || !keyMap["key3"] { t.Error("Missing expected keys") } } // TestTypeConversions 测试类型转换方法 func TestTypeConversions(t *testing.T) { // 测试整数转换 type Numbers struct { IntVal int Int64Val int64 UintVal uint FloatVal float64 BoolVal bool StringVal string } n := Numbers{ IntVal: 42, Int64Val: 9223372036854775807, UintVal: 100, FloatVal: 3.14, BoolVal: true, StringVal: "hello", } rfx := New(&n) // Int if rfx.Get("IntVal").Int() != 42 { t.Error("Int() conversion failed") } // Int64 if rfx.Get("Int64Val").Int64() != 9223372036854775807 { t.Error("Int64() conversion failed") } // Uint if rfx.Get("UintVal").Uint() != 100 { t.Error("Uint() conversion failed") } // Float64 if rfx.Get("FloatVal").Float64() != 3.14 { t.Error("Float64() conversion failed") } // Bool if !rfx.Get("BoolVal").Bool() { t.Error("Bool() conversion failed") } // String if rfx.Get("StringVal").String() != "hello" { t.Error("String() conversion failed") } // 跨类型转换 if rfx.Get("IntVal").Float64() != 42.0 { t.Error("Int to Float64 conversion failed") } if rfx.Get("FloatVal").Int64() != 3 { t.Error("Float64 to Int64 conversion failed") } } // TestStringMapConversions 测试 map 类型转换 func TestStringMapConversions(t *testing.T) { type Maps struct { StringMap map[string]string IntMap map[string]int BoolMap map[string]bool StringSliceMap map[string][]string } m := Maps{ StringMap: map[string]string{ "name": "Alice", "city": "NYC", }, IntMap: map[string]int{ "age": 30, "score": 100, }, BoolMap: map[string]bool{ "active": true, "enabled": false, }, StringSliceMap: map[string][]string{ "tags": {"go", "rust"}, }, } rfx := New(&m) // StringMapString strMap := rfx.Get("StringMap").StringMapString() if strMap["name"] != "Alice" { t.Error("StringMapString conversion failed") } // StringMapInt intMap := rfx.Get("IntMap").StringMapInt() if intMap["age"] != 30 { t.Error("StringMapInt conversion failed") } // StringMapBool boolMap := rfx.Get("BoolMap").StringMapBool() if !boolMap["active"] { t.Error("StringMapBool conversion failed") } // StringMapStringSlice sliceMap := rfx.Get("StringSliceMap").StringMapStringSlice() if len(sliceMap["tags"]) != 2 || sliceMap["tags"][0] != "go" { t.Error("StringMapStringSlice conversion failed") } } // TestSliceConversions 测试切片类型转换 func TestSliceConversions(t *testing.T) { type Slices struct { IntSlice []int StringSlice []string BoolSlice []bool } s := Slices{ IntSlice: []int{1, 2, 3}, StringSlice: []string{"a", "b", "c"}, BoolSlice: []bool{true, false, true}, } rfx := New(&s) // IntSlice intSlice := rfx.Get("IntSlice").IntSlice() if len(intSlice) != 3 || intSlice[1] != 2 { t.Error("IntSlice conversion failed") } // StringSlice strSlice := rfx.Get("StringSlice").StringSlice() if len(strSlice) != 3 || strSlice[1] != "b" { t.Error("StringSlice conversion failed") } // BoolSlice boolSlice := rfx.Get("BoolSlice").BoolSlice() if len(boolSlice) != 3 || boolSlice[1] != false { t.Error("BoolSlice conversion failed") } // Slice (any) anySlice := rfx.Get("IntSlice").Slice() if len(anySlice) != 3 { t.Error("Slice conversion failed") } } // TestPtr 测试 Ptr 方法 func TestPtr(t *testing.T) { p := Person{Name: "Frank"} rfx := New(&p) ptr := rfx.Ptr() if ptr == nil { t.Error("Ptr() returned nil") } // 验证指针指向正确的对象 if pPtr, ok := ptr.(*Person); ok { if pPtr.Name != "Frank" { t.Error("Ptr() returned incorrect pointer") } } else { t.Error("Ptr() returned wrong type") } } // TestGetPtrWithJSONUnmarshal 测试 Get().Ptr() 与 json.Unmarshal() 的配合 func TestGetPtrWithJSONUnmarshal(t *testing.T) { t.Run("Unmarshal to nested struct field", func(t *testing.T) { p := Person{ Name: "Alice", Age: 30, Address: Address{ City: "OldCity", }, } rfx := New(&p) // 准备 JSON 数据 jsonData := []byte(`{ "City": "Shanghai", "Street": "Nanjing Road", "ZipCode": 200000 }`) // 通过 Get().Ptr() 获取 Address 字段的指针 addressPtr := rfx.Get("Address").Ptr() if addressPtr == nil { t.Fatal("Get('Address').Ptr() returned nil") } // 使用 json.Unmarshal 直接赋值 err := json.Unmarshal(jsonData, addressPtr) if err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } // 验证赋值成功 if p.Address.City != "Shanghai" { t.Errorf("Expected City 'Shanghai', got '%s'", p.Address.City) } if p.Address.Street != "Nanjing Road" { t.Errorf("Expected Street 'Nanjing Road', got '%s'", p.Address.Street) } if p.Address.ZipCode != 200000 { t.Errorf("Expected ZipCode 200000, got %d", p.Address.ZipCode) } }) t.Run("Unmarshal to top-level struct", func(t *testing.T) { p := Person{ Name: "Bob", Age: 25, } rfx := New(&p) // 准备 JSON 数据 jsonData := []byte(`{ "Name": "Charlie", "Age": 35, "Email": "charlie@example.com" }`) // 通过 Ptr() 获取整个 Person 的指针 personPtr := rfx.Ptr() if personPtr == nil { t.Fatal("Ptr() returned nil") } // 使用 json.Unmarshal 直接赋值 err := json.Unmarshal(jsonData, personPtr) if err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } // 验证赋值成功 if p.Name != "Charlie" { t.Errorf("Expected Name 'Charlie', got '%s'", p.Name) } if p.Age != 35 { t.Errorf("Expected Age 35, got %d", p.Age) } if p.Email != "charlie@example.com" { t.Errorf("Expected Email 'charlie@example.com', got '%s'", p.Email) } }) t.Run("Unmarshal to map field", func(t *testing.T) { p := Person{ Name: "Dave", Meta: make(map[string]string), } rfx := New(&p) // 准备 JSON 数据 jsonData := []byte(`{ "key1": "value1", "key2": "value2", "key3": "value3" }`) // 通过 Get().Ptr() 获取 Meta 字段的指针 metaPtr := rfx.Get("Meta").Ptr() if metaPtr == nil { t.Fatal("Get('Meta').Ptr() returned nil") } // 使用 json.Unmarshal 直接赋值 err := json.Unmarshal(jsonData, metaPtr) if err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } // 验证赋值成功 if p.Meta["key1"] != "value1" { t.Errorf("Expected Meta['key1'] 'value1', got '%s'", p.Meta["key1"]) } if p.Meta["key2"] != "value2" { t.Errorf("Expected Meta['key2'] 'value2', got '%s'", p.Meta["key2"]) } if p.Meta["key3"] != "value3" { t.Errorf("Expected Meta['key3'] 'value3', got '%s'", p.Meta["key3"]) } }) t.Run("Unmarshal to slice field", func(t *testing.T) { p := Person{ Name: "Eve", Tags: []string{"old1", "old2"}, } rfx := New(&p) // 准备 JSON 数据 jsonData := []byte(`["tag1", "tag2", "tag3"]`) // 通过 Get().Ptr() 获取 Tags 字段的指针 tagsPtr := rfx.Get("Tags").Ptr() if tagsPtr == nil { t.Fatal("Get('Tags').Ptr() returned nil") } // 使用 json.Unmarshal 直接赋值 err := json.Unmarshal(jsonData, tagsPtr) if err != nil { t.Fatalf("json.Unmarshal failed: %v", err) } // 验证赋值成功 if len(p.Tags) != 3 { t.Errorf("Expected Tags length 3, got %d", len(p.Tags)) } if p.Tags[0] != "tag1" || p.Tags[1] != "tag2" || p.Tags[2] != "tag3" { t.Errorf("Expected Tags ['tag1', 'tag2', 'tag3'], got %v", p.Tags) } }) } // TestAny 测试 Any 方法 func TestAny(t *testing.T) { p := Person{Name: "Grace", Age: 28} rfx := New(&p) anyVal := rfx.Any() if person, ok := anyVal.(Person); ok { if person.Name != "Grace" || person.Age != 28 { t.Error("Any() returned incorrect value") } } else { t.Error("Any() returned wrong type") } } // TestRaw 测试 Value 方法 func TestRaw(t *testing.T) { p := Person{Name: "Henry"} rfx := New(&p) val := rfx.Raw() if !val.IsValid() { t.Error("Value() returned invalid value") } if val.Kind() != 22 { // reflect.Ptr t.Errorf("Expected pointer kind, got %v", val.Kind()) } } // TestComplexNesting 测试复杂嵌套场景 func TestComplexNesting(t *testing.T) { type Company struct { Name string Employees []Person } company := Company{ Name: "TechCorp", Employees: []Person{ {Name: "Alice", Age: 30}, {Name: "Bob", Age: 25}, }, } rfx := New(&company) // 获取嵌套数组中的值 empName := rfx.Get("Employees", "0", "Name").String() if empName != "Alice" { t.Errorf("Expected 'Alice', got '%s'", empName) } // 设置嵌套数组中的值 rfx.Set("Employees.0.Age", 31) if company.Employees[0].Age != 31 { t.Errorf("Expected 31, got %d", company.Employees[0].Age) } } // TestEdgeCases 测试边界情况 func TestEdgeCases(t *testing.T) { p := Person{} rfx := New(&p) // 测试空值 emptyStr := rfx.Get("Name").String() if emptyStr != "" { t.Error("Empty string should be returned") } // 测试不存在的路径 nonExistent := rfx.Get("NonExistent", "Field").String() if nonExistent != "" { t.Error("Non-existent path should return empty string") } // 测试初始化的 nil map(结构体字段默认为 nil) metaMap := rfx.Get("Meta").StringMapString() // nil map 会返回 nil,这是正确的行为 _ = metaMap // 测试 nil 切片(结构体字段默认为 nil) tags := rfx.Get("Tags").StringSlice() // nil slice 会返回 nil,这是正确的行为 _ = tags // 测试设置到不存在的路径应该 panic defer func() { if r := recover(); r == nil { t.Error("Setting non-existent field should panic") } }() rfx.Set("NonExistent", "value") // 应该 panic } // TestMapOperations 测试 map 操作 func TestMapOperations(t *testing.T) { m := map[string]any{ "name": "Alice", "age": 30, "tags": []string{"go", "rust"}, } rfx := New(&m) // Get from map name := rfx.Get("name").String() if name != "Alice" { t.Errorf("Expected 'Alice', got '%s'", name) } // Set to map rfx.Set("name", "Bob") if m["name"] != "Bob" { t.Errorf("Expected 'Bob', got '%v'", m["name"]) } // Add new key rfx.Set("age", 35) // Delete from map rfx.Delete("age") if _, exists := m["age"]; exists { t.Error("Key should have been deleted") } } // BenchmarkGet 性能测试 Get 方法 func BenchmarkGet(b *testing.B) { p := Person{ Name: "Benchmark", Address: Address{ City: "TestCity", }, } rfx := New(&p) b.ResetTimer() for i := 0; i < b.N; i++ { _ = rfx.Get("Address", "City").String() } } // BenchmarkSet 性能测试 Set 方法 func BenchmarkSet(b *testing.B) { p := Person{} rfx := New(&p) b.ResetTimer() for i := 0; i < b.N; i++ { rfx.Set("Name", "TestName") } } // TestDotNotationPath 测试点号分割路径 func TestDotNotationPath(t *testing.T) { p := Person{ Name: "Alice", Age: 30, Address: Address{ City: "Beijing", Street: "Main St", ZipCode: 100000, }, Tags: []string{"go", "rust", "python"}, Meta: map[string]string{ "level": "senior", }, } rfx := New(&p) // 测试点号分割路径获取 t.Run("Get with dot notation", func(t *testing.T) { // 使用点号访问嵌套字段 city := rfx.Get("Address.City").String() if city != "Beijing" { t.Errorf("Expected 'Beijing', got '%s'", city) } zipCode := rfx.Get("Address.ZipCode").Int() if zipCode != 100000 { t.Errorf("Expected 100000, got %d", zipCode) } }) // 测试混合使用点号和分隔参数 t.Run("Get with mixed notation", func(t *testing.T) { city := rfx.Get("Address.City").String() if city != "Beijing" { t.Errorf("Expected 'Beijing', got '%s'", city) } // 混合使用 metaLevel := rfx.Get("Meta", "level").String() if metaLevel != "senior" { t.Errorf("Expected 'senior', got '%s'", metaLevel) } // 也可以用点号访问 Map metaLevel2 := rfx.Get("Meta.level").String() if metaLevel2 != "senior" { t.Errorf("Expected 'senior', got '%s'", metaLevel2) } }) // 测试访问切片元素 t.Run("Get array with dot notation", func(t *testing.T) { tag := rfx.Get("Tags.0").String() if tag != "go" { t.Errorf("Expected 'go', got '%s'", tag) } tag2 := rfx.Get("Tags.1").String() if tag2 != "rust" { t.Errorf("Expected 'rust', got '%s'", tag2) } }) // 测试 Set 使用点号路径 t.Run("Set with dot notation", func(t *testing.T) { rfx.Set("Address.City", "Shanghai") if p.Address.City != "Shanghai" { t.Errorf("Expected 'Shanghai', got '%s'", p.Address.City) } rfx.Set("Address.ZipCode", 200000) if p.Address.ZipCode != 200000 { t.Errorf("Expected 200000, got %d", p.Address.ZipCode) } }) // 测试 Exists 使用点号路径 t.Run("Exists with dot notation", func(t *testing.T) { if !rfx.Exists("Address.City") { t.Error("Address.City should exist") } if rfx.Exists("Address.NonExistent") { t.Error("Address.NonExistent should not exist") } }) // 测试 Delete 使用点号路径 t.Run("Delete with dot notation", func(t *testing.T) { rfx.Delete("Meta.level") if _, exists := p.Meta["level"]; exists { t.Error("Meta.level should have been deleted") } }) // 测试 Scope 使用点号路径 t.Run("Scope with dot notation", func(t *testing.T) { addressScope := rfx.Scope("Address") city := addressScope.Get("City").String() if city != "Shanghai" { t.Errorf("Expected 'Shanghai', got '%s'", city) } }) } // TestExpandPath 测试路径展开功能 func TestExpandPath(t *testing.T) { tests := []struct { name string input []string expected []string }{ { name: "Simple path", input: []string{"a", "b", "c"}, expected: []string{"a", "b", "c"}, }, { name: "Dot notation", input: []string{"a.b.c"}, expected: []string{"a", "b", "c"}, }, { name: "Mixed notation", input: []string{"a.b", "c"}, expected: []string{"a", "b", "c"}, }, { name: "Multiple dots", input: []string{"a.b", "c.d", "e"}, expected: []string{"a", "b", "c", "d", "e"}, }, { name: "Empty segments", input: []string{"a..b", "c"}, expected: []string{"a", "b", "c"}, }, { name: "Leading/trailing dots", input: []string{".a.b.", "c"}, expected: []string{"a", "b", "c"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := expandPath(tt.input...) if len(result) != len(tt.expected) { t.Errorf("Expected length %d, got %d", len(tt.expected), len(result)) return } for i := range result { if result[i] != tt.expected[i] { t.Errorf("At index %d: expected '%s', got '%s'", i, tt.expected[i], result[i]) } } }) } } // TestComplexDotNotation 测试复杂的点号路径场景 func TestComplexDotNotation(t *testing.T) { type Company struct { Name string Address Address CEO Person } company := Company{ Name: "TechCorp", Address: Address{ City: "Beijing", Street: "Tech Street", }, CEO: Person{ Name: "John Doe", Age: 45, Address: Address{ City: "Shanghai", }, }, } rfx := New(&company) // 深层嵌套访问 ceoCity := rfx.Get("CEO.Address.City").String() if ceoCity != "Shanghai" { t.Errorf("Expected 'Shanghai', got '%s'", ceoCity) } // 设置深层嵌套值 rfx.Set("CEO.Address.City", "Guangzhou") if company.CEO.Address.City != "Guangzhou" { t.Errorf("Expected 'Guangzhou', got '%s'", company.CEO.Address.City) } // 检查深层路径存在性 if !rfx.Exists("CEO.Address.City") { t.Error("CEO.Address.City should exist") } } // TestScopeSetIssue 测试 Scope 深度克隆的特性 func TestScopeSetIssue(t *testing.T) { p := Person{ Name: "Alice", Address: Address{ City: "Beijing", }, } rfx := New(&p) // 测试直接通过路径设置值 - 这应该可以工作 t.Run("Direct path set", func(t *testing.T) { rfx.Set("Address.City", "Shanghai") if p.Address.City != "Shanghai" { t.Errorf("Expected 'Shanghai', got '%s'", p.Address.City) } }) // 测试通过 Scope 设置值 - 由于是深度克隆,不会修改原始值 t.Run("Scope set - deep clone behavior", func(t *testing.T) { addressScope := rfx.Scope("Address") originalCity := p.Address.City // "Shanghai" // 在 Scope 上设置值 addressScope.Set("City", "Guangzhou") // 原始值不应该被修改(因为 Scope 返回深度克隆) if p.Address.City != originalCity { t.Errorf("Original value should remain '%s', got '%s'", originalCity, p.Address.City) } // Scope 内的值应该已经改变 scopeCity := addressScope.Get("City").String() if scopeCity != "Guangzhou" { t.Errorf("Scope value should be 'Guangzhou', got '%s'", scopeCity) } }) // 测试获取 Scope 的值是独立副本 t.Run("Scope returns independent copy", func(t *testing.T) { // 获取 Address 的 Scope addressScope := rfx.Scope("Address") // 获取 Scope 的 Any 值 addr := addressScope.Any() if address, ok := addr.(Address); ok { originalCity := p.Address.City // 修改 Scope 返回的值 addressScope.Set("City", "TestCity") // 原始值不应该被修改 if p.Address.City != originalCity { t.Errorf("Modifying scope should not affect original, expected '%s', got '%s'", originalCity, p.Address.City) } // 确保 address 变量本身也是副本 _ = address } }) // 测试嵌套 Scope 的深度克隆 t.Run("Nested scope deep clone", func(t *testing.T) { p2 := Person{ Name: "Bob", Age: 25, Address: Address{ City: "Beijing", Street: "Main St", ZipCode: 100000, }, } sm2 := New(&p2) // 创建 Scope scope := sm2.Scope("Address") // 在 Scope 上修改多个字段 scope.Set("City", "Shenzhen") scope.Set("Street", "New Street") scope.Set("ZipCode", 518000) // 验证原始对象没有被修改 if p2.Address.City != "Beijing" { t.Errorf("Original City should be 'Beijing', got '%s'", p2.Address.City) } if p2.Address.Street != "Main St" { t.Errorf("Original Street should be 'Main St', got '%s'", p2.Address.Street) } if p2.Address.ZipCode != 100000 { t.Errorf("Original ZipCode should be 100000, got %d", p2.Address.ZipCode) } // 验证 Scope 内的值已改变 if scope.Get("City").String() != "Shenzhen" { t.Errorf("Scope City should be 'Shenzhen', got '%s'", scope.Get("City").String()) } }) } // TestScopeDeepClone 测试 Scope 深度克隆复杂嵌套结构 func TestScopeDeepClone(t *testing.T) { type Company struct { Name string Employees []Person Locations map[string]Address } company := Company{ Name: "TechCorp", Employees: []Person{ { Name: "Alice", Age: 30, Address: Address{ City: "Beijing", Street: "Main St", }, Tags: []string{"go", "rust"}, }, { Name: "Bob", Age: 25, Address: Address{ City: "Shanghai", }, }, }, Locations: map[string]Address{ "hq": { City: "Beijing", Street: "Tech Park", ZipCode: 100000, }, }, } rfx := New(&company) t.Run("Clone and modify nested slice", func(t *testing.T) { // 创建 Employees 的 Scope empScope := rfx.Scope("Employees") // 修改 Scope 中的值 empScope.Set("0.Name", "Charlie") empScope.Set("0.Age", 35) // 验证原始数据没有被修改 if company.Employees[0].Name != "Alice" { t.Errorf("Original employee name should be 'Alice', got '%s'", company.Employees[0].Name) } if company.Employees[0].Age != 30 { t.Errorf("Original employee age should be 30, got %d", company.Employees[0].Age) } // 验证 Scope 中的值已修改 if empScope.Get("0", "Name").String() != "Charlie" { t.Error("Scope employee name should be 'Charlie'") } }) t.Run("Clone and modify nested map", func(t *testing.T) { // 创建 Locations 的 Scope locScope := rfx.Scope("Locations") // 修改 Scope 中的值 locScope.Set("hq.City", "Shanghai").Set("hq.ZipCode", 200000) // 验证原始数据没有被修改 if company.Locations["hq"].City != "Beijing" { t.Errorf("Original location city should be 'Beijing', got '%s'", company.Locations["hq"].City) } if company.Locations["hq"].ZipCode != 100000 { t.Errorf("Original location zipcode should be 100000, got %d", company.Locations["hq"].ZipCode) } // 验证 Scope 中的值已修改 if locScope.Get("hq", "City").String() != "Shanghai" { t.Error("Scope location city should be 'Shanghai'") } if locScope.Get("hq", "ZipCode").Int() != 200000 { t.Error("Scope location zipcode should be 200000") } }) t.Run("Clone nested struct with slices", func(t *testing.T) { // 创建第一个员工的 Scope emp0Scope := rfx.Scope("Employees", "0") // 修改嵌套的切片 emp0Scope.Set("Tags.0", "python") // 验证原始数据没有被修改 if company.Employees[0].Tags[0] != "go" { t.Errorf("Original tag should be 'go', got '%s'", company.Employees[0].Tags[0]) } // 验证 Scope 中的值已修改 if emp0Scope.Get("Tags", "0").String() != "python" { t.Error("Scope tag should be 'python'") } }) } // TestSetValueWithCastInStruct 测试在实际结构体中使用 cast 转换 func TestSetValueWithCastInStruct(t *testing.T) { type Config struct { Port int Host string Enabled bool Timeout float64 } config := Config{} rfx := New(&config) // 字符串转 int rfx.Set("Port", "8080") if config.Port != 8080 { t.Errorf("Expected Port to be 8080, got %d", config.Port) } // int 转 string rfx.Set("Host", 12345) if config.Host != "12345" { t.Errorf("Expected Host to be '12345', got '%s'", config.Host) } // 字符串转 bool rfx.Set("Enabled", "true") if !config.Enabled { t.Errorf("Expected Enabled to be true, got %v", config.Enabled) } // 字符串转 float rfx.Set("Timeout", "30.5") if config.Timeout != 30.5 { t.Errorf("Expected Timeout to be 30.5, got %f", config.Timeout) } } // TestSetValueChainWithCast 测试链式调用中的 cast 转换 func TestSetValueChainWithCast(t *testing.T) { type User struct { Name string Age int Active bool Score float64 } user := User{} rfx := New(&user) // 链式设置,使用不同类型的值 rfx.Set("Name", 12345). // int -> string Set("Age", "30"). // string -> int Set("Active", "1"). // string -> bool Set("Score", "95.5") // string -> float64 if user.Name != "12345" { t.Errorf("Expected Name to be '12345', got '%s'", user.Name) } if user.Age != 30 { t.Errorf("Expected Age to be 30, got %d", user.Age) } if !user.Active { t.Errorf("Expected Active to be true, got %v", user.Active) } if user.Score != 95.5 { t.Errorf("Expected Score to be 95.5, got %f", user.Score) } } // TestNormalizeValuexAccessor 测试 normalizeInputValue 对 valuex.Accessor 的支持 func TestNormalizeValuexAccessor(t *testing.T) { // 创建一个 R 实例 data := map[string]any{ "name": "Alice", "age": 30, } r := New(data) // 测试 valuex.Accessor 类型 rv, isPtr, err := normalizeInputValue(r) if err != nil { t.Fatalf("normalizeInputValue failed: %v", err) } if !isPtr { t.Error("Expected isPtr to be true for valuex.Accessor") } if !rv.IsValid() { t.Error("Expected valid reflect.Value") } } // TestNormalizeValuexAccessorSlice 测试 normalizeInputValue 对 []valuex.Accessor 的支持 func TestNormalizeValuexAccessorSlice(t *testing.T) { // 创建多个 R 实例 r1 := New(map[string]any{"id": 1, "name": "Alice"}) r2 := New(map[string]any{"id": 2, "name": "Bob"}) // 创建 []valuex.Accessor slice := []valuex.Accessor{r1, r2} // 测试 []valuex.Accessor 类型 rv, isPtr, err := normalizeInputValue(slice) if err != nil { t.Fatalf("normalizeInputValue failed: %v", err) } if !isPtr { t.Error("Expected isPtr to be true for []valuex.Accessor") } if !rv.IsValid() { t.Error("Expected valid reflect.Value") } if rv.Kind() != reflect.Slice { t.Errorf("Expected Slice kind, got %v", rv.Kind()) } if rv.Len() != 2 { t.Errorf("Expected slice length 2, got %d", rv.Len()) } }