summaryrefslogtreecommitdiff
path: root/go/strain/strain_test.go
blob: dd3da5a26266f9d2d58d7e9abea6db1e9a3f4bf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// 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)
		}
	}
}