322 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package reflect_test
 | 
						|
 | 
						|
import (
 | 
						|
	"net/url"
 | 
						|
	"reflect"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	rutil "go.unistack.org/micro/v3/util/reflect"
 | 
						|
)
 | 
						|
 | 
						|
func TestStructFields(t *testing.T) {
 | 
						|
	type NestedStr struct {
 | 
						|
		BBB string
 | 
						|
		CCC int
 | 
						|
	}
 | 
						|
	type Str struct {
 | 
						|
		Name   []string `json:"name" codec:"flatten"`
 | 
						|
		XXX    string   `json:"xxx"`
 | 
						|
		Nested NestedStr
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	fields, err := rutil.StructFields(val)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	var ok bool
 | 
						|
	for _, field := range fields {
 | 
						|
		if field.Path == "Nested.CCC" {
 | 
						|
			ok = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if !ok {
 | 
						|
		t.Fatalf("struct fields returns invalid path: %v", fields)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructFieldsNested(t *testing.T) {
 | 
						|
	type NestedConfig struct {
 | 
						|
		Value string
 | 
						|
	}
 | 
						|
	type Config struct {
 | 
						|
		Time     time.Time
 | 
						|
		Nested   *NestedConfig
 | 
						|
		Metadata map[string]int
 | 
						|
		Broker   string
 | 
						|
		Addr     []string
 | 
						|
		Wait     time.Duration
 | 
						|
		Verbose  bool
 | 
						|
	}
 | 
						|
	cfg := &Config{Nested: &NestedConfig{}}
 | 
						|
	fields, err := rutil.StructFields(cfg)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if len(fields) != 7 {
 | 
						|
		for _, field := range fields {
 | 
						|
			t.Logf("field %#+v\n", field)
 | 
						|
		}
 | 
						|
		t.Fatalf("invalid fields number: %d != %d", 7, len(fields))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestSetFieldByPath(t *testing.T) {
 | 
						|
	type NestedStr struct {
 | 
						|
		BBB string `json:"bbb"`
 | 
						|
		CCC int    `json:"ccc"`
 | 
						|
	}
 | 
						|
	type Str1 struct {
 | 
						|
		Name   []string  `json:"name" codec:"flatten"`
 | 
						|
		XXX    string    `json:"xxx"`
 | 
						|
		Nested NestedStr `json:"nested"`
 | 
						|
	}
 | 
						|
	type Str2 struct {
 | 
						|
		XXX    string     `json:"xxx"`
 | 
						|
		Nested *NestedStr `json:"nested"`
 | 
						|
		Name   []string   `json:"name" codec:"flatten"`
 | 
						|
	}
 | 
						|
	var err error
 | 
						|
	val1 := &Str1{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	val2 := &Str2{Name: []string{"first", "second"}, XXX: "ttt", Nested: &NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	err = rutil.SetFieldByPath(val1, "xxx", "Nested.BBB")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if val1.Nested.BBB != "xxx" {
 | 
						|
		t.Fatalf("SetFieldByPath not works: %#+v", val1)
 | 
						|
	}
 | 
						|
	err = rutil.SetFieldByPath(val2, "xxx", "Nested.BBB")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if val2.Nested.BBB != "xxx" {
 | 
						|
		t.Fatalf("SetFieldByPath not works: %#+v", val1)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestZeroFieldByPath(t *testing.T) {
 | 
						|
	type NestedStr struct {
 | 
						|
		BBB string `json:"bbb"`
 | 
						|
		CCC int    `json:"ccc"`
 | 
						|
	}
 | 
						|
	type Str1 struct {
 | 
						|
		Name   []string  `json:"name" codec:"flatten"`
 | 
						|
		XXX    string    `json:"xxx"`
 | 
						|
		Nested NestedStr `json:"nested"`
 | 
						|
	}
 | 
						|
	type Str2 struct {
 | 
						|
		XXX    string     `json:"xxx"`
 | 
						|
		Nested *NestedStr `json:"nested"`
 | 
						|
		Name   []string   `json:"name" codec:"flatten"`
 | 
						|
	}
 | 
						|
	var err error
 | 
						|
	val1 := &Str1{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
 | 
						|
	err = rutil.ZeroFieldByPath(val1, "Nested.BBB")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	err = rutil.ZeroFieldByPath(val1, "Nested")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if val1.Nested.BBB == "ddd" {
 | 
						|
		t.Fatalf("zero field not works: %v", val1)
 | 
						|
	}
 | 
						|
 | 
						|
	val2 := &Str2{Name: []string{"first", "second"}, XXX: "ttt", Nested: &NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	err = rutil.ZeroFieldByPath(val2, "Nested")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if val2.Nested != nil {
 | 
						|
		t.Fatalf("zero field not works: %v", val2)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructFieldsMap(t *testing.T) {
 | 
						|
	type NestedStr struct {
 | 
						|
		BBB string
 | 
						|
		CCC int
 | 
						|
	}
 | 
						|
	type Str struct {
 | 
						|
		Name   []string `json:"name" codec:"flatten"`
 | 
						|
		XXX    string   `json:"xxx"`
 | 
						|
		Nested NestedStr
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	fields, err := rutil.StructFieldsMap(val)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if v, ok := fields["Nested.BBB"]; !ok || v != "ddd" {
 | 
						|
		t.Fatalf("invalid field from %v", fields)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructFieldByPath(t *testing.T) {
 | 
						|
	type NestedStr struct {
 | 
						|
		BBB string
 | 
						|
		CCC int
 | 
						|
	}
 | 
						|
	type Str struct {
 | 
						|
		Name   []string `json:"name" codec:"flatten"`
 | 
						|
		XXX    string   `json:"xxx"`
 | 
						|
		Nested NestedStr
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: []string{"first", "second"}, XXX: "ttt", Nested: NestedStr{BBB: "ddd", CCC: 9}}
 | 
						|
	field, err := rutil.StructFieldByPath(val, "Nested.CCC")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	if reflect.Indirect(reflect.ValueOf(field)).Int() != 9 {
 | 
						|
		t.Fatalf("invalid elem returned: %v", field)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructFieldByTag(t *testing.T) {
 | 
						|
	type Str struct {
 | 
						|
		Name []string `json:"name" codec:"flatten"`
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: []string{"first", "second"}}
 | 
						|
 | 
						|
	iface, err := rutil.StructFieldByTag(val, "codec", "flatten")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := iface.([]string); !ok {
 | 
						|
		t.Fatalf("not *[]string %v", iface)
 | 
						|
	} else if len(v) != 2 {
 | 
						|
		t.Fatalf("invalid number %v", iface)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructFieldByName(t *testing.T) {
 | 
						|
	type Str struct {
 | 
						|
		Name []string `json:"name" codec:"flatten"`
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: []string{"first", "second"}}
 | 
						|
 | 
						|
	iface, err := rutil.StructFieldByName(val, "Name")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if v, ok := iface.([]string); !ok {
 | 
						|
		t.Fatalf("not []string %v", iface)
 | 
						|
	} else if len(v) != 2 {
 | 
						|
		t.Fatalf("invalid number %v", iface)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestStructURLValues(t *testing.T) {
 | 
						|
	type Str struct {
 | 
						|
		Str  *Str   `json:"str"`
 | 
						|
		Name string `json:"name"`
 | 
						|
		Args []int  `json:"args"`
 | 
						|
	}
 | 
						|
 | 
						|
	val := &Str{Name: "test_name", Args: []int{1, 2, 3}, Str: &Str{Name: "nested_name"}}
 | 
						|
	data, err := rutil.StructURLValues(val, "", []string{"json"})
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	if data.Get("name") != "test_name" {
 | 
						|
		t.Fatalf("invalid data: %v", data)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestURLSliceVars(t *testing.T) {
 | 
						|
	u, err := url.Parse("http://localhost/v1/test/call/my_name?key=arg1&key=arg2&key=arg3")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	mp, err := rutil.URLMap(u.RawQuery)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	v, ok := mp["key"]
 | 
						|
	if !ok {
 | 
						|
		t.Fatalf("key not exists: %#+v", mp)
 | 
						|
	}
 | 
						|
 | 
						|
	vm, ok := v.([]interface{})
 | 
						|
	if !ok {
 | 
						|
		t.Fatalf("invalid key value")
 | 
						|
	}
 | 
						|
 | 
						|
	if len(vm) != 3 {
 | 
						|
		t.Fatalf("missing key value: %#+v", mp)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestURLMap(t *testing.T) {
 | 
						|
	u, err := url.Parse("http://localhost/v1/test/call/my_name?req=key&arg1=arg1&arg2=12345&nested.string_args=str1&nested.string_args=str2&arg2=54321")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
 | 
						|
	mp, err := rutil.URLMap(u.RawQuery)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	_ = mp
 | 
						|
}
 | 
						|
 | 
						|
func TestIsZero(t *testing.T) {
 | 
						|
	testStr1 := struct {
 | 
						|
		Name   string
 | 
						|
		Value  string
 | 
						|
		Nested struct {
 | 
						|
			NestedName string
 | 
						|
		}
 | 
						|
	}{
 | 
						|
		Name:  "test_name",
 | 
						|
		Value: "test_value",
 | 
						|
	}
 | 
						|
	testStr1.Nested.NestedName = "nested_name"
 | 
						|
 | 
						|
	if ok := rutil.IsZero(testStr1); ok {
 | 
						|
		t.Fatalf("zero ret on non zero struct: %#+v", testStr1)
 | 
						|
	}
 | 
						|
 | 
						|
	testStr1.Name = ""
 | 
						|
	testStr1.Value = ""
 | 
						|
	testStr1.Nested.NestedName = ""
 | 
						|
	if ok := rutil.IsZero(testStr1); !ok {
 | 
						|
		t.Fatalf("non zero ret on zero struct: %#+v", testStr1)
 | 
						|
	}
 | 
						|
 | 
						|
	type testStr3 struct {
 | 
						|
		Nested string
 | 
						|
	}
 | 
						|
	type testStr2 struct {
 | 
						|
		Nested *testStr3
 | 
						|
		Name   string
 | 
						|
	}
 | 
						|
	vtest := &testStr2{
 | 
						|
		Name:   "test_name",
 | 
						|
		Nested: &testStr3{Nested: "nested_name"},
 | 
						|
	}
 | 
						|
	if ok := rutil.IsZero(vtest); ok {
 | 
						|
		t.Fatalf("zero ret on non zero struct: %#+v", vtest)
 | 
						|
	}
 | 
						|
	vtest.Nested = nil
 | 
						|
	vtest.Name = ""
 | 
						|
	if ok := rutil.IsZero(vtest); !ok {
 | 
						|
		t.Fatalf("non zero ret on zero struct: %#+v", vtest)
 | 
						|
	}
 | 
						|
 | 
						|
	// t.Logf("XX %#+v\n", ok)
 | 
						|
}
 |