Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: go/src/infra/tools/cipd/remote_test.go

Issue 1129043003: cipd: Refactor client to make it more readable. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « go/src/infra/tools/cipd/remote.go ('k') | go/src/infra/tools/cipd/storage.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package cipd 5 package cipd
6 6
7 import ( 7 import (
8 "fmt"
9 "io/ioutil"
10 "net/http"
11 "net/http/httptest"
12 "net/url" 8 "net/url"
13 "reflect"
14 "strings" 9 "strings"
15 "testing" 10 "testing"
16 "time" 11 "time"
17 12
18 » "infra/libs/logging" 13 » . "github.com/smartystreets/goconvey/convey"
19 14
20 » . "github.com/smartystreets/goconvey/convey" 15 » . "infra/tools/cipd/common"
21 ) 16 )
22 17
23 func TestRemoteService(t *testing.T) { 18 func TestRemoteImpl(t *testing.T) {
24 » mockInitiateUpload := func(c C, response string) (*uploadSession, error) { 19 » mockInitiateUpload := func(c C, reply string) (*UploadSession, error) {
25 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 20 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
26 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/upload/SH A1/abc") 21 » » » {
27 » » » c.So(r.Method, ShouldEqual, "POST") 22 » » » » Method: "POST",
28 » » » w.Write([]byte(response)) 23 » » » » Path: "/_ah/api/cas/v1/upload/SHA1/abc",
24 » » » » Reply: reply,
25 » » » },
29 }) 26 })
30 return remote.initiateUpload("abc") 27 return remote.initiateUpload("abc")
31 } 28 }
32 29
33 » mockFinalizeUpload := func(c C, response string) (bool, error) { 30 » mockFinalizeUpload := func(c C, reply string) (bool, error) {
34 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 31 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
35 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/finalize/ abc") 32 » » » {
36 » » » c.So(r.Method, ShouldEqual, "POST") 33 » » » » Method: "POST",
37 » » » w.Write([]byte(response)) 34 » » » » Path: "/_ah/api/cas/v1/finalize/abc",
35 » » » » Reply: reply,
36 » » » },
38 }) 37 })
39 return remote.finalizeUpload("abc") 38 return remote.finalizeUpload("abc")
40 } 39 }
41 40
42 » mockRegisterInstance := func(c C, response string) (*registerInstanceRes ponse, error) { 41 » mockRegisterInstance := func(c C, reply string) (*registerInstanceRespon se, error) {
43 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 42 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
44 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/instance ") 43 » » » {
45 » » » c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pk gname") 44 » » » » Method: "POST",
46 » » » c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 45 » » » » Path: "/_ah/api/repo/v1/instance",
47 » » » c.So(r.Method, ShouldEqual, "POST") 46 » » » » Query: url.Values{
48 » » » w.Write([]byte(response)) 47 » » » » » "package_name": []string{"pkgname"},
48 » » » » » "instance_id": []string{"aaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa"},
49 » » » » },
50 » » » » Reply: reply,
51 » » » },
49 }) 52 })
50 » » return remote.registerInstance("pkgname", "aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa") 53 » » return remote.registerInstance(Pin{"pkgname", "aaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaa"})
51 } 54 }
52 55
53 » mockFetchInstance := func(c C, response string) (*fetchInstanceResponse, error) { 56 » mockFetchInstance := func(c C, reply string) (*fetchInstanceResponse, er ror) {
54 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 57 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
55 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/instance ") 58 » » » {
56 » » » c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pk gname") 59 » » » » Method: "GET",
57 » » » c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 60 » » » » Path: "/_ah/api/repo/v1/instance",
58 » » » c.So(r.Method, ShouldEqual, "GET") 61 » » » » Query: url.Values{
59 » » » w.Write([]byte(response)) 62 » » » » » "package_name": []string{"pkgname"},
63 » » » » » "instance_id": []string{"aaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa"},
64 » » » » },
65 » » » » Reply: reply,
66 » » » },
60 }) 67 })
61 » » return remote.fetchInstance("pkgname", "aaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa") 68 » » return remote.fetchInstance(Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa"})
62 } 69 }
63 70
64 » mockFetchACL := func(c C, response string) ([]PackageACL, error) { 71 » mockFetchACL := func(c C, reply string) ([]PackageACL, error) {
65 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 72 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
66 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/acl") 73 » » » {
67 » » » c.So(r.URL.Query().Get("package_path"), ShouldEqual, "pk gname") 74 » » » » Method: "GET",
68 » » » c.So(r.Method, ShouldEqual, "GET") 75 » » » » Path: "/_ah/api/repo/v1/acl",
69 » » » w.Write([]byte(response)) 76 » » » » Query: url.Values{"package_path": []string{"pkg name"}},
77 » » » » Reply: reply,
78 » » » },
70 }) 79 })
71 return remote.fetchACL("pkgname") 80 return remote.fetchACL("pkgname")
72 } 81 }
73 82
74 » mockModifyACL := func(c C, changes []PackageACLChange, request, response string) error { 83 » mockModifyACL := func(c C, changes []PackageACLChange, body, reply strin g) error {
75 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 84 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
76 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/acl") 85 » » » {
77 » » » c.So(r.URL.Query().Get("package_path"), ShouldEqual, "pk gname") 86 » » » » Method: "POST",
78 » » » c.So(r.Method, ShouldEqual, "POST") 87 » » » » Path: "/_ah/api/repo/v1/acl",
79 » » » body, err := ioutil.ReadAll(r.Body) 88 » » » » Query: url.Values{"package_path": []string{"pkg name"}},
80 » » » c.So(err, ShouldBeNil) 89 » » » » Body: body,
81 » » » c.So(string(body), ShouldEqual, request) 90 » » » » Reply: reply,
82 » » » w.Write([]byte(response)) 91 » » » },
83 }) 92 })
84 return remote.modifyACL("pkgname", changes) 93 return remote.modifyACL("pkgname", changes)
85 } 94 }
86 95
87 » mockAttachTags := func(c C, tags []string, request, response string) err or { 96 » mockAttachTags := func(c C, tags []string, body, reply string) error {
88 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 97 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
89 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/tags") 98 » » » {
90 » » » c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pk gname") 99 » » » » Method: "POST",
91 » » » c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 100 » » » » Path: "/_ah/api/repo/v1/tags",
92 » » » c.So(r.Method, ShouldEqual, "POST") 101 » » » » Query: url.Values{
93 » » » body, err := ioutil.ReadAll(r.Body) 102 » » » » » "package_name": []string{"pkgname"},
94 » » » c.So(err, ShouldBeNil) 103 » » » » » "instance_id": []string{"aaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa"},
95 » » » c.So(string(body), ShouldEqual, request) 104 » » » » },
96 » » » w.Write([]byte(response)) 105 » » » » Body: body,
106 » » » » Reply: reply,
107 » » » },
97 }) 108 })
98 » » return remote.attachTags("pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaa", tags) 109 » » return remote.attachTags(Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa"}, tags)
99 } 110 }
100 111
101 Convey("makeRequest POST works", t, func(c C) { 112 Convey("makeRequest POST works", t, func(c C) {
102 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 113 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
103 » » » c.So(r.Method, ShouldEqual, "POST") 114 » » » {
104 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/method") 115 » » » » Method: "POST",
105 » » » w.Write([]byte(`{"value":"123"}`)) 116 » » » » Path: "/_ah/api/cas/v1/method",
117 » » » » Reply: `{"value":"123"}`,
118 » » » },
106 }) 119 })
107 var reply struct { 120 var reply struct {
108 Value string `json:"value"` 121 Value string `json:"value"`
109 } 122 }
110 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) 123 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply)
111 So(err, ShouldBeNil) 124 So(err, ShouldBeNil)
112 So(reply.Value, ShouldEqual, "123") 125 So(reply.Value, ShouldEqual, "123")
113 }) 126 })
114 127
115 Convey("makeRequest GET works", t, func(c C) { 128 Convey("makeRequest GET works", t, func(c C) {
116 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 129 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
117 » » » c.So(r.Method, ShouldEqual, "GET") 130 » » » {
118 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/method") 131 » » » » Method: "GET",
119 » » » w.Write([]byte(`{"value":"123"}`)) 132 » » » » Path: "/_ah/api/cas/v1/method",
133 » » » » Reply: `{"value":"123"}`,
134 » » » },
120 }) 135 })
121 var reply struct { 136 var reply struct {
122 Value string `json:"value"` 137 Value string `json:"value"`
123 } 138 }
124 err := remote.makeRequest("cas/v1/method", "GET", nil, &reply) 139 err := remote.makeRequest("cas/v1/method", "GET", nil, &reply)
125 So(err, ShouldBeNil) 140 So(err, ShouldBeNil)
126 So(reply.Value, ShouldEqual, "123") 141 So(reply.Value, ShouldEqual, "123")
127 }) 142 })
128 143
129 » Convey("makeRequest handles fatal error", t, func() { 144 » Convey("makeRequest handles fatal error", t, func(c C) {
130 » » calls := 0 145 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
131 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 146 » » » {
132 » » » calls++ 147 » » » » Method: "POST",
133 » » » w.WriteHeader(403) 148 » » » » Path: "/_ah/api/cas/v1/method",
149 » » » » Status: 403,
150 » » » },
134 }) 151 })
135 var reply struct{} 152 var reply struct{}
136 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) 153 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply)
137 So(err, ShouldNotBeNil) 154 So(err, ShouldNotBeNil)
138 So(calls, ShouldEqual, 1)
139 }) 155 })
140 156
141 » Convey("makeRequest handles retries", t, func() { 157 » Convey("makeRequest handles retries", t, func(c C) {
142 » » mockClock(time.Now()) 158 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
143 » » calls := 0 159 » » » {
144 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 160 » » » » Method: "POST",
145 » » » calls++ 161 » » » » Path: "/_ah/api/cas/v1/method",
146 » » » if calls == 1 { 162 » » » » Status: 500,
147 » » » » w.WriteHeader(500) 163 » » » },
148 » » » } else { 164 » » » {
149 » » » » w.Write([]byte(`{}`)) 165 » » » » Method: "POST",
150 » » » } 166 » » » » Path: "/_ah/api/cas/v1/method",
167 » » » » Reply: `{}`,
168 » » » },
151 }) 169 })
152 var reply struct{} 170 var reply struct{}
153 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) 171 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply)
154 So(err, ShouldBeNil) 172 So(err, ShouldBeNil)
155 So(calls, ShouldEqual, 2)
156 }) 173 })
157 174
158 » Convey("makeRequest gives up trying", t, func() { 175 » Convey("makeRequest gives up trying", t, func(c C) {
159 » » mockClock(time.Now()) 176 » » calls := []expectedHTTPCall{}
160 » » calls := 0 177 » » for i := 0; i < remoteMaxRetries; i++ {
161 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 178 » » » calls = append(calls, expectedHTTPCall{
162 » » » calls++ 179 » » » » Method: "POST",
163 » » » w.WriteHeader(500) 180 » » » » Path: "/_ah/api/cas/v1/method",
164 » » }) 181 » » » » Status: 500,
182 » » » })
183 » » }
184 » » remote := mockRemoteImpl(c, calls)
165 var reply struct{} 185 var reply struct{}
166 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) 186 err := remote.makeRequest("cas/v1/method", "POST", nil, &reply)
167 So(err, ShouldNotBeNil) 187 So(err, ShouldNotBeNil)
168 So(calls, ShouldEqual, 10)
169 }) 188 })
170 189
171 Convey("initiateUpload ALREADY_UPLOADED", t, func(c C) { 190 Convey("initiateUpload ALREADY_UPLOADED", t, func(c C) {
172 s, err := mockInitiateUpload(c, `{"status":"ALREADY_UPLOADED"}`) 191 s, err := mockInitiateUpload(c, `{"status":"ALREADY_UPLOADED"}`)
173 So(err, ShouldBeNil) 192 So(err, ShouldBeNil)
174 So(s, ShouldBeNil) 193 So(s, ShouldBeNil)
175 }) 194 })
176 195
177 Convey("initiateUpload SUCCESS", t, func(c C) { 196 Convey("initiateUpload SUCCESS", t, func(c C) {
178 s, err := mockInitiateUpload(c, `{"status":"SUCCESS","upload_ses sion_id":"123","upload_url":"http://localhost"}`) 197 s, err := mockInitiateUpload(c, `{"status":"SUCCESS","upload_ses sion_id":"123","upload_url":"http://localhost"}`)
179 So(err, ShouldBeNil) 198 So(err, ShouldBeNil)
180 » » So(s, ShouldResemble, &uploadSession{ 199 » » So(s, ShouldResemble, &UploadSession{"123", "http://localhost"})
181 » » » ID: "123",
182 » » » URL: "http://localhost",
183 » » })
184 }) 200 })
185 201
186 Convey("initiateUpload ERROR", t, func(c C) { 202 Convey("initiateUpload ERROR", t, func(c C) {
187 s, err := mockInitiateUpload(c, `{"status":"ERROR","error_messag e":"boo"}`) 203 s, err := mockInitiateUpload(c, `{"status":"ERROR","error_messag e":"boo"}`)
188 So(err, ShouldNotBeNil) 204 So(err, ShouldNotBeNil)
189 So(s, ShouldBeNil) 205 So(s, ShouldBeNil)
190 }) 206 })
191 207
192 Convey("initiateUpload unknown status", t, func(c C) { 208 Convey("initiateUpload unknown status", t, func(c C) {
193 s, err := mockInitiateUpload(c, `{"status":"???"}`) 209 s, err := mockInitiateUpload(c, `{"status":"???"}`)
194 So(err, ShouldNotBeNil) 210 So(err, ShouldNotBeNil)
195 So(s, ShouldBeNil) 211 So(s, ShouldBeNil)
196 }) 212 })
197 213
198 » Convey("initiateUpload bad reply", t, func() { 214 » Convey("initiateUpload bad reply", t, func(c C) {
199 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 215 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
200 » » » So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/upload/SHA1 /abc") 216 » » » {
201 » » » w.WriteHeader(403) 217 » » » » Method: "POST",
218 » » » » Path: "/_ah/api/cas/v1/upload/SHA1/abc",
219 » » » » Status: 403,
220 » » » },
202 }) 221 })
203 s, err := remote.initiateUpload("abc") 222 s, err := remote.initiateUpload("abc")
204 So(err, ShouldNotBeNil) 223 So(err, ShouldNotBeNil)
205 So(s, ShouldBeNil) 224 So(s, ShouldBeNil)
206 }) 225 })
207 226
208 Convey("finalizeUpload MISSING", t, func(c C) { 227 Convey("finalizeUpload MISSING", t, func(c C) {
209 finished, err := mockFinalizeUpload(c, `{"status":"MISSING"}`) 228 finished, err := mockFinalizeUpload(c, `{"status":"MISSING"}`)
210 So(err, ShouldNotBeNil) 229 So(err, ShouldNotBeNil)
211 So(finished, ShouldBeFalse) 230 So(finished, ShouldBeFalse)
(...skipping 23 matching lines...) Expand all
235 So(finished, ShouldBeFalse) 254 So(finished, ShouldBeFalse)
236 }) 255 })
237 256
238 Convey("finalizeUpload unknown status", t, func(c C) { 257 Convey("finalizeUpload unknown status", t, func(c C) {
239 finished, err := mockFinalizeUpload(c, `{"status":"???"}`) 258 finished, err := mockFinalizeUpload(c, `{"status":"???"}`)
240 So(err, ShouldNotBeNil) 259 So(err, ShouldNotBeNil)
241 So(finished, ShouldBeFalse) 260 So(finished, ShouldBeFalse)
242 }) 261 })
243 262
244 Convey("finalizeUpload bad reply", t, func(c C) { 263 Convey("finalizeUpload bad reply", t, func(c C) {
245 » » remote := mockRemoteService(func(w http.ResponseWriter, r *http. Request) { 264 » » remote := mockRemoteImpl(c, []expectedHTTPCall{
246 » » » c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/finalize/ abc") 265 » » » {
247 » » » w.WriteHeader(403) 266 » » » » Method: "POST",
267 » » » » Path: "/_ah/api/cas/v1/finalize/abc",
268 » » » » Status: 403,
269 » » » },
248 }) 270 })
249 finished, err := remote.finalizeUpload("abc") 271 finished, err := remote.finalizeUpload("abc")
250 So(err, ShouldNotBeNil) 272 So(err, ShouldNotBeNil)
251 So(finished, ShouldBeFalse) 273 So(finished, ShouldBeFalse)
252 }) 274 })
253 275
254 Convey("registerInstance REGISTERED", t, func(c C) { 276 Convey("registerInstance REGISTERED", t, func(c C) {
255 result, err := mockRegisterInstance(c, `{ 277 result, err := mockRegisterInstance(c, `{
256 » » » "status": "REGISTERED", 278 » » » » "status": "REGISTERED",
257 » » » "instance": { 279 » » » » "instance": {
258 » » » » "registered_by": "user:abc@example.com", 280 » » » » » "registered_by": "user:abc@example.com",
259 » » » » "registered_ts": "1420244414571500" 281 » » » » » "registered_ts": "1420244414571500"
260 » » » } 282 » » » » }
261 » » }`) 283 » » » }`)
262 So(err, ShouldBeNil) 284 So(err, ShouldBeNil)
263 So(result, ShouldResemble, &registerInstanceResponse{ 285 So(result, ShouldResemble, &registerInstanceResponse{
264 » » » Info: packageInstanceInfo{ 286 » » » registeredBy: "user:abc@example.com",
265 » » » » RegisteredBy: "user:abc@example.com", 287 » » » registeredTs: time.Unix(0, 1420244414571500000),
266 » » » » RegisteredTs: time.Unix(0, 1420244414571500000),
267 » » » },
268 }) 288 })
269 }) 289 })
270 290
271 Convey("registerInstance ALREADY_REGISTERED", t, func(c C) { 291 Convey("registerInstance ALREADY_REGISTERED", t, func(c C) {
272 result, err := mockRegisterInstance(c, `{ 292 result, err := mockRegisterInstance(c, `{
273 » » » "status": "ALREADY_REGISTERED", 293 » » » » "status": "ALREADY_REGISTERED",
274 » » » "instance": { 294 » » » » "instance": {
275 » » » » "registered_by": "user:abc@example.com", 295 » » » » » "registered_by": "user:abc@example.com",
276 » » » » "registered_ts": "1420244414571500" 296 » » » » » "registered_ts": "1420244414571500"
277 » » » } 297 » » » » }
278 » » }`) 298 » » » }`)
279 So(err, ShouldBeNil) 299 So(err, ShouldBeNil)
280 So(result, ShouldResemble, &registerInstanceResponse{ 300 So(result, ShouldResemble, &registerInstanceResponse{
281 » » » AlreadyRegistered: true, 301 » » » alreadyRegistered: true,
282 » » » Info: packageInstanceInfo{ 302 » » » registeredBy: "user:abc@example.com",
283 » » » » RegisteredBy: "user:abc@example.com", 303 » » » registeredTs: time.Unix(0, 1420244414571500000),
284 » » » » RegisteredTs: time.Unix(0, 1420244414571500000),
285 » » » },
286 }) 304 })
287 }) 305 })
288 306
289 Convey("registerInstance UPLOAD_FIRST", t, func(c C) { 307 Convey("registerInstance UPLOAD_FIRST", t, func(c C) {
290 result, err := mockRegisterInstance(c, `{ 308 result, err := mockRegisterInstance(c, `{
291 » » » "status": "UPLOAD_FIRST", 309 » » » » "status": "UPLOAD_FIRST",
292 » » » "upload_session_id": "upload_session_id", 310 » » » » "upload_session_id": "upload_session_id",
293 » » » "upload_url": "http://upload_url" 311 » » » » "upload_url": "http://upload_url"
294 » » }`) 312 » » » }`)
295 So(err, ShouldBeNil) 313 So(err, ShouldBeNil)
296 So(result, ShouldResemble, &registerInstanceResponse{ 314 So(result, ShouldResemble, &registerInstanceResponse{
297 » » » UploadSession: &uploadSession{ 315 » » » uploadSession: &UploadSession{"upload_session_id", "http ://upload_url"},
298 » » » » ID: "upload_session_id",
299 » » » » URL: "http://upload_url",
300 » » » },
301 }) 316 })
302 }) 317 })
303 318
304 Convey("registerInstance ERROR", t, func(c C) { 319 Convey("registerInstance ERROR", t, func(c C) {
305 result, err := mockRegisterInstance(c, `{ 320 result, err := mockRegisterInstance(c, `{
306 » » » "status": "ERROR", 321 » » » » "status": "ERROR",
307 » » » "error_message": "Some error message" 322 » » » » "error_message": "Some error message"
308 » » }`) 323 » » » }`)
309 So(err, ShouldNotBeNil) 324 So(err, ShouldNotBeNil)
310 So(result, ShouldBeNil) 325 So(result, ShouldBeNil)
311 }) 326 })
312 327
313 Convey("registerInstance unknown status", t, func(c C) { 328 Convey("registerInstance unknown status", t, func(c C) {
314 result, err := mockRegisterInstance(c, `{"status":"???"}`) 329 result, err := mockRegisterInstance(c, `{"status":"???"}`)
315 So(err, ShouldNotBeNil) 330 So(err, ShouldNotBeNil)
316 So(result, ShouldBeNil) 331 So(result, ShouldBeNil)
317 }) 332 })
318 333
319 Convey("fetchInstance SUCCESS", t, func(c C) { 334 Convey("fetchInstance SUCCESS", t, func(c C) {
320 result, err := mockFetchInstance(c, `{ 335 result, err := mockFetchInstance(c, `{
321 » » » "status": "SUCCESS", 336 » » » » "status": "SUCCESS",
322 » » » "instance": { 337 » » » » "instance": {
323 » » » » "registered_by": "user:abc@example.com", 338 » » » » » "registered_by": "user:abc@example.com",
324 » » » » "registered_ts": "1420244414571500" 339 » » » » » "registered_ts": "1420244414571500"
325 » » » }, 340 » » » » },
326 » » » "fetch_url": "https://fetch_url" 341 » » » » "fetch_url": "https://fetch_url"
327 » » }`) 342 » » » }`)
328 So(err, ShouldBeNil) 343 So(err, ShouldBeNil)
329 So(result, ShouldResemble, &fetchInstanceResponse{ 344 So(result, ShouldResemble, &fetchInstanceResponse{
330 » » » Info: packageInstanceInfo{ 345 » » » registeredBy: "user:abc@example.com",
331 » » » » RegisteredBy: "user:abc@example.com", 346 » » » registeredTs: time.Unix(0, 1420244414571500000),
332 » » » » RegisteredTs: time.Unix(0, 1420244414571500000), 347 » » » fetchURL: "https://fetch_url",
333 » » » },
334 » » » FetchURL: "https://fetch_url",
335 }) 348 })
336 }) 349 })
337 350
338 Convey("fetchInstance PACKAGE_NOT_FOUND", t, func(c C) { 351 Convey("fetchInstance PACKAGE_NOT_FOUND", t, func(c C) {
339 result, err := mockFetchInstance(c, `{"status": "PACKAGE_NOT_FOU ND"}`) 352 result, err := mockFetchInstance(c, `{"status": "PACKAGE_NOT_FOU ND"}`)
340 So(err, ShouldNotBeNil) 353 So(err, ShouldNotBeNil)
341 So(result, ShouldBeNil) 354 So(result, ShouldBeNil)
342 }) 355 })
343 356
344 Convey("fetchInstance INSTANCE_NOT_FOUND", t, func(c C) { 357 Convey("fetchInstance INSTANCE_NOT_FOUND", t, func(c C) {
345 result, err := mockFetchInstance(c, `{"status": "INSTANCE_NOT_FO UND"}`) 358 result, err := mockFetchInstance(c, `{"status": "INSTANCE_NOT_FO UND"}`)
346 So(err, ShouldNotBeNil) 359 So(err, ShouldNotBeNil)
347 So(result, ShouldBeNil) 360 So(result, ShouldBeNil)
348 }) 361 })
349 362
350 Convey("fetchInstance ERROR", t, func(c C) { 363 Convey("fetchInstance ERROR", t, func(c C) {
351 result, err := mockFetchInstance(c, `{ 364 result, err := mockFetchInstance(c, `{
352 » » » "status": "ERROR", 365 » » » » "status": "ERROR",
353 » » » "error_message": "Some error message" 366 » » » » "error_message": "Some error message"
354 » » }`) 367 » » » }`)
355 So(err, ShouldNotBeNil) 368 So(err, ShouldNotBeNil)
356 So(result, ShouldBeNil) 369 So(result, ShouldBeNil)
357 }) 370 })
358 371
359 Convey("fetchACL SUCCESS", t, func(c C) { 372 Convey("fetchACL SUCCESS", t, func(c C) {
360 result, err := mockFetchACL(c, `{ 373 result, err := mockFetchACL(c, `{
361 » » » "status": "SUCCESS", 374 » » » » "status": "SUCCESS",
362 » » » "acls": { 375 » » » » "acls": {
363 » » » » "acls": [ 376 » » » » » "acls": [
364 » » » » » { 377 » » » » » » {
365 » » » » » » "package_path": "a", 378 » » » » » » » "package_path": "a",
366 » » » » » » "role": "OWNER", 379 » » » » » » » "role": "OWNER",
367 » » » » » » "principals": ["user:a", "group: b"], 380 » » » » » » » "principals": ["user:a", "group:b"],
368 » » » » » » "modified_by": "user:abc@example .com", 381 » » » » » » » "modified_by": "user:abc @example.com",
369 » » » » » » "modified_ts": "1420244414571500 " 382 » » » » » » » "modified_ts": "14202444 14571500"
370 » » » » » }, 383 » » » » » » },
371 » » » » » { 384 » » » » » » {
372 » » » » » » "package_path": "a/b", 385 » » » » » » » "package_path": "a/b",
373 » » » » » » "role": "READER", 386 » » » » » » » "role": "READER",
374 » » » » » » "principals": ["group:c"], 387 » » » » » » » "principals": ["group:c" ],
375 » » » » » » "modified_by": "user:abc@example .com", 388 » » » » » » » "modified_by": "user:abc @example.com",
376 » » » » » » "modified_ts": "1420244414571500 " 389 » » » » » » » "modified_ts": "14202444 14571500"
377 » » » » » } 390 » » » » » » }
378 » » » » ] 391 » » » » » ]
379 » » » } 392 » » » » }
380 » » }`) 393 » » » }`)
381 So(err, ShouldBeNil) 394 So(err, ShouldBeNil)
382 So(result, ShouldResemble, []PackageACL{ 395 So(result, ShouldResemble, []PackageACL{
383 { 396 {
384 PackagePath: "a", 397 PackagePath: "a",
385 Role: "OWNER", 398 Role: "OWNER",
386 Principals: []string{"user:a", "group:b"}, 399 Principals: []string{"user:a", "group:b"},
387 ModifiedBy: "user:abc@example.com", 400 ModifiedBy: "user:abc@example.com",
388 ModifiedTs: time.Unix(0, 1420244414571500000), 401 ModifiedTs: time.Unix(0, 1420244414571500000),
389 }, 402 },
390 { 403 {
391 PackagePath: "a/b", 404 PackagePath: "a/b",
392 Role: "READER", 405 Role: "READER",
393 Principals: []string{"group:c"}, 406 Principals: []string{"group:c"},
394 ModifiedBy: "user:abc@example.com", 407 ModifiedBy: "user:abc@example.com",
395 ModifiedTs: time.Unix(0, 1420244414571500000), 408 ModifiedTs: time.Unix(0, 1420244414571500000),
396 }, 409 },
397 }) 410 })
398 }) 411 })
399 412
400 Convey("fetchACL ERROR", t, func(c C) { 413 Convey("fetchACL ERROR", t, func(c C) {
401 result, err := mockFetchACL(c, `{ 414 result, err := mockFetchACL(c, `{
402 » » » "status": "ERROR", 415 » » » » "status": "ERROR",
403 » » » "error_message": "Some error message" 416 » » » » "error_message": "Some error message"
404 » » }`) 417 » » » }`)
405 So(err, ShouldNotBeNil) 418 So(err, ShouldNotBeNil)
406 So(result, ShouldBeNil) 419 So(result, ShouldBeNil)
407 }) 420 })
408 421
409 Convey("modifyACL SUCCESS", t, func(c C) { 422 Convey("modifyACL SUCCESS", t, func(c C) {
410 expected := `{ 423 expected := `{
411 » » » "changes": [ 424 » » » » "changes": [
412 » » » » { 425 » » » » » {
413 » » » » » "action": "GRANT", 426 » » » » » » "action": "GRANT",
414 » » » » » "role": "OWNER", 427 » » » » » » "role": "OWNER",
415 » » » » » "principal": "user:a@example.com" 428 » » » » » » "principal": "user:a@example.com "
416 » » » » }, 429 » » » » » },
417 » » » » { 430 » » » » » {
418 » » » » » "action": "REVOKE", 431 » » » » » » "action": "REVOKE",
419 » » » » » "role": "READER", 432 » » » » » » "role": "READER",
420 » » » » » "principal": "user:b@example.com" 433 » » » » » » "principal": "user:b@example.com "
421 » » » » } 434 » » » » » }
422 » » » ] 435 » » » » ]
423 » » }` 436 » » » }`
424 // Strip " ", "\t" and "\n". 437 // Strip " ", "\t" and "\n".
425 expected = strings.Replace(expected, " ", "", -1) 438 expected = strings.Replace(expected, " ", "", -1)
426 expected = strings.Replace(expected, "\n", "", -1) 439 expected = strings.Replace(expected, "\n", "", -1)
427 expected = strings.Replace(expected, "\t", "", -1) 440 expected = strings.Replace(expected, "\t", "", -1)
428 441
429 err := mockModifyACL(c, []PackageACLChange{ 442 err := mockModifyACL(c, []PackageACLChange{
430 { 443 {
431 Action: GrantRole, 444 Action: GrantRole,
432 Role: "OWNER", 445 Role: "OWNER",
433 Principal: "user:a@example.com", 446 Principal: "user:a@example.com",
434 }, 447 },
435 { 448 {
436 Action: RevokeRole, 449 Action: RevokeRole,
437 Role: "READER", 450 Role: "READER",
438 Principal: "user:b@example.com", 451 Principal: "user:b@example.com",
439 }, 452 },
440 }, expected, `{"status":"SUCCESS"}`) 453 }, expected, `{"status":"SUCCESS"}`)
441 So(err, ShouldBeNil) 454 So(err, ShouldBeNil)
442 }) 455 })
443 456
444 Convey("modifyACL ERROR", t, func(c C) { 457 Convey("modifyACL ERROR", t, func(c C) {
445 err := mockModifyACL(c, []PackageACLChange{}, `{"changes":null}` , `{ 458 err := mockModifyACL(c, []PackageACLChange{}, `{"changes":null}` , `{
446 » » » "status": "ERROR", 459 » » » » "status": "ERROR",
447 » » » "error_message": "Error message" 460 » » » » "error_message": "Error message"
448 » » }`) 461 » » » }`)
449 So(err, ShouldNotBeNil) 462 So(err, ShouldNotBeNil)
450 }) 463 })
451 464
452 Convey("attachTags SUCCESS", t, func(c C) { 465 Convey("attachTags SUCCESS", t, func(c C) {
453 err := mockAttachTags( 466 err := mockAttachTags(
454 c, []string{"tag1:value1", "tag2:value2"}, 467 c, []string{"tag1:value1", "tag2:value2"},
455 `{"tags":["tag1:value1","tag2:value2"]}`, 468 `{"tags":["tag1:value1","tag2:value2"]}`,
456 `{"status":"SUCCESS"}`) 469 `{"status":"SUCCESS"}`)
457 So(err, ShouldBeNil) 470 So(err, ShouldBeNil)
458 }) 471 })
459 472
460 » Convey("attachTags no tags", t, func(c C) { 473 » Convey("attachTags bad tag", t, func(c C) {
461 » » err := mockAttachTags(c, nil, "", "") 474 » » err := mockRemoteImpl(c, nil).attachTags(
475 » » » Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "},
476 » » » []string{"BADTAG"})
462 So(err, ShouldNotBeNil) 477 So(err, ShouldNotBeNil)
463 }) 478 })
464 479
465 Convey("attachTags bad tag", t, func(c C) {
466 err := mockAttachTags(c, []string{"BADTAG"}, "", "")
467 So(err, ShouldNotBeNil)
468 })
469
470 Convey("attachTags PROCESSING_NOT_FINISHED_YET", t, func(c C) { 480 Convey("attachTags PROCESSING_NOT_FINISHED_YET", t, func(c C) {
471 err := mockAttachTags( 481 err := mockAttachTags(
472 c, []string{"tag1:value1", "tag2:value2"}, 482 c, []string{"tag1:value1", "tag2:value2"},
473 `{"tags":["tag1:value1","tag2:value2"]}`, 483 `{"tags":["tag1:value1","tag2:value2"]}`,
474 `{"status":"PROCESSING_NOT_FINISHED_YET", "error_message ":"Blah"}`) 484 `{"status":"PROCESSING_NOT_FINISHED_YET", "error_message ":"Blah"}`)
475 So(err, ShouldResemble, &pendingProcessingError{message: "Blah"} ) 485 So(err, ShouldResemble, &pendingProcessingError{message: "Blah"} )
476 }) 486 })
477 487
478 Convey("attachTags ERROR", t, func(c C) { 488 Convey("attachTags ERROR", t, func(c C) {
479 err := mockAttachTags( 489 err := mockAttachTags(
480 c, []string{"tag1:value1", "tag2:value2"}, 490 c, []string{"tag1:value1", "tag2:value2"},
481 `{"tags":["tag1:value1","tag2:value2"]}`, 491 `{"tags":["tag1:value1","tag2:value2"]}`,
482 `{"status":"ERROR", "error_message":"Blah"}`) 492 `{"status":"ERROR", "error_message":"Blah"}`)
483 So(err, ShouldNotBeNil) 493 So(err, ShouldNotBeNil)
484 }) 494 })
485 } 495 }
486 496
487 //////////////////////////////////////////////////////////////////////////////// 497 ////////////////////////////////////////////////////////////////////////////////
488 498
489 type expectedHTTPCall struct { 499 func mockRemoteImpl(c C, expectations []expectedHTTPCall) *remoteImpl {
490 » Method string 500 » return &remoteImpl{mockClient(c, expectations)}
491 » Path string
492 » Reply string
493 » Query url.Values
494 » Status int
495 } 501 }
496
497 func mockServerWithMux(mux *http.ServeMux) (*httptest.Server, *http.Client) {
498 server := httptest.NewServer(mux)
499 transport := &http.Transport{
500 Proxy: func(req *http.Request) (*url.URL, error) {
501 return url.Parse(server.URL)
502 },
503 }
504 Reset(func() { server.Close() })
505 return server, &http.Client{Transport: transport}
506 }
507
508 func mockServerWithHandler(pattern string, handler http.HandlerFunc) (*httptest. Server, *http.Client) {
509 mux := http.NewServeMux()
510 mux.HandleFunc(pattern, handler)
511 return mockServerWithMux(mux)
512 }
513
514 func mockRemoteService(handler http.HandlerFunc) *remoteService {
515 server, client := mockServerWithHandler("/", handler)
516 remote := &remoteService{
517 client: client,
518 serviceURL: server.URL,
519 log: logging.DefaultLogger,
520 }
521 prev := newRemoteService
522 newRemoteService = func(client *http.Client, url string, log logging.Log ger) *remoteService {
523 return remote
524 }
525 Reset(func() { newRemoteService = prev })
526 return remote
527 }
528
529 func mockRemoteServiceWithExpectations(expectations []expectedHTTPCall) *remoteS ervice {
530 index := 0
531 return mockRemoteService(func(w http.ResponseWriter, r *http.Request) {
532 // Can't use So(...) assertions here. They are not recognized. R eturn
533 // errors via HTTP instead, to let the main test case catch them .
534 msg := ""
535 exp := expectedHTTPCall{}
536 if index >= len(expectations) {
537 msg = "Unexpected call"
538 } else {
539 // Fill in defaults.
540 exp = expectations[index]
541 if exp.Method == "" {
542 exp.Method = "GET"
543 }
544 if exp.Query == nil {
545 exp.Query = url.Values{}
546 }
547 // Check that request is what it is expected to be.
548 if r.URL.Path != exp.Path {
549 msg = fmt.Sprintf("Expecting call to %s, got %s instead", exp.Path, r.URL.Path)
550 } else if !reflect.DeepEqual(r.URL.Query(), exp.Query) {
551 msg = fmt.Sprintf("Expecting query string %v, go t %v instead", exp.Query, r.URL.Query())
552 } else if r.Method != exp.Method {
553 msg = fmt.Sprintf("Expecting %s to %s, got %s in stead", exp.Method, exp.Path, r.Method)
554 }
555 }
556
557 // Error?
558 if msg != "" {
559 w.WriteHeader(400)
560 w.Write([]byte(msg))
561 return
562 }
563
564 // Mocked reply.
565 if exp.Status != 0 {
566 w.WriteHeader(exp.Status)
567 }
568 if exp.Reply != "" {
569 w.Write([]byte(exp.Reply))
570 }
571 index++
572 })
573 }
OLDNEW
« no previous file with comments | « go/src/infra/tools/cipd/remote.go ('k') | go/src/infra/tools/cipd/storage.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698