package walk import ( "reflect" "testing" ) type Profile struct { Age int City string } type Person struct { Name string Profile Profile } func TestWalk(t *testing.T) { cases := []struct { Name string Input interface{} ExpectedCalls []string }{ { "struct with one string field", struct { Name string }{"Chris"}, []string{"Chris"}, }, { "struct with two string fields", struct { Name string City string }{"Chris", "London"}, []string{"Chris", "London"}, }, { "struct with non string field", struct { Name string Age int }{"Chris", 29}, []string{"Chris"}, }, { "nested fields", Person{"Chris", Profile{29, "London"}}, []string{"Chris", "London"}, }, { "pointer to things", &Person{"Chris", Profile{29, "London"}}, []string{"Chris", "London"}, }, { "slices", []Profile{ {29, "London"}, {33, "Paris"}, }, []string{"London", "Paris"}, }, { "arrays", [2]Profile{ {29, "London"}, {33, "Paris"}, }, []string{"London", "Paris"}, }, } 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("got %v want %v", got, test.ExpectedCalls) } }) } t.Run("with maps", func(t *testing.T) { aMap := map[string]string{ "Cow": "meuh", "Sheep": "meh", } var got []string Walk(aMap, func(input string) { got = append(got, input) }) assertContains(t, got, "meuh") assertContains(t, got, "meh") }) t.Run("with channels", func(t *testing.T) { aChannel := make(chan Profile) go func() { aChannel <- Profile{21, "Berlin"} aChannel <- Profile{28, "Beijing"} close(aChannel) }() var got []string want := []string{"Berlin", "Beijing"} 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 functions", func(t *testing.T) { aFunction := func() (Profile, Profile) { return Profile{21, "Berlin"}, Profile{28, "Beijing"} } var got []string want := []string{"Berlin", "Beijing"} Walk(aFunction, func(input string) { got = append(got, input) }) if !reflect.DeepEqual(got, want) { t.Errorf("got %v want %v", got, want) } }) } 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) } }