All checks were successful
* Introduce tests for PostgreSQL data types and keywords. * Implement tests for reflect utility functions. * Ensure consistency and correctness of type conversions and keyword mappings. * Validate behavior for various edge cases and input types.
491 lines
11 KiB
Go
491 lines
11 KiB
Go
package reflectutil
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type testStruct struct {
|
|
Name string
|
|
Age int
|
|
Active bool
|
|
Nested *nestedStruct
|
|
Private string
|
|
}
|
|
|
|
type nestedStruct struct {
|
|
Value string
|
|
Count int
|
|
}
|
|
|
|
func TestDeref(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
wantValid bool
|
|
wantKind reflect.Kind
|
|
}{
|
|
{
|
|
name: "non-pointer int",
|
|
input: 42,
|
|
wantValid: true,
|
|
wantKind: reflect.Int,
|
|
},
|
|
{
|
|
name: "single pointer",
|
|
input: ptrInt(42),
|
|
wantValid: true,
|
|
wantKind: reflect.Int,
|
|
},
|
|
{
|
|
name: "double pointer",
|
|
input: ptrPtr(ptrInt(42)),
|
|
wantValid: true,
|
|
wantKind: reflect.Int,
|
|
},
|
|
{
|
|
name: "nil pointer",
|
|
input: (*int)(nil),
|
|
wantValid: false,
|
|
wantKind: reflect.Ptr,
|
|
},
|
|
{
|
|
name: "string",
|
|
input: "test",
|
|
wantValid: true,
|
|
wantKind: reflect.String,
|
|
},
|
|
{
|
|
name: "struct",
|
|
input: testStruct{Name: "test"},
|
|
wantValid: true,
|
|
wantKind: reflect.Struct,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
v := reflect.ValueOf(tt.input)
|
|
got, valid := Deref(v)
|
|
|
|
if valid != tt.wantValid {
|
|
t.Errorf("Deref() valid = %v, want %v", valid, tt.wantValid)
|
|
}
|
|
|
|
if got.Kind() != tt.wantKind {
|
|
t.Errorf("Deref() kind = %v, want %v", got.Kind(), tt.wantKind)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDerefInterface(t *testing.T) {
|
|
i := 42
|
|
pi := &i
|
|
ppi := &pi
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
wantKind reflect.Kind
|
|
}{
|
|
{"int", 42, reflect.Int},
|
|
{"pointer to int", &i, reflect.Int},
|
|
{"double pointer to int", ppi, reflect.Int},
|
|
{"string", "test", reflect.String},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := DerefInterface(tt.input)
|
|
if got.Kind() != tt.wantKind {
|
|
t.Errorf("DerefInterface() kind = %v, want %v", got.Kind(), tt.wantKind)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetFieldValue(t *testing.T) {
|
|
ts := testStruct{
|
|
Name: "John",
|
|
Age: 30,
|
|
Active: true,
|
|
Nested: &nestedStruct{Value: "nested", Count: 5},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
item interface{}
|
|
field string
|
|
want interface{}
|
|
}{
|
|
{"struct field Name", ts, "Name", "John"},
|
|
{"struct field Age", ts, "Age", 30},
|
|
{"struct field Active", ts, "Active", true},
|
|
{"struct non-existent field", ts, "NonExistent", nil},
|
|
{"pointer to struct", &ts, "Name", "John"},
|
|
{"map string key", map[string]string{"key": "value"}, "key", "value"},
|
|
{"map int key", map[string]int{"count": 42}, "count", 42},
|
|
{"map non-existent key", map[string]string{"key": "value"}, "missing", nil},
|
|
{"nil pointer", (*testStruct)(nil), "Name", nil},
|
|
{"non-struct non-map", 42, "field", nil},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := GetFieldValue(tt.item, tt.field)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("GetFieldValue() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSliceOrArray(t *testing.T) {
|
|
arr := [3]int{1, 2, 3}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want bool
|
|
}{
|
|
{"slice", []int{1, 2, 3}, true},
|
|
{"array", arr, true},
|
|
{"pointer to slice", &[]int{1, 2, 3}, true},
|
|
{"string", "test", false},
|
|
{"int", 42, false},
|
|
{"map", map[string]int{}, false},
|
|
{"nil slice", ([]int)(nil), true}, // nil slice is still Kind==Slice
|
|
{"nil pointer", (*[]int)(nil), false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := IsSliceOrArray(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("IsSliceOrArray() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsMap(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want bool
|
|
}{
|
|
{"map[string]int", map[string]int{"a": 1}, true},
|
|
{"map[int]string", map[int]string{1: "a"}, true},
|
|
{"pointer to map", &map[string]int{"a": 1}, true},
|
|
{"slice", []int{1, 2, 3}, false},
|
|
{"string", "test", false},
|
|
{"int", 42, false},
|
|
{"nil map", (map[string]int)(nil), true}, // nil map is still Kind==Map
|
|
{"nil pointer", (*map[string]int)(nil), false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := IsMap(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("IsMap() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSliceLen(t *testing.T) {
|
|
arr := [3]int{1, 2, 3}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want int
|
|
}{
|
|
{"slice length 3", []int{1, 2, 3}, 3},
|
|
{"empty slice", []int{}, 0},
|
|
{"array length 3", arr, 3},
|
|
{"pointer to slice", &[]int{1, 2, 3}, 3},
|
|
{"not a slice", "test", 0},
|
|
{"int", 42, 0},
|
|
{"nil slice", ([]int)(nil), 0},
|
|
{"nil pointer", (*[]int)(nil), 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := SliceLen(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("SliceLen() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapLen(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want int
|
|
}{
|
|
{"map length 2", map[string]int{"a": 1, "b": 2}, 2},
|
|
{"empty map", map[string]int{}, 0},
|
|
{"pointer to map", &map[string]int{"a": 1}, 1},
|
|
{"not a map", []int{1, 2, 3}, 0},
|
|
{"string", "test", 0},
|
|
{"nil map", (map[string]int)(nil), 0},
|
|
{"nil pointer", (*map[string]int)(nil), 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := MapLen(tt.input)
|
|
if got != tt.want {
|
|
t.Errorf("MapLen() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSliceToInterfaces(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want []interface{}
|
|
}{
|
|
{"int slice", []int{1, 2, 3}, []interface{}{1, 2, 3}},
|
|
{"string slice", []string{"a", "b"}, []interface{}{"a", "b"}},
|
|
{"empty slice", []int{}, []interface{}{}},
|
|
{"pointer to slice", &[]int{1, 2}, []interface{}{1, 2}},
|
|
{"not a slice", "test", []interface{}{}},
|
|
{"nil slice", ([]int)(nil), []interface{}{}},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := SliceToInterfaces(tt.input)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("SliceToInterfaces() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapKeys(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want []interface{}
|
|
}{
|
|
{"map with keys", map[string]int{"a": 1, "b": 2}, []interface{}{"a", "b"}},
|
|
{"empty map", map[string]int{}, []interface{}{}},
|
|
{"not a map", []int{1, 2, 3}, []interface{}{}},
|
|
{"nil map", (map[string]int)(nil), []interface{}{}},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := MapKeys(tt.input)
|
|
if len(got) != len(tt.want) {
|
|
t.Errorf("MapKeys() length = %v, want %v", len(got), len(tt.want))
|
|
}
|
|
// For maps, order is not guaranteed, so just check length
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapValues(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
want int // length of values
|
|
}{
|
|
{"map with values", map[string]int{"a": 1, "b": 2}, 2},
|
|
{"empty map", map[string]int{}, 0},
|
|
{"not a map", []int{1, 2, 3}, 0},
|
|
{"nil map", (map[string]int)(nil), 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := MapValues(tt.input)
|
|
if len(got) != tt.want {
|
|
t.Errorf("MapValues() length = %v, want %v", len(got), tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMapGet(t *testing.T) {
|
|
m := map[string]int{"a": 1, "b": 2}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
key interface{}
|
|
want interface{}
|
|
}{
|
|
{"existing key", m, "a", 1},
|
|
{"existing key b", m, "b", 2},
|
|
{"non-existing key", m, "c", nil},
|
|
{"pointer to map", &m, "a", 1},
|
|
{"not a map", []int{1, 2}, 0, nil},
|
|
{"nil map", (map[string]int)(nil), "a", nil},
|
|
{"nil pointer", (*map[string]int)(nil), "a", nil},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := MapGet(tt.input, tt.key)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("MapGet() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSliceIndex(t *testing.T) {
|
|
s := []int{10, 20, 30}
|
|
|
|
tests := []struct {
|
|
name string
|
|
slice interface{}
|
|
index int
|
|
want interface{}
|
|
}{
|
|
{"index 0", s, 0, 10},
|
|
{"index 1", s, 1, 20},
|
|
{"index 2", s, 2, 30},
|
|
{"negative index", s, -1, nil},
|
|
{"out of bounds", s, 5, nil},
|
|
{"pointer to slice", &s, 1, 20},
|
|
{"not a slice", "test", 0, nil},
|
|
{"nil slice", ([]int)(nil), 0, nil},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := SliceIndex(tt.slice, tt.index)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("SliceIndex() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCompareValues(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
a interface{}
|
|
b interface{}
|
|
want int
|
|
}{
|
|
{"both nil", nil, nil, 0},
|
|
{"a nil", nil, 5, -1},
|
|
{"b nil", 5, nil, 1},
|
|
{"equal strings", "abc", "abc", 0},
|
|
{"a less than b strings", "abc", "xyz", -1},
|
|
{"a greater than b strings", "xyz", "abc", 1},
|
|
{"equal ints", 5, 5, 0},
|
|
{"a less than b ints", 3, 7, -1},
|
|
{"a greater than b ints", 10, 5, 1},
|
|
{"equal floats", 3.14, 3.14, 0},
|
|
{"a less than b floats", 2.5, 5.5, -1},
|
|
{"a greater than b floats", 10.5, 5.5, 1},
|
|
{"equal uints", uint(5), uint(5), 0},
|
|
{"different types", "abc", 123, 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := CompareValues(tt.a, tt.b)
|
|
if got != tt.want {
|
|
t.Errorf("CompareValues(%v, %v) = %v, want %v", tt.a, tt.b, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetNestedValue(t *testing.T) {
|
|
nested := map[string]interface{}{
|
|
"level1": map[string]interface{}{
|
|
"level2": map[string]interface{}{
|
|
"value": "deep",
|
|
},
|
|
},
|
|
}
|
|
|
|
ts := testStruct{
|
|
Name: "John",
|
|
Nested: &nestedStruct{
|
|
Value: "nested value",
|
|
Count: 42,
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
path string
|
|
want interface{}
|
|
}{
|
|
{"empty path", nested, "", nested},
|
|
{"single level map", nested, "level1", nested["level1"]},
|
|
{"nested map", nested, "level1.level2", map[string]interface{}{"value": "deep"}},
|
|
{"deep nested map", nested, "level1.level2.value", "deep"},
|
|
{"struct field", ts, "Name", "John"},
|
|
{"nested struct field", ts, "Nested", ts.Nested},
|
|
{"non-existent path", nested, "missing.path", nil},
|
|
{"nil input", nil, "path", nil},
|
|
{"partial missing path", nested, "level1.missing", nil},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := GetNestedValue(tt.input, tt.path)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("GetNestedValue() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDeepEqual(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
a interface{}
|
|
b interface{}
|
|
want bool
|
|
}{
|
|
{"equal ints", 42, 42, true},
|
|
{"different ints", 42, 43, false},
|
|
{"equal strings", "test", "test", true},
|
|
{"different strings", "test", "other", false},
|
|
{"equal slices", []int{1, 2, 3}, []int{1, 2, 3}, true},
|
|
{"different slices", []int{1, 2, 3}, []int{1, 2, 4}, false},
|
|
{"equal maps", map[string]int{"a": 1}, map[string]int{"a": 1}, true},
|
|
{"different maps", map[string]int{"a": 1}, map[string]int{"a": 2}, false},
|
|
{"both nil", nil, nil, true},
|
|
{"one nil", nil, 42, false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := DeepEqual(tt.a, tt.b)
|
|
if got != tt.want {
|
|
t.Errorf("DeepEqual(%v, %v) = %v, want %v", tt.a, tt.b, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Helper functions
|
|
func ptrInt(i int) *int {
|
|
return &i
|
|
}
|
|
|
|
func ptrPtr(p *int) **int {
|
|
return &p
|
|
}
|