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