Index: go/src/infra/tools/cipd/remote_test.go |
diff --git a/go/src/infra/tools/cipd/remote_test.go b/go/src/infra/tools/cipd/remote_test.go |
index f8e40b466e72cc76264cc2b502fffaf3bbd87350..bc70e9f654658ebf323b5970bbd9ae14f036b7fe 100644 |
--- a/go/src/infra/tools/cipd/remote_test.go |
+++ b/go/src/infra/tools/cipd/remote_test.go |
@@ -5,104 +5,117 @@ |
package cipd |
import ( |
- "fmt" |
- "io/ioutil" |
- "net/http" |
- "net/http/httptest" |
"net/url" |
- "reflect" |
"strings" |
"testing" |
"time" |
- "infra/libs/logging" |
- |
. "github.com/smartystreets/goconvey/convey" |
+ |
+ . "infra/tools/cipd/common" |
) |
-func TestRemoteService(t *testing.T) { |
- mockInitiateUpload := func(c C, response string) (*uploadSession, error) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/upload/SHA1/abc") |
- c.So(r.Method, ShouldEqual, "POST") |
- w.Write([]byte(response)) |
+func TestRemoteImpl(t *testing.T) { |
+ mockInitiateUpload := func(c C, reply string) (*UploadSession, error) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/upload/SHA1/abc", |
+ Reply: reply, |
+ }, |
}) |
return remote.initiateUpload("abc") |
} |
- mockFinalizeUpload := func(c C, response string) (bool, error) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/finalize/abc") |
- c.So(r.Method, ShouldEqual, "POST") |
- w.Write([]byte(response)) |
+ mockFinalizeUpload := func(c C, reply string) (bool, error) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/finalize/abc", |
+ Reply: reply, |
+ }, |
}) |
return remote.finalizeUpload("abc") |
} |
- mockRegisterInstance := func(c C, response string) (*registerInstanceResponse, error) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/instance") |
- c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pkgname") |
- c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
- c.So(r.Method, ShouldEqual, "POST") |
- w.Write([]byte(response)) |
+ mockRegisterInstance := func(c C, reply string) (*registerInstanceResponse, error) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/repo/v1/instance", |
+ Query: url.Values{ |
+ "package_name": []string{"pkgname"}, |
+ "instance_id": []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, |
+ }, |
+ Reply: reply, |
+ }, |
}) |
- return remote.registerInstance("pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
+ return remote.registerInstance(Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}) |
} |
- mockFetchInstance := func(c C, response string) (*fetchInstanceResponse, error) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/instance") |
- c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pkgname") |
- c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
- c.So(r.Method, ShouldEqual, "GET") |
- w.Write([]byte(response)) |
+ mockFetchInstance := func(c C, reply string) (*fetchInstanceResponse, error) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "GET", |
+ Path: "/_ah/api/repo/v1/instance", |
+ Query: url.Values{ |
+ "package_name": []string{"pkgname"}, |
+ "instance_id": []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, |
+ }, |
+ Reply: reply, |
+ }, |
}) |
- return remote.fetchInstance("pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
+ return remote.fetchInstance(Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}) |
} |
- mockFetchACL := func(c C, response string) ([]PackageACL, error) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/acl") |
- c.So(r.URL.Query().Get("package_path"), ShouldEqual, "pkgname") |
- c.So(r.Method, ShouldEqual, "GET") |
- w.Write([]byte(response)) |
+ mockFetchACL := func(c C, reply string) ([]PackageACL, error) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "GET", |
+ Path: "/_ah/api/repo/v1/acl", |
+ Query: url.Values{"package_path": []string{"pkgname"}}, |
+ Reply: reply, |
+ }, |
}) |
return remote.fetchACL("pkgname") |
} |
- mockModifyACL := func(c C, changes []PackageACLChange, request, response string) error { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/acl") |
- c.So(r.URL.Query().Get("package_path"), ShouldEqual, "pkgname") |
- c.So(r.Method, ShouldEqual, "POST") |
- body, err := ioutil.ReadAll(r.Body) |
- c.So(err, ShouldBeNil) |
- c.So(string(body), ShouldEqual, request) |
- w.Write([]byte(response)) |
+ mockModifyACL := func(c C, changes []PackageACLChange, body, reply string) error { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/repo/v1/acl", |
+ Query: url.Values{"package_path": []string{"pkgname"}}, |
+ Body: body, |
+ Reply: reply, |
+ }, |
}) |
return remote.modifyACL("pkgname", changes) |
} |
- mockAttachTags := func(c C, tags []string, request, response string) error { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/repo/v1/tags") |
- c.So(r.URL.Query().Get("package_name"), ShouldEqual, "pkgname") |
- c.So(r.URL.Query().Get("instance_id"), ShouldEqual, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
- c.So(r.Method, ShouldEqual, "POST") |
- body, err := ioutil.ReadAll(r.Body) |
- c.So(err, ShouldBeNil) |
- c.So(string(body), ShouldEqual, request) |
- w.Write([]byte(response)) |
+ mockAttachTags := func(c C, tags []string, body, reply string) error { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/repo/v1/tags", |
+ Query: url.Values{ |
+ "package_name": []string{"pkgname"}, |
+ "instance_id": []string{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, |
+ }, |
+ Body: body, |
+ Reply: reply, |
+ }, |
}) |
- return remote.attachTags("pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", tags) |
+ return remote.attachTags(Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, tags) |
} |
Convey("makeRequest POST works", t, func(c C) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.Method, ShouldEqual, "POST") |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/method") |
- w.Write([]byte(`{"value":"123"}`)) |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/method", |
+ Reply: `{"value":"123"}`, |
+ }, |
}) |
var reply struct { |
Value string `json:"value"` |
@@ -113,10 +126,12 @@ func TestRemoteService(t *testing.T) { |
}) |
Convey("makeRequest GET works", t, func(c C) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.Method, ShouldEqual, "GET") |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/method") |
- w.Write([]byte(`{"value":"123"}`)) |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "GET", |
+ Path: "/_ah/api/cas/v1/method", |
+ Reply: `{"value":"123"}`, |
+ }, |
}) |
var reply struct { |
Value string `json:"value"` |
@@ -126,46 +141,50 @@ func TestRemoteService(t *testing.T) { |
So(reply.Value, ShouldEqual, "123") |
}) |
- Convey("makeRequest handles fatal error", t, func() { |
- calls := 0 |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- calls++ |
- w.WriteHeader(403) |
+ Convey("makeRequest handles fatal error", t, func(c C) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/method", |
+ Status: 403, |
+ }, |
}) |
var reply struct{} |
err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) |
So(err, ShouldNotBeNil) |
- So(calls, ShouldEqual, 1) |
- }) |
- |
- Convey("makeRequest handles retries", t, func() { |
- mockClock(time.Now()) |
- calls := 0 |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- calls++ |
- if calls == 1 { |
- w.WriteHeader(500) |
- } else { |
- w.Write([]byte(`{}`)) |
- } |
+ }) |
+ |
+ Convey("makeRequest handles retries", t, func(c C) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/method", |
+ Status: 500, |
+ }, |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/method", |
+ Reply: `{}`, |
+ }, |
}) |
var reply struct{} |
err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) |
So(err, ShouldBeNil) |
- So(calls, ShouldEqual, 2) |
}) |
- Convey("makeRequest gives up trying", t, func() { |
- mockClock(time.Now()) |
- calls := 0 |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- calls++ |
- w.WriteHeader(500) |
- }) |
+ Convey("makeRequest gives up trying", t, func(c C) { |
+ calls := []expectedHTTPCall{} |
+ for i := 0; i < remoteMaxRetries; i++ { |
+ calls = append(calls, expectedHTTPCall{ |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/method", |
+ Status: 500, |
+ }) |
+ } |
+ remote := mockRemoteImpl(c, calls) |
var reply struct{} |
err := remote.makeRequest("cas/v1/method", "POST", nil, &reply) |
So(err, ShouldNotBeNil) |
- So(calls, ShouldEqual, 10) |
}) |
Convey("initiateUpload ALREADY_UPLOADED", t, func(c C) { |
@@ -177,10 +196,7 @@ func TestRemoteService(t *testing.T) { |
Convey("initiateUpload SUCCESS", t, func(c C) { |
s, err := mockInitiateUpload(c, `{"status":"SUCCESS","upload_session_id":"123","upload_url":"http://localhost"}`) |
So(err, ShouldBeNil) |
- So(s, ShouldResemble, &uploadSession{ |
- ID: "123", |
- URL: "http://localhost", |
- }) |
+ So(s, ShouldResemble, &UploadSession{"123", "http://localhost"}) |
}) |
Convey("initiateUpload ERROR", t, func(c C) { |
@@ -195,10 +211,13 @@ func TestRemoteService(t *testing.T) { |
So(s, ShouldBeNil) |
}) |
- Convey("initiateUpload bad reply", t, func() { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/upload/SHA1/abc") |
- w.WriteHeader(403) |
+ Convey("initiateUpload bad reply", t, func(c C) { |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/upload/SHA1/abc", |
+ Status: 403, |
+ }, |
}) |
s, err := remote.initiateUpload("abc") |
So(err, ShouldNotBeNil) |
@@ -242,9 +261,12 @@ func TestRemoteService(t *testing.T) { |
}) |
Convey("finalizeUpload bad reply", t, func(c C) { |
- remote := mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- c.So(r.URL.Path, ShouldEqual, "/_ah/api/cas/v1/finalize/abc") |
- w.WriteHeader(403) |
+ remote := mockRemoteImpl(c, []expectedHTTPCall{ |
+ { |
+ Method: "POST", |
+ Path: "/_ah/api/cas/v1/finalize/abc", |
+ Status: 403, |
+ }, |
}) |
finished, err := remote.finalizeUpload("abc") |
So(err, ShouldNotBeNil) |
@@ -253,59 +275,52 @@ func TestRemoteService(t *testing.T) { |
Convey("registerInstance REGISTERED", t, func(c C) { |
result, err := mockRegisterInstance(c, `{ |
- "status": "REGISTERED", |
- "instance": { |
- "registered_by": "user:abc@example.com", |
- "registered_ts": "1420244414571500" |
- } |
- }`) |
+ "status": "REGISTERED", |
+ "instance": { |
+ "registered_by": "user:abc@example.com", |
+ "registered_ts": "1420244414571500" |
+ } |
+ }`) |
So(err, ShouldBeNil) |
So(result, ShouldResemble, ®isterInstanceResponse{ |
- Info: packageInstanceInfo{ |
- RegisteredBy: "user:abc@example.com", |
- RegisteredTs: time.Unix(0, 1420244414571500000), |
- }, |
+ registeredBy: "user:abc@example.com", |
+ registeredTs: time.Unix(0, 1420244414571500000), |
}) |
}) |
Convey("registerInstance ALREADY_REGISTERED", t, func(c C) { |
result, err := mockRegisterInstance(c, `{ |
- "status": "ALREADY_REGISTERED", |
- "instance": { |
- "registered_by": "user:abc@example.com", |
- "registered_ts": "1420244414571500" |
- } |
- }`) |
+ "status": "ALREADY_REGISTERED", |
+ "instance": { |
+ "registered_by": "user:abc@example.com", |
+ "registered_ts": "1420244414571500" |
+ } |
+ }`) |
So(err, ShouldBeNil) |
So(result, ShouldResemble, ®isterInstanceResponse{ |
- AlreadyRegistered: true, |
- Info: packageInstanceInfo{ |
- RegisteredBy: "user:abc@example.com", |
- RegisteredTs: time.Unix(0, 1420244414571500000), |
- }, |
+ alreadyRegistered: true, |
+ registeredBy: "user:abc@example.com", |
+ registeredTs: time.Unix(0, 1420244414571500000), |
}) |
}) |
Convey("registerInstance UPLOAD_FIRST", t, func(c C) { |
result, err := mockRegisterInstance(c, `{ |
- "status": "UPLOAD_FIRST", |
- "upload_session_id": "upload_session_id", |
- "upload_url": "http://upload_url" |
- }`) |
+ "status": "UPLOAD_FIRST", |
+ "upload_session_id": "upload_session_id", |
+ "upload_url": "http://upload_url" |
+ }`) |
So(err, ShouldBeNil) |
So(result, ShouldResemble, ®isterInstanceResponse{ |
- UploadSession: &uploadSession{ |
- ID: "upload_session_id", |
- URL: "http://upload_url", |
- }, |
+ uploadSession: &UploadSession{"upload_session_id", "http://upload_url"}, |
}) |
}) |
Convey("registerInstance ERROR", t, func(c C) { |
result, err := mockRegisterInstance(c, `{ |
- "status": "ERROR", |
- "error_message": "Some error message" |
- }`) |
+ "status": "ERROR", |
+ "error_message": "Some error message" |
+ }`) |
So(err, ShouldNotBeNil) |
So(result, ShouldBeNil) |
}) |
@@ -318,20 +333,18 @@ func TestRemoteService(t *testing.T) { |
Convey("fetchInstance SUCCESS", t, func(c C) { |
result, err := mockFetchInstance(c, `{ |
- "status": "SUCCESS", |
- "instance": { |
- "registered_by": "user:abc@example.com", |
- "registered_ts": "1420244414571500" |
- }, |
- "fetch_url": "https://fetch_url" |
- }`) |
+ "status": "SUCCESS", |
+ "instance": { |
+ "registered_by": "user:abc@example.com", |
+ "registered_ts": "1420244414571500" |
+ }, |
+ "fetch_url": "https://fetch_url" |
+ }`) |
So(err, ShouldBeNil) |
So(result, ShouldResemble, &fetchInstanceResponse{ |
- Info: packageInstanceInfo{ |
- RegisteredBy: "user:abc@example.com", |
- RegisteredTs: time.Unix(0, 1420244414571500000), |
- }, |
- FetchURL: "https://fetch_url", |
+ registeredBy: "user:abc@example.com", |
+ registeredTs: time.Unix(0, 1420244414571500000), |
+ fetchURL: "https://fetch_url", |
}) |
}) |
@@ -349,35 +362,35 @@ func TestRemoteService(t *testing.T) { |
Convey("fetchInstance ERROR", t, func(c C) { |
result, err := mockFetchInstance(c, `{ |
- "status": "ERROR", |
- "error_message": "Some error message" |
- }`) |
+ "status": "ERROR", |
+ "error_message": "Some error message" |
+ }`) |
So(err, ShouldNotBeNil) |
So(result, ShouldBeNil) |
}) |
Convey("fetchACL SUCCESS", t, func(c C) { |
result, err := mockFetchACL(c, `{ |
- "status": "SUCCESS", |
- "acls": { |
- "acls": [ |
- { |
- "package_path": "a", |
- "role": "OWNER", |
- "principals": ["user:a", "group:b"], |
- "modified_by": "user:abc@example.com", |
- "modified_ts": "1420244414571500" |
- }, |
- { |
- "package_path": "a/b", |
- "role": "READER", |
- "principals": ["group:c"], |
- "modified_by": "user:abc@example.com", |
- "modified_ts": "1420244414571500" |
- } |
- ] |
- } |
- }`) |
+ "status": "SUCCESS", |
+ "acls": { |
+ "acls": [ |
+ { |
+ "package_path": "a", |
+ "role": "OWNER", |
+ "principals": ["user:a", "group:b"], |
+ "modified_by": "user:abc@example.com", |
+ "modified_ts": "1420244414571500" |
+ }, |
+ { |
+ "package_path": "a/b", |
+ "role": "READER", |
+ "principals": ["group:c"], |
+ "modified_by": "user:abc@example.com", |
+ "modified_ts": "1420244414571500" |
+ } |
+ ] |
+ } |
+ }`) |
So(err, ShouldBeNil) |
So(result, ShouldResemble, []PackageACL{ |
{ |
@@ -399,28 +412,28 @@ func TestRemoteService(t *testing.T) { |
Convey("fetchACL ERROR", t, func(c C) { |
result, err := mockFetchACL(c, `{ |
- "status": "ERROR", |
- "error_message": "Some error message" |
- }`) |
+ "status": "ERROR", |
+ "error_message": "Some error message" |
+ }`) |
So(err, ShouldNotBeNil) |
So(result, ShouldBeNil) |
}) |
Convey("modifyACL SUCCESS", t, func(c C) { |
expected := `{ |
- "changes": [ |
- { |
- "action": "GRANT", |
- "role": "OWNER", |
- "principal": "user:a@example.com" |
- }, |
- { |
- "action": "REVOKE", |
- "role": "READER", |
- "principal": "user:b@example.com" |
- } |
- ] |
- }` |
+ "changes": [ |
+ { |
+ "action": "GRANT", |
+ "role": "OWNER", |
+ "principal": "user:a@example.com" |
+ }, |
+ { |
+ "action": "REVOKE", |
+ "role": "READER", |
+ "principal": "user:b@example.com" |
+ } |
+ ] |
+ }` |
// Strip " ", "\t" and "\n". |
expected = strings.Replace(expected, " ", "", -1) |
expected = strings.Replace(expected, "\n", "", -1) |
@@ -443,9 +456,9 @@ func TestRemoteService(t *testing.T) { |
Convey("modifyACL ERROR", t, func(c C) { |
err := mockModifyACL(c, []PackageACLChange{}, `{"changes":null}`, `{ |
- "status": "ERROR", |
- "error_message": "Error message" |
- }`) |
+ "status": "ERROR", |
+ "error_message": "Error message" |
+ }`) |
So(err, ShouldNotBeNil) |
}) |
@@ -457,13 +470,10 @@ func TestRemoteService(t *testing.T) { |
So(err, ShouldBeNil) |
}) |
- Convey("attachTags no tags", t, func(c C) { |
- err := mockAttachTags(c, nil, "", "") |
- So(err, ShouldNotBeNil) |
- }) |
- |
Convey("attachTags bad tag", t, func(c C) { |
- err := mockAttachTags(c, []string{"BADTAG"}, "", "") |
+ err := mockRemoteImpl(c, nil).attachTags( |
+ Pin{"pkgname", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, |
+ []string{"BADTAG"}) |
So(err, ShouldNotBeNil) |
}) |
@@ -486,88 +496,6 @@ func TestRemoteService(t *testing.T) { |
//////////////////////////////////////////////////////////////////////////////// |
-type expectedHTTPCall struct { |
- Method string |
- Path string |
- Reply string |
- Query url.Values |
- Status int |
-} |
- |
-func mockServerWithMux(mux *http.ServeMux) (*httptest.Server, *http.Client) { |
- server := httptest.NewServer(mux) |
- transport := &http.Transport{ |
- Proxy: func(req *http.Request) (*url.URL, error) { |
- return url.Parse(server.URL) |
- }, |
- } |
- Reset(func() { server.Close() }) |
- return server, &http.Client{Transport: transport} |
-} |
- |
-func mockServerWithHandler(pattern string, handler http.HandlerFunc) (*httptest.Server, *http.Client) { |
- mux := http.NewServeMux() |
- mux.HandleFunc(pattern, handler) |
- return mockServerWithMux(mux) |
-} |
- |
-func mockRemoteService(handler http.HandlerFunc) *remoteService { |
- server, client := mockServerWithHandler("/", handler) |
- remote := &remoteService{ |
- client: client, |
- serviceURL: server.URL, |
- log: logging.DefaultLogger, |
- } |
- prev := newRemoteService |
- newRemoteService = func(client *http.Client, url string, log logging.Logger) *remoteService { |
- return remote |
- } |
- Reset(func() { newRemoteService = prev }) |
- return remote |
-} |
- |
-func mockRemoteServiceWithExpectations(expectations []expectedHTTPCall) *remoteService { |
- index := 0 |
- return mockRemoteService(func(w http.ResponseWriter, r *http.Request) { |
- // Can't use So(...) assertions here. They are not recognized. Return |
- // errors via HTTP instead, to let the main test case catch them. |
- msg := "" |
- exp := expectedHTTPCall{} |
- if index >= len(expectations) { |
- msg = "Unexpected call" |
- } else { |
- // Fill in defaults. |
- exp = expectations[index] |
- if exp.Method == "" { |
- exp.Method = "GET" |
- } |
- if exp.Query == nil { |
- exp.Query = url.Values{} |
- } |
- // Check that request is what it is expected to be. |
- if r.URL.Path != exp.Path { |
- msg = fmt.Sprintf("Expecting call to %s, got %s instead", exp.Path, r.URL.Path) |
- } else if !reflect.DeepEqual(r.URL.Query(), exp.Query) { |
- msg = fmt.Sprintf("Expecting query string %v, got %v instead", exp.Query, r.URL.Query()) |
- } else if r.Method != exp.Method { |
- msg = fmt.Sprintf("Expecting %s to %s, got %s instead", exp.Method, exp.Path, r.Method) |
- } |
- } |
- |
- // Error? |
- if msg != "" { |
- w.WriteHeader(400) |
- w.Write([]byte(msg)) |
- return |
- } |
- |
- // Mocked reply. |
- if exp.Status != 0 { |
- w.WriteHeader(exp.Status) |
- } |
- if exp.Reply != "" { |
- w.Write([]byte(exp.Reply)) |
- } |
- index++ |
- }) |
+func mockRemoteImpl(c C, expectations []expectedHTTPCall) *remoteImpl { |
+ return &remoteImpl{mockClient(c, expectations)} |
} |