github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/paginator/paginator_test.go (about) 1 package paginator 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/hashicorp/nomad/ci" 8 "github.com/hashicorp/nomad/nomad/structs" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestPaginator(t *testing.T) { 13 ci.Parallel(t) 14 ids := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} 15 16 cases := []struct { 17 name string 18 perPage int32 19 nextToken string 20 expected []string 21 expectedNextToken string 22 expectedError string 23 }{ 24 { 25 name: "size-3 page-1", 26 perPage: 3, 27 expected: []string{"0", "1", "2"}, 28 expectedNextToken: "3", 29 }, 30 { 31 name: "size-5 page-2 stop before end", 32 perPage: 5, 33 nextToken: "3", 34 expected: []string{"3", "4", "5", "6", "7"}, 35 expectedNextToken: "8", 36 }, 37 { 38 name: "page-2 reading off the end", 39 perPage: 10, 40 nextToken: "5", 41 expected: []string{"5", "6", "7", "8", "9"}, 42 expectedNextToken: "", 43 }, 44 { 45 name: "starting off the end", 46 perPage: 5, 47 nextToken: "a", 48 expected: []string{}, 49 expectedNextToken: "", 50 }, 51 { 52 name: "error during append", 53 expectedError: "failed to append", 54 }, 55 } 56 57 for _, tc := range cases { 58 t.Run(tc.name, func(t *testing.T) { 59 60 iter := newTestIterator(ids) 61 tokenizer := testTokenizer{} 62 opts := structs.QueryOptions{ 63 PerPage: tc.perPage, 64 NextToken: tc.nextToken, 65 } 66 67 results := []string{} 68 paginator, err := NewPaginator(iter, tokenizer, nil, opts, 69 func(raw interface{}) error { 70 if tc.expectedError != "" { 71 return errors.New(tc.expectedError) 72 } 73 74 result := raw.(*mockObject) 75 results = append(results, result.id) 76 return nil 77 }, 78 ) 79 require.NoError(t, err) 80 81 nextToken, err := paginator.Page() 82 if tc.expectedError == "" { 83 require.NoError(t, err) 84 require.Equal(t, tc.expected, results) 85 require.Equal(t, tc.expectedNextToken, nextToken) 86 } else { 87 require.Error(t, err) 88 require.Contains(t, err.Error(), tc.expectedError) 89 } 90 }) 91 } 92 93 } 94 95 // helpers for pagination tests 96 97 // implements Iterator interface 98 type testResultIterator struct { 99 results chan interface{} 100 } 101 102 func (i testResultIterator) Next() interface{} { 103 select { 104 case raw := <-i.results: 105 if raw == nil { 106 return nil 107 } 108 109 m := raw.(*mockObject) 110 return m 111 default: 112 return nil 113 } 114 } 115 116 type mockObject struct { 117 id string 118 namespace string 119 } 120 121 func (m *mockObject) GetNamespace() string { 122 return m.namespace 123 } 124 125 func newTestIterator(ids []string) testResultIterator { 126 iter := testResultIterator{results: make(chan interface{}, 20)} 127 for _, id := range ids { 128 iter.results <- &mockObject{id: id} 129 } 130 return iter 131 } 132 133 func newTestIteratorWithMocks(mocks []*mockObject) testResultIterator { 134 iter := testResultIterator{results: make(chan interface{}, 20)} 135 for _, m := range mocks { 136 iter.results <- m 137 } 138 return iter 139 } 140 141 // implements Tokenizer interface 142 type testTokenizer struct{} 143 144 func (t testTokenizer) GetToken(raw interface{}) string { 145 return raw.(*mockObject).id 146 }