reflux/rfx_append_test.go
what bacec92841 feat: Append 方法支持 R 接口包装的指针类型
增强 setValue 函数,支持将 R 接口包装的指针值追加到非指针类型的切片中。当源值是指针但目标不是指针时,自动解引用后再赋值,使得 New(&item) 可以追加到 []Item 类型的切片。同时统一使用 Raw() 方法替代 Value() 方法名。
2025-12-08 17:24:45 +08:00

248 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package reflux
import (
"testing"
)
// TestAppendWithRInterface 测试 Append 方法对 R 接口的支持
func TestAppendWithRInterface(t *testing.T) {
t.Run("Append R interface to slice", func(t *testing.T) {
type Item struct {
Name string
Value int
}
items := []Item{}
rfx := New(&items)
// 创建 R 实例
item1 := Item{Name: "apple", Value: 10}
r1 := New(&item1)
item2 := Item{Name: "banana", Value: 20}
r2 := New(item2)
// 使用 Append 添加 R 接口
rfx.Append(r1, r2)
if len(items) != 2 {
t.Fatalf("Expected 2 items, got %d", len(items))
}
if items[0].Name != "apple" || items[0].Value != 10 {
t.Errorf("Item[0] mismatch: got %+v", items[0])
}
if items[1].Name != "banana" || items[1].Value != 20 {
t.Errorf("Item[1] mismatch: got %+v", items[1])
}
})
t.Run("Append mixed types including R interface", func(t *testing.T) {
type Number struct {
Value int
}
numbers := []int{}
rfx := New(&numbers)
// 创建 R 实例包装 map使用 map 代替基本类型)
numMap := map[string]int{"value": 42}
rNum := New(&numMap)
// 混合添加普通值和通过 Get 提取的值
rfx.Append(10, rNum.Get("value").Int(), 30)
if len(numbers) != 3 {
t.Fatalf("Expected 3 numbers, got %d", len(numbers))
}
if numbers[0] != 10 || numbers[1] != 42 || numbers[2] != 30 {
t.Errorf("Numbers mismatch: got %v", numbers)
}
})
t.Run("Append with nested R interface", func(t *testing.T) {
type Address struct {
City string
}
addresses := []Address{}
rfx := New(&addresses)
// 创建嵌套的 R 实例
addr := Address{City: "Beijing"}
rAddr := New(&addr)
rfx.Append(rAddr)
if len(addresses) != 1 {
t.Fatalf("Expected 1 address, got %d", len(addresses))
}
if addresses[0].City != "Beijing" {
t.Errorf("Expected City=Beijing, got %s", addresses[0].City)
}
})
t.Run("Append map through R interface", func(t *testing.T) {
type Config map[string]string
configs := []Config{}
rfx := New(&configs)
// 创建 map 的 R 实例
cfg := Config{"host": "localhost", "port": "8080"}
rCfg := New(&cfg)
rfx.Append(rCfg)
if len(configs) != 1 {
t.Fatalf("Expected 1 config, got %d", len(configs))
}
if configs[0]["host"] != "localhost" || configs[0]["port"] != "8080" {
t.Errorf("Config mismatch: got %+v", configs[0])
}
})
}
// TestSetWithAutoInit 测试 Set 方法的自动初始化功能
func TestSetWithAutoInit(t *testing.T) {
t.Run("Auto init nil map", func(t *testing.T) {
type Container struct {
Data map[string]string
}
container := Container{}
rfx := New(&container)
// 设置 nil map 的值,应该自动初始化
rfx.Set("Data.key1", "value1")
rfx.Set("Data.key2", "value2")
if container.Data == nil {
t.Fatal("Expected Data to be initialized, got nil")
}
if container.Data["key1"] != "value1" {
t.Errorf("Expected key1=value1, got %s", container.Data["key1"])
}
if container.Data["key2"] != "value2" {
t.Errorf("Expected key2=value2, got %s", container.Data["key2"])
}
})
t.Run("Auto init nested nil map", func(t *testing.T) {
type Nested struct {
Meta map[string]any
}
type Root struct {
Config Nested
}
root := Root{}
rfx := New(&root)
// 设置嵌套的 nil map
rfx.Set("Config.Meta.host", "localhost")
rfx.Set("Config.Meta.port", 8080)
if root.Config.Meta == nil {
t.Fatal("Expected Meta to be initialized, got nil")
}
if root.Config.Meta["host"] != "localhost" {
t.Errorf("Expected host=localhost, got %v", root.Config.Meta["host"])
}
if root.Config.Meta["port"] != 8080 {
t.Errorf("Expected port=8080, got %v", root.Config.Meta["port"])
}
})
t.Run("Auto init map with R interface value", func(t *testing.T) {
type Settings struct {
Options map[string]int
}
settings := Settings{}
rfx := New(&settings)
// 使用 R 接口包装的值(使用 map 而非基本类型)
timeoutData := map[string]int{"value": 30}
rTimeout := New(&timeoutData)
// 通过 Get 提取值再设置
rfx.Set("Options.timeout", rTimeout.Get("value").Int())
if settings.Options == nil {
t.Fatal("Expected Options to be initialized, got nil")
}
if settings.Options["timeout"] != 30 {
t.Errorf("Expected timeout=30, got %d", settings.Options["timeout"])
}
})
t.Run("Set to uninitialized map in nested structure", func(t *testing.T) {
type Database struct {
Params map[string]string
}
type Config struct {
DB Database
}
config := Config{
DB: Database{}, // Params is nil
}
rfx := New(&config)
// 设置未初始化的 map
rfx.Set("DB.Params.host", "localhost")
rfx.Set("DB.Params.port", "5432")
if config.DB.Params == nil {
t.Fatal("Expected Params to be initialized, got nil")
}
if config.DB.Params["host"] != "localhost" {
t.Errorf("Expected host=localhost, got %s", config.DB.Params["host"])
}
if config.DB.Params["port"] != "5432" {
t.Errorf("Expected port=5432, got %s", config.DB.Params["port"])
}
})
t.Run("Set complex value to auto-initialized map", func(t *testing.T) {
type Item struct {
Name string
Count int
}
type Store struct {
Items map[string]Item
}
store := Store{}
rfx := New(&store)
// 设置复杂类型到未初始化的 map
item := Item{Name: "apple", Count: 10}
rfx.Set("Items.fruit", item)
if store.Items == nil {
t.Fatal("Expected Items to be initialized, got nil")
}
if store.Items["fruit"].Name != "apple" || store.Items["fruit"].Count != 10 {
t.Errorf("Expected Item{Name:apple, Count:10}, got %+v", store.Items["fruit"])
}
})
}