1
2
3
4
5
6
7
8
9 package testing
10
11 import (
12 "fmt"
13 "reflect"
14
15 "google.golang.org/api/iterator"
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 func TestIterator(want interface{}, create func() interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
49 vWant := reflect.ValueOf(want)
50 if vWant.Kind() != reflect.Slice {
51 return "'want' must be a slice", false
52 }
53 it := create()
54 msg, ok := testNext(vWant, it, next)
55 if !ok {
56 return msg, ok
57 }
58 if _, ok := it.(iterator.Pageable); !ok || vWant.Len() == 0 {
59 return "", true
60 }
61 return testPaging(vWant, create, next)
62 }
63
64
65 func testNext(vWant reflect.Value, it interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
66 for i := 0; i < vWant.Len(); i++ {
67 got, err := next(it)
68 if err != nil {
69 return fmt.Sprintf("#%d: got %v, expected an item", i, err), false
70 }
71 w := vWant.Index(i).Interface()
72 if !reflect.DeepEqual(got, w) {
73 return fmt.Sprintf("#%d: got %+v, want %+v", i, got, w), false
74 }
75 }
76
77
78 zero := reflect.Zero(vWant.Type().Elem()).Interface()
79 for i := 0; i < 3; i++ {
80 got, err := next(it)
81 if err != iterator.Done {
82 return fmt.Sprintf("at end: got error %v, want iterator.Done", err), false
83 }
84
85 if got != zero {
86 return fmt.Sprintf("got %+v with done, want zero %T", got, zero), false
87 }
88 }
89 return "", true
90 }
91
92
93 func testPaging(vWant reflect.Value, create func() interface{}, next func(interface{}) (interface{}, error)) (string, bool) {
94
95
96 for _, pageSize := range []int{1, 2, vWant.Len(), vWant.Len() + 10} {
97 wantPages := wantedPages(vWant, pageSize)
98
99
100
101
102 it := create().(iterator.Pageable)
103 pager := iterator.NewPager(it, pageSize, "")
104 msg, ok := testPager(fmt.Sprintf("ignore page token, pageSize %d", pageSize),
105 vWant.Type(), wantPages,
106 func(_ string, pagep interface{}) (string, error) {
107 return pager.NextPage(pagep)
108 })
109 if !ok {
110 return msg, false
111 }
112
113
114 it = create().(iterator.Pageable)
115 msg, ok = testPager(fmt.Sprintf("use page token, pageSize %d", pageSize),
116 vWant.Type(), wantPages,
117 func(pageToken string, pagep interface{}) (string, error) {
118 return iterator.NewPager(it, pageSize, pageToken).NextPage(pagep)
119 })
120 if !ok {
121 return msg, false
122 }
123 }
124 return "", true
125 }
126
127
128 func wantedPages(vWant reflect.Value, pageSize int) []interface{} {
129 var pages []interface{}
130 for i, j := 0, pageSize; i < vWant.Len(); i, j = j, j+pageSize {
131 if j > vWant.Len() {
132 j = vWant.Len()
133 }
134 pages = append(pages, vWant.Slice(i, j).Interface())
135 }
136 return pages
137 }
138
139 func testPager(prefix string, sliceType reflect.Type, wantPages []interface{},
140 nextPage func(pageToken string, pagep interface{}) (string, error)) (string, bool) {
141 tok := ""
142 var err error
143 for i := 0; i < len(wantPages)+1; i++ {
144 vpagep := reflect.New(sliceType)
145 tok, err = nextPage(tok, vpagep.Interface())
146 if err != nil {
147 return fmt.Sprintf("%s, page #%d: got error %v", prefix, i, err), false
148 }
149 if i == len(wantPages) {
150
151 if vpagep.Elem().Len() != 0 || tok != "" {
152 return fmt.Sprintf("%s: did not get one empty page at end", prefix), false
153 }
154 break
155 }
156 if msg, ok := compareSlices(vpagep.Elem(), reflect.ValueOf(wantPages[i])); !ok {
157 return fmt.Sprintf("%s, page #%d:\n%s", prefix, i, msg), false
158 }
159 if tok == "" {
160 if i != len(wantPages)-1 {
161 return fmt.Sprintf("%s, page #%d: got empty page token", prefix, i), false
162 }
163 break
164 }
165 }
166 return "", true
167 }
168
169
170
171 func compareSlices(vgot, vwant reflect.Value) (string, bool) {
172 if got, want := vgot.Len(), vwant.Len(); got != want {
173 return fmt.Sprintf("got %d items, want %d", got, want), false
174 }
175 for i := 0; i < vgot.Len(); i++ {
176 if got, want := vgot.Index(i).Interface(), vwant.Index(i).Interface(); !reflect.DeepEqual(got, want) {
177 return fmt.Sprintf("got[%d] = %+v\nwant = %+v", i, got, want), false
178 }
179 }
180 return "", true
181 }
182
View as plain text