373 lines
8.7 KiB
Go
373 lines
8.7 KiB
Go
|
package set
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"sort"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
// TestBasicSetOps tests the fundamental operations, whose implementations operate
|
||
|
// directly on the underlying data structure. The remaining operations are implemented
|
||
|
// in terms of these.
|
||
|
func TestBasicSetOps(t *testing.T) {
|
||
|
s := NewSet(testRules{})
|
||
|
want := map[int][]interface{}{}
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("new set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
s.Add(1)
|
||
|
want[1] = []interface{}{1}
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Add(1) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
if !s.Has(1) {
|
||
|
t.Fatalf("s.Has(1) returned false; want true")
|
||
|
}
|
||
|
s.Add(2)
|
||
|
want[2] = []interface{}{2}
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Add(2) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
if !s.Has(2) {
|
||
|
t.Fatalf("s.Has(2) returned false; want true")
|
||
|
}
|
||
|
|
||
|
// Our testRules cause 17 and 33 to return the same hash value as 1, so we can use this
|
||
|
// to test the situation where multiple values are in a bucket.
|
||
|
if s.Has(17) {
|
||
|
t.Fatalf("s.Has(17) returned true; want false")
|
||
|
}
|
||
|
s.Add(17)
|
||
|
s.Add(33)
|
||
|
want[1] = append(want[1], 17, 33)
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Add(17) and s.Add(33) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
if !s.Has(17) {
|
||
|
t.Fatalf("s.Has(17) returned false; want true")
|
||
|
}
|
||
|
if !s.Has(33) {
|
||
|
t.Fatalf("s.Has(33) returned false; want true")
|
||
|
}
|
||
|
|
||
|
vals := make([]int, 0)
|
||
|
s.EachValue(func(v interface{}) {
|
||
|
vals = append(vals, v.(int))
|
||
|
})
|
||
|
sort.Ints(vals)
|
||
|
if want := []int{1, 2, 17, 33}; !reflect.DeepEqual(vals, want) {
|
||
|
t.Fatalf("wrong values from EachValue %#v; want %#v", vals, want)
|
||
|
}
|
||
|
|
||
|
s.Remove(2)
|
||
|
delete(want, 2)
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Remove(2) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
|
||
|
s.Remove(17)
|
||
|
want[1] = []interface{}{1, 33}
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Remove(17) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
|
||
|
s.Remove(1)
|
||
|
want[1] = []interface{}{33}
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Remove(1) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
|
||
|
s.Remove(33)
|
||
|
delete(want, 1)
|
||
|
if !reflect.DeepEqual(s.vals, want) {
|
||
|
t.Fatalf("after s.Remove(33) set has unexpected contents %#v; want %#v", s.vals, want)
|
||
|
}
|
||
|
|
||
|
vals = make([]int, 0)
|
||
|
s.EachValue(func(v interface{}) {
|
||
|
vals = append(vals, v.(int))
|
||
|
})
|
||
|
if len(vals) > 0 {
|
||
|
t.Fatalf("s.EachValue produced values %#v; want no calls", vals)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestUnion(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
s1 Set
|
||
|
s2 Set
|
||
|
wantValues []int
|
||
|
}{
|
||
|
{
|
||
|
NewSet(testRules{}),
|
||
|
NewSet(testRules{}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSet(testRules{}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2}),
|
||
|
[]int{1, 2},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
[]int{1, 17, 33},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2, 1}),
|
||
|
[]int{1, 2, 17, 33},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for i, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||
|
got := test.s1.Union(test.s2)
|
||
|
var gotValues []int
|
||
|
got.EachValue(func(v interface{}) {
|
||
|
gotValues = append(gotValues, v.(int))
|
||
|
})
|
||
|
sort.Ints(gotValues)
|
||
|
sort.Ints(test.wantValues)
|
||
|
if !reflect.DeepEqual(gotValues, test.wantValues) {
|
||
|
s1Values := test.s1.Values()
|
||
|
s2Values := test.s2.Values()
|
||
|
t.Errorf(
|
||
|
"wrong result %#v for %#v union %#v; want %#v",
|
||
|
gotValues,
|
||
|
s1Values,
|
||
|
s2Values,
|
||
|
test.wantValues,
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestIntersection(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
s1 Set
|
||
|
s2 Set
|
||
|
wantValues []int
|
||
|
}{
|
||
|
{
|
||
|
NewSet(testRules{}),
|
||
|
NewSet(testRules{}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSet(testRules{}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 17}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{3, 2, 1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
[]int{1, 2, 3},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2, 1}),
|
||
|
nil,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for i, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||
|
got := test.s1.Intersection(test.s2)
|
||
|
var gotValues []int
|
||
|
got.EachValue(func(v interface{}) {
|
||
|
gotValues = append(gotValues, v.(int))
|
||
|
})
|
||
|
sort.Ints(gotValues)
|
||
|
sort.Ints(test.wantValues)
|
||
|
if !reflect.DeepEqual(gotValues, test.wantValues) {
|
||
|
s1Values := test.s1.Values()
|
||
|
s2Values := test.s2.Values()
|
||
|
t.Errorf(
|
||
|
"wrong result %#v for %#v intersection %#v; want %#v",
|
||
|
gotValues,
|
||
|
s1Values,
|
||
|
s2Values,
|
||
|
test.wantValues,
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSubtract(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
s1 Set
|
||
|
s2 Set
|
||
|
wantValues []int
|
||
|
}{
|
||
|
{
|
||
|
NewSet(testRules{}),
|
||
|
NewSet(testRules{}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSet(testRules{}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 17}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
[]int{17},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{3, 2, 1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
[]int{17, 33},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2, 1}),
|
||
|
[]int{17, 33},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for i, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||
|
got := test.s1.Subtract(test.s2)
|
||
|
var gotValues []int
|
||
|
got.EachValue(func(v interface{}) {
|
||
|
gotValues = append(gotValues, v.(int))
|
||
|
})
|
||
|
sort.Ints(gotValues)
|
||
|
sort.Ints(test.wantValues)
|
||
|
if !reflect.DeepEqual(gotValues, test.wantValues) {
|
||
|
s1Values := test.s1.Values()
|
||
|
s2Values := test.s2.Values()
|
||
|
t.Errorf(
|
||
|
"wrong result %#v for %#v subtract %#v; want %#v",
|
||
|
gotValues,
|
||
|
s1Values,
|
||
|
s2Values,
|
||
|
test.wantValues,
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSymmetricDifference(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
s1 Set
|
||
|
s2 Set
|
||
|
wantValues []int
|
||
|
}{
|
||
|
{
|
||
|
NewSet(testRules{}),
|
||
|
NewSet(testRules{}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSet(testRules{}),
|
||
|
[]int{1},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2}),
|
||
|
[]int{1, 2},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 17}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
[]int{2, 3, 17},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{3, 2, 1}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1, 2, 3}),
|
||
|
nil,
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{1}),
|
||
|
[]int{1, 17, 33},
|
||
|
},
|
||
|
{
|
||
|
NewSetFromSlice(testRules{}, []interface{}{17, 33}),
|
||
|
NewSetFromSlice(testRules{}, []interface{}{2, 1}),
|
||
|
[]int{1, 2, 17, 33},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for i, test := range tests {
|
||
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||
|
got := test.s1.SymmetricDifference(test.s2)
|
||
|
var gotValues []int
|
||
|
got.EachValue(func(v interface{}) {
|
||
|
gotValues = append(gotValues, v.(int))
|
||
|
})
|
||
|
sort.Ints(gotValues)
|
||
|
sort.Ints(test.wantValues)
|
||
|
if !reflect.DeepEqual(gotValues, test.wantValues) {
|
||
|
s1Values := test.s1.Values()
|
||
|
s2Values := test.s2.Values()
|
||
|
t.Errorf(
|
||
|
"wrong result %#v for %#v symmetric difference %#v; want %#v",
|
||
|
gotValues,
|
||
|
s1Values,
|
||
|
s2Values,
|
||
|
test.wantValues,
|
||
|
)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|