You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
3.2 KiB
Go
178 lines
3.2 KiB
Go
4 months ago
|
package reflection
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
type Person struct {
|
||
|
Name string
|
||
|
Profile Profile
|
||
|
}
|
||
|
|
||
|
type Profile struct {
|
||
|
Age int
|
||
|
City string
|
||
|
}
|
||
|
|
||
|
func assertContains(t testing.TB, haystack []string, needle string) {
|
||
|
t.Helper()
|
||
|
contains := false
|
||
|
for _, x := range haystack {
|
||
|
if x == needle {
|
||
|
contains = true
|
||
|
}
|
||
|
}
|
||
|
if !contains {
|
||
|
t.Errorf("expected %v to contain %q but it didn't", haystack, needle)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestWalk(t *testing.T) {
|
||
|
|
||
|
cases := []struct {
|
||
|
Name string
|
||
|
Input interface{}
|
||
|
ExpectedCalls []string
|
||
|
}{
|
||
|
// case 0
|
||
|
{
|
||
|
Name: "struct with on string field",
|
||
|
Input: struct{ Name string }{"Drew"},
|
||
|
ExpectedCalls: []string{"Drew"},
|
||
|
},
|
||
|
// case 1
|
||
|
{
|
||
|
"struct with two string fields",
|
||
|
struct {
|
||
|
Name string
|
||
|
City string
|
||
|
}{"Chris", "London"},
|
||
|
[]string{"Chris", "London"},
|
||
|
},
|
||
|
// case 2
|
||
|
{
|
||
|
"struct with non string field",
|
||
|
struct {
|
||
|
Name string
|
||
|
Age int
|
||
|
}{"Chris", 33},
|
||
|
[]string{"Chris"},
|
||
|
},
|
||
|
// case 3 Nested Struct
|
||
|
{
|
||
|
"nested fields",
|
||
|
Person{
|
||
|
"Chris",
|
||
|
Profile{33, "London"},
|
||
|
},
|
||
|
[]string{"Chris", "London"},
|
||
|
},
|
||
|
// case 4 struct as pointer
|
||
|
{
|
||
|
"pointers to things",
|
||
|
&Person{
|
||
|
"Chris",
|
||
|
Profile{33, "London"},
|
||
|
},
|
||
|
[]string{"Chris", "London"},
|
||
|
},
|
||
|
// case 5 slice of profiles
|
||
|
{
|
||
|
"slices",
|
||
|
[]Profile{
|
||
|
{33, "London"},
|
||
|
{34, "Reykjavík"},
|
||
|
},
|
||
|
[]string{"London", "Reykjavík"},
|
||
|
},
|
||
|
// case 6 array
|
||
|
{
|
||
|
"arrays",
|
||
|
[2]Profile{
|
||
|
{33, "London"},
|
||
|
{34, "Reykjavík"},
|
||
|
},
|
||
|
[]string{"London", "Reykjavík"},
|
||
|
},
|
||
|
// case 7 map THIS HAS A GOTCHA
|
||
|
// maps in go do not guarantee order. It will eventually fake
|
||
|
// moved to a separate test run to handle that case
|
||
|
// {
|
||
|
// "maps",
|
||
|
// map[string]string{
|
||
|
// "Cow": "Moo",
|
||
|
// "Sheep": "Baa",
|
||
|
// },
|
||
|
// []string{"Moo", "Baa"},
|
||
|
// },
|
||
|
}
|
||
|
|
||
|
for _, test := range cases {
|
||
|
t.Run(test.Name, func(t *testing.T) {
|
||
|
var got []string
|
||
|
walk(test.Input, func(input string) {
|
||
|
got = append(got, input)
|
||
|
})
|
||
|
|
||
|
if !reflect.DeepEqual(got, test.ExpectedCalls) {
|
||
|
t.Errorf("get %v, want %v", got, test.ExpectedCalls)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
}
|
||
|
|
||
|
t.Run("with mas", func(t *testing.T) {
|
||
|
aMap := map[string]string{
|
||
|
"Cow": "Moo",
|
||
|
"Sheep": "Baa",
|
||
|
}
|
||
|
|
||
|
var got []string
|
||
|
walk(aMap, func(input string) {
|
||
|
got = append(got, input)
|
||
|
})
|
||
|
|
||
|
assertContains(t, got, "Moo")
|
||
|
assertContains(t, got, "Baa")
|
||
|
})
|
||
|
|
||
|
t.Run("with channels", func(t *testing.T) {
|
||
|
aChannel := make(chan Profile)
|
||
|
|
||
|
go func() {
|
||
|
aChannel <- Profile{33, "Berlin"}
|
||
|
aChannel <- Profile{34, "Katowice"}
|
||
|
close(aChannel)
|
||
|
}()
|
||
|
|
||
|
var got []string
|
||
|
want := []string{"Berlin", "Katowice"}
|
||
|
|
||
|
walk(aChannel, func(input string) {
|
||
|
got = append(got, input)
|
||
|
})
|
||
|
|
||
|
if !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("got %v, want %v", got, want)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
t.Run("with function", func(t *testing.T) {
|
||
|
aFunction := func() (Profile, Profile) {
|
||
|
return Profile{33, "Berlin"}, Profile{34, "Katowice"}
|
||
|
}
|
||
|
|
||
|
var got []string
|
||
|
want := []string{"Berlin", "Katowice"}
|
||
|
|
||
|
walk(aFunction, func(input string) {
|
||
|
got = append(got, input)
|
||
|
})
|
||
|
|
||
|
if !reflect.DeepEqual(got, want) {
|
||
|
t.Errorf("got %v, want %v", got, want)
|
||
|
}
|
||
|
})
|
||
|
}
|