exercism/go/strain/strain_test.go

171 lines
3.7 KiB
Go

// Collections, hm? For this exercise in Go you'll work with slices as
// collections. Define the following in your solution:
//
// type Ints []int
// type Lists [][]int
// type Strings []string
//
// Then complete the exercise by implementing these methods:
//
// (Ints) Keep(func(int) bool) Ints
// (Ints) Discard(func(int) bool) Ints
// (Lists) Keep(func([]int) bool) Lists
// (Strings) Keep(func(string) bool) Strings
package strain
import (
"reflect"
"testing"
)
func lt10(x int) bool { return x < 10 }
func gt10(x int) bool { return x > 10 }
func odd(x int) bool { return x&1 == 1 }
func even(x int) bool { return x&1 == 0 }
var keepTests = []struct {
pred func(int) bool
list Ints
want Ints
}{
{lt10,
nil,
nil},
{lt10,
Ints{1, 2, 3},
Ints{1, 2, 3}},
{odd,
Ints{1, 2, 3},
Ints{1, 3}},
{even,
Ints{1, 2, 3, 4, 5},
Ints{2, 4}},
}
func TestKeepInts(t *testing.T) {
for _, test := range keepTests {
// setup here copies test.list, preserving the nil value if it is nil
// and making a fresh copy of the underlying array otherwise.
cp := test.list
if cp != nil {
cp = append(Ints{}, cp...)
}
switch res := cp.Keep(test.pred); {
case !reflect.DeepEqual(cp, test.list):
t.Fatalf("Ints%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
test.list, cp, test.list)
case !reflect.DeepEqual(res, test.want):
t.Fatalf("Ints%v.Keep() = %v, want %v",
test.list, res, test.want)
}
}
}
var discardTests = []struct {
pred func(int) bool
list Ints
want Ints
}{
{lt10,
nil,
nil},
{gt10,
Ints{1, 2, 3},
Ints{1, 2, 3}},
{odd,
Ints{1, 2, 3},
Ints{2}},
{even,
Ints{1, 2, 3, 4, 5},
Ints{1, 3, 5}},
}
func TestDiscardInts(t *testing.T) {
for _, test := range discardTests {
cp := test.list
if cp != nil {
cp = append(Ints{}, cp...) // dup underlying array
}
switch res := cp.Discard(test.pred); {
case !reflect.DeepEqual(cp, test.list):
t.Fatalf("Ints%v.Discard() should not modify its reciever. "+
"Found %v, reciever should stay %v",
test.list, cp, test.list)
case !reflect.DeepEqual(res, test.want):
t.Fatalf("Ints%v.Discard() = %v, want %v",
test.list, res, test.want)
}
}
}
func TestKeepStrings(t *testing.T) {
zword := func(s string) bool { return len(s) > 0 && s[0] == 'z' }
list := Strings{"apple", "zebra", "banana", "zombies", "cherimoya", "zelot"}
want := Strings{"zebra", "zombies", "zelot"}
cp := append(Strings{}, list...) // make copy, as with TestInts
switch res := cp.Keep(zword); {
case !reflect.DeepEqual(cp, list):
t.Fatalf("Strings%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
list, cp, list)
case !reflect.DeepEqual(res, want):
t.Fatalf("Strings%v.Keep() = %v, want %v",
list, res, want)
}
}
func TestKeepLists(t *testing.T) {
has5 := func(l []int) bool {
for _, e := range l {
if e == 5 {
return true
}
}
return false
}
list := Lists{
{1, 2, 3},
{5, 5, 5},
{5, 1, 2},
{2, 1, 2},
{1, 5, 2},
{2, 2, 1},
{1, 2, 5},
}
want := Lists{
{5, 5, 5},
{5, 1, 2},
{1, 5, 2},
{1, 2, 5},
}
cp := append(Lists{}, list...)
switch res := cp.Keep(has5); {
case !reflect.DeepEqual(cp, list):
t.Fatalf("Lists%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
list, cp, list)
case !reflect.DeepEqual(res, want):
t.Fatalf("Lists%v.Keep() = %v, want %v",
list, res, want)
}
}
func BenchmarkKeepInts(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range keepTests {
test.list.Keep(test.pred)
}
}
}
func BenchmarkDiscardInts(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range discardTests {
test.list.Discard(test.pred)
}
}
}