blob: a1c59bb53575dd944839036f7cc07458d735e715 [file] [log] [blame]
Ash Wilson64d67b22014-09-05 13:04:12 -04001package gophercloud
2
3import (
Ash Wilson4bf4fac2014-09-15 09:16:13 -04004 "fmt"
Ash Wilson64d67b22014-09-05 13:04:12 -04005 "net/http"
6 "reflect"
Ash Wilson993cf322014-09-15 14:34:12 -04007 "strings"
Ash Wilson64d67b22014-09-05 13:04:12 -04008 "testing"
9
Ash Wilson5bf6f662014-09-12 12:31:17 -040010 "github.com/mitchellh/mapstructure"
Ash Wilson4bf4fac2014-09-15 09:16:13 -040011 "github.com/rackspace/gophercloud/testhelper"
Ash Wilson64d67b22014-09-05 13:04:12 -040012)
13
Ash Wilson4bf4fac2014-09-15 09:16:13 -040014func createClient() *ServiceClient {
15 return &ServiceClient{
16 Provider: &ProviderClient{TokenID: "abc123"},
17 Endpoint: testhelper.Endpoint(),
18 }
Ash Wilson5bf6f662014-09-12 12:31:17 -040019}
20
Ash Wilson64d67b22014-09-05 13:04:12 -040021// SinglePage sample and test cases.
22
Ash Wilson5bf6f662014-09-12 12:31:17 -040023func ExtractSingleInts(page Page) ([]int, error) {
24 var response struct {
25 Ints []int `mapstructure:"ints"`
26 }
Ash Wilson64d67b22014-09-05 13:04:12 -040027
Ash Wilson75eae572014-09-12 12:34:21 -040028 err := mapstructure.Decode(page.(SinglePage).Body, &response)
Ash Wilson5bf6f662014-09-12 12:31:17 -040029 if err != nil {
30 return nil, err
31 }
Ash Wilsonb110fc92014-09-08 13:54:59 -040032
Ash Wilson5bf6f662014-09-12 12:31:17 -040033 return response.Ints, nil
Ash Wilson64d67b22014-09-05 13:04:12 -040034}
35
Ash Wilsone30b76b2014-09-12 08:36:17 -040036func setupSinglePaged() Pager {
Ash Wilson4bf4fac2014-09-15 09:16:13 -040037 testhelper.SetupHTTP()
38 client := createClient()
39
40 testhelper.Mux.HandleFunc("/only", func(w http.ResponseWriter, r *http.Request) {
Ash Wilson993cf322014-09-15 14:34:12 -040041 w.Header().Add("Content-Type", "application/json")
Ash Wilson4bf4fac2014-09-15 09:16:13 -040042 fmt.Fprintf(w, `{ "ints": [1, 2, 3] }`)
Ash Wilsone30b76b2014-09-12 08:36:17 -040043 })
Ash Wilson4bf4fac2014-09-15 09:16:13 -040044
45 return NewSinglePager(client, testhelper.Server.URL+"/only")
Ash Wilson64d67b22014-09-05 13:04:12 -040046}
47
48func TestEnumerateSinglePaged(t *testing.T) {
49 callCount := 0
Ash Wilson4bf4fac2014-09-15 09:16:13 -040050 pager := setupSinglePaged()
51 defer testhelper.TeardownHTTP()
52
53 err := pager.EachPage(func(page Page) (bool, error) {
Ash Wilson64d67b22014-09-05 13:04:12 -040054 callCount++
55
56 expected := []int{1, 2, 3}
Ash Wilson5bf6f662014-09-12 12:31:17 -040057 actual, err := ExtractSingleInts(page)
58 if err != nil {
Ash Wilson6b35e502014-09-12 15:15:23 -040059 return false, err
Ash Wilson5bf6f662014-09-12 12:31:17 -040060 }
Ash Wilson64d67b22014-09-05 13:04:12 -040061 if !reflect.DeepEqual(expected, actual) {
62 t.Errorf("Expected %v, but was %v", expected, actual)
63 }
Ash Wilson6b35e502014-09-12 15:15:23 -040064 return true, nil
Ash Wilson64d67b22014-09-05 13:04:12 -040065 })
Ash Wilsone30b76b2014-09-12 08:36:17 -040066 if err != nil {
67 t.Fatalf("Unexpected error calling EachPage: %v", err)
68 }
Ash Wilson64d67b22014-09-05 13:04:12 -040069
70 if callCount != 1 {
71 t.Errorf("Callback was invoked %d times", callCount)
72 }
73}
74
Ash Wilson64d67b22014-09-05 13:04:12 -040075// LinkedPager sample and test cases.
76
Ash Wilson5bf6f662014-09-12 12:31:17 -040077func ExtractLinkedInts(page Page) ([]int, error) {
78 var response struct {
79 Ints []int `mapstructure:"ints"`
Ash Wilsone30b76b2014-09-12 08:36:17 -040080 }
Ash Wilsonb110fc92014-09-08 13:54:59 -040081
Ash Wilson583dc732014-09-12 13:30:05 -040082 err := mapstructure.Decode(page.(LinkedPage).Body, &response)
Ash Wilson5bf6f662014-09-12 12:31:17 -040083 if err != nil {
84 return nil, err
Ash Wilsonb110fc92014-09-08 13:54:59 -040085 }
Ash Wilson5bf6f662014-09-12 12:31:17 -040086
87 return response.Ints, nil
Ash Wilsonb110fc92014-09-08 13:54:59 -040088}
89
Ash Wilson5bf6f662014-09-12 12:31:17 -040090func createLinked(t *testing.T) Pager {
Ash Wilson4bf4fac2014-09-15 09:16:13 -040091 testhelper.SetupHTTP()
92
93 testhelper.Mux.HandleFunc("/page1", func(w http.ResponseWriter, r *http.Request) {
Ash Wilson993cf322014-09-15 14:34:12 -040094 w.Header().Add("Content-Type", "application/json")
Ash Wilson4bf4fac2014-09-15 09:16:13 -040095 fmt.Fprintf(w, `{ "ints": [1, 2, 3], "links": { "next": "%s/page2" } }`, testhelper.Server.URL)
Ash Wilson64d67b22014-09-05 13:04:12 -040096 })
Ash Wilson4bf4fac2014-09-15 09:16:13 -040097
98 testhelper.Mux.HandleFunc("/page2", func(w http.ResponseWriter, r *http.Request) {
Ash Wilson993cf322014-09-15 14:34:12 -040099 w.Header().Add("Content-Type", "application/json")
Ash Wilson4bf4fac2014-09-15 09:16:13 -0400100 fmt.Fprintf(w, `{ "ints": [4, 5, 6], "links": { "next": "%s/page3" } }`, testhelper.Server.URL)
101 })
102
103 testhelper.Mux.HandleFunc("/page3", func(w http.ResponseWriter, r *http.Request) {
Ash Wilson993cf322014-09-15 14:34:12 -0400104 w.Header().Add("Content-Type", "application/json")
Ash Wilson4bf4fac2014-09-15 09:16:13 -0400105 fmt.Fprintf(w, `{ "ints": [7, 8, 9], "links": { "next": null } }`)
106 })
107
108 client := createClient()
109
110 return NewLinkedPager(client, testhelper.Server.URL+"/page1")
Ash Wilson64d67b22014-09-05 13:04:12 -0400111}
112
113func TestEnumerateLinked(t *testing.T) {
Ash Wilson5bf6f662014-09-12 12:31:17 -0400114 pager := createLinked(t)
Ash Wilson4bf4fac2014-09-15 09:16:13 -0400115 defer testhelper.TeardownHTTP()
Ash Wilson64d67b22014-09-05 13:04:12 -0400116
117 callCount := 0
Ash Wilson6b35e502014-09-12 15:15:23 -0400118 err := pager.EachPage(func(page Page) (bool, error) {
Ash Wilson5bf6f662014-09-12 12:31:17 -0400119 actual, err := ExtractLinkedInts(page)
120 if err != nil {
Ash Wilson6b35e502014-09-12 15:15:23 -0400121 return false, err
Ash Wilson5bf6f662014-09-12 12:31:17 -0400122 }
123
Ash Wilson64d67b22014-09-05 13:04:12 -0400124 t.Logf("Handler invoked with %v", actual)
125
126 var expected []int
127 switch callCount {
128 case 0:
129 expected = []int{1, 2, 3}
130 case 1:
131 expected = []int{4, 5, 6}
132 case 2:
133 expected = []int{7, 8, 9}
134 default:
135 t.Fatalf("Unexpected call count: %d", callCount)
Ash Wilson6b35e502014-09-12 15:15:23 -0400136 return false, nil
Ash Wilson64d67b22014-09-05 13:04:12 -0400137 }
138
139 if !reflect.DeepEqual(expected, actual) {
140 t.Errorf("Call %d: Expected %#v, but was %#v", callCount, expected, actual)
141 }
142
143 callCount++
Ash Wilson6b35e502014-09-12 15:15:23 -0400144 return true, nil
Ash Wilson64d67b22014-09-05 13:04:12 -0400145 })
146 if err != nil {
147 t.Errorf("Unexpected error for page iteration: %v", err)
148 }
149
150 if callCount != 3 {
151 t.Errorf("Expected 3 calls, but was %d", callCount)
152 }
153}
Ash Wilson993cf322014-09-15 14:34:12 -0400154
155func createMarkerPaged(t *testing.T) Pager {
156 testhelper.SetupHTTP()
157
158 testhelper.Mux.HandleFunc("/page", func(w http.ResponseWriter, r *http.Request) {
159 r.ParseForm()
160 ms := r.Form["marker"]
161 switch {
162 case len(ms) == 0:
163 fmt.Fprintf(w, "aaa\nbbb\nccc")
164 case len(ms) == 1 && ms[0] == "ccc":
165 fmt.Fprintf(w, "ddd\neee\nfff")
166 case len(ms) == 1 && ms[0] == "fff":
167 fmt.Fprintf(w, "ggg\nhhh\niii")
168 case len(ms) == 1 && ms[0] == "iii":
169 w.WriteHeader(http.StatusNoContent)
170 default:
171 t.Errorf("Request with unexpected marker: [%v]", ms)
172 }
173 })
174
175 client := createClient()
176
177 return NewMarkerPager(client, testhelper.Server.URL+"/page", func(p MarkerPage) (string, error) {
178 items, err := ExtractMarkerStrings(p)
179 if err != nil {
180 return "", err
181 }
182 return items[len(items)-1], nil
183 })
184}
185
186func ExtractMarkerStrings(page Page) ([]string, error) {
187 content := page.(MarkerPage).Body.([]uint8)
188 return strings.Split(string(content), "\n"), nil
189}
190
191func TestEnumerateMarker(t *testing.T) {
192 pager := createMarkerPaged(t)
193 defer testhelper.TeardownHTTP()
194
195 callCount := 0
196 err := pager.EachPage(func(page Page) (bool, error) {
197 actual, err := ExtractMarkerStrings(page)
198 if err != nil {
199 return false, err
200 }
201
202 t.Logf("Handler invoked with %v", actual)
203
204 var expected []string
205 switch callCount {
206 case 0:
207 expected = []string{"aaa", "bbb", "ccc"}
208 case 1:
209 expected = []string{"ddd", "eee", "fff"}
210 case 2:
211 expected = []string{"ggg", "hhh", "iii"}
212 default:
213 t.Fatalf("Unexpected call count: %d", callCount)
214 return false, nil
215 }
216
217 testhelper.CheckDeepEquals(t, expected, actual)
218
219 callCount++
220 return true, nil
221 })
222 testhelper.AssertNoErr(t, err)
223 testhelper.AssertEquals(t, callCount, 3)
224}