// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan. // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ package equal import ( "bytes" "fmt" "testing" ) func TestEqual(t *testing.T) { one, oneAgain, two := 1, 1, 2 type CyclePtr *CyclePtr var cyclePtr1, cyclePtr2 CyclePtr cyclePtr1 = &cyclePtr1 cyclePtr2 = &cyclePtr2 type CycleSlice []CycleSlice var cycleSlice CycleSlice cycleSlice = append(cycleSlice, cycleSlice) ch1, ch2 := make(chan int), make(chan int) var ch1ro <-chan int = ch1 type mystring string var iface1, iface1Again, iface2 interface{} = &one, &oneAgain, &two for _, test := range []struct { x, y interface{} want bool }{ // basic types {1, 1, true}, {1, 2, false}, // different values {1, 1.0, false}, // different types {"foo", "foo", true}, {"foo", "bar", false}, {mystring("foo"), "foo", false}, // different types // slices {[]string{"foo"}, []string{"foo"}, true}, {[]string{"foo"}, []string{"bar"}, false}, {[]string{}, []string(nil), true}, // slice cycles {cycleSlice, cycleSlice, true}, // maps { map[string][]int{"foo": {1, 2, 3}}, map[string][]int{"foo": {1, 2, 3}}, true, }, { map[string][]int{"foo": {1, 2, 3}}, map[string][]int{"foo": {1, 2, 3, 4}}, false, }, { map[string][]int{}, map[string][]int(nil), true, }, // pointers {&one, &one, true}, {&one, &two, false}, {&one, &oneAgain, true}, {new(bytes.Buffer), new(bytes.Buffer), true}, // pointer cycles {cyclePtr1, cyclePtr1, true}, {cyclePtr2, cyclePtr2, true}, {cyclePtr1, cyclePtr2, true}, // they're deeply equal // functions {(func())(nil), (func())(nil), true}, {(func())(nil), func() {}, false}, {func() {}, func() {}, false}, // arrays {[...]int{1, 2, 3}, [...]int{1, 2, 3}, true}, {[...]int{1, 2, 3}, [...]int{1, 2, 4}, false}, // channels {ch1, ch1, true}, {ch1, ch2, false}, {ch1ro, ch1, false}, // NOTE: not equal // interfaces {&iface1, &iface1, true}, {&iface1, &iface2, false}, {&iface1Again, &iface1, true}, } { if Equal(test.x, test.y) != test.want { t.Errorf("Equal(%v, %v) = %t", test.x, test.y, !test.want) } } } func ExampleEqual() { //!+ fmt.Println(Equal([]int{1, 2, 3}, []int{1, 2, 3})) // "true" fmt.Println(Equal([]string{"foo"}, []string{"bar"})) // "false" fmt.Println(Equal([]string(nil), []string{})) // "true" fmt.Println(Equal(map[string]int(nil), map[string]int{})) // "true" //!- // Output: // true // false // true // true } func ExampleEqualCycle() { //!+cycle // Circular linked lists a -> b -> a and c -> c. type link struct { value string tail *link } a, b, c := &link{value: "a"}, &link{value: "b"}, &link{value: "c"} a.tail, b.tail, c.tail = b, a, c fmt.Println(Equal(a, a)) // "true" fmt.Println(Equal(b, b)) // "true" fmt.Println(Equal(c, c)) // "true" fmt.Println(Equal(a, b)) // "false" fmt.Println(Equal(a, c)) // "false" //!-cycle // Output: // true // true // true // false // false }