[ARVADOS] updated: 1a844d06238368c9d5c946a34c0c52485de1c435
git at public.curoverse.com
git at public.curoverse.com
Fri May 9 02:51:35 EDT 2014
Summary of changes:
services/keep/src/keep/handler_test.go | 346 ++++++++++++++++++++------------
1 files changed, 221 insertions(+), 125 deletions(-)
via 1a844d06238368c9d5c946a34c0c52485de1c435 (commit)
from 04ec74cf7dedfbb0becea0e0cb5018ccf55a31eb (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 1a844d06238368c9d5c946a34c0c52485de1c435
Author: Tim Pierce <twp at curoverse.com>
Date: Fri May 9 02:49:51 2014 -0400
2328: handler_test.go refactoring
Refactoring to make tests easier to read and understand.
diff --git a/services/keep/src/keep/handler_test.go b/services/keep/src/keep/handler_test.go
index a45ab43..9455a8a 100644
--- a/services/keep/src/keep/handler_test.go
+++ b/services/keep/src/keep/handler_test.go
@@ -11,6 +11,7 @@ package main
import (
"bytes"
+ "github.com/gorilla/mux"
"net/http"
"net/http/httptest"
"regexp"
@@ -18,6 +19,22 @@ import (
"time"
)
+// A RequestTester represents the parameters for an HTTP request to
+// be issued on behalf of a unit test.
+type RequestTester struct {
+ uri string
+ api_token string
+ method string
+ request_body []byte
+}
+
+// Test GetBlockHandler on the following situations:
+// - permissions off, unauthenticated request, unsigned locator
+// - permissions on, authenticated request, signed locator
+// - permissions on, authenticated request, unsigned locator
+// - permissions on, unauthenticated request, signed locator
+// - permissions on, authenticated request, expired locator
+//
func TestGetHandler(t *testing.T) {
defer teardown()
@@ -33,59 +50,77 @@ func TestGetHandler(t *testing.T) {
// Set up a REST router for testing the handlers.
rest := NewRESTRouter()
- // Test an unsigned GET request.
- test_url := "http://localhost:25107/" + TEST_HASH
- req, _ := http.NewRequest("GET", test_url, nil)
- resp := httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
+ // -----------------
+ // Permissions: off.
- ExpectStatusCode(t, "unsigned GET", resp, http.StatusOK)
- ExpectBody(t, "unsigned GET", resp, string(TEST_BLOCK))
+ // Unauthenticated request, unsigned locator
+ // => OK
+ unsigned_locator := "http://localhost:25107/" + TEST_HASH
+ response := IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: unsigned_locator,
+ })
+ ExpectStatusCode(t, "unsigned GET (permissions off)", http.StatusOK, response)
+ ExpectBody(t, "unsigned GET (permissions off)", string(TEST_BLOCK), response)
- // Enable permissions.
+ // ----------------
+ // Permissions: on.
+
+ // Create signed and expired locators for testing.
enforce_permissions = true
PermissionSecret = []byte(known_key)
- permission_ttl = 300
- expiry := time.Now().Add(time.Duration(permission_ttl) * time.Second)
-
- // Test GET with a signed locator.
- test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expiry)
- resp = httptest.NewRecorder()
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+known_token)
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "signed GET", resp, http.StatusOK)
- ExpectBody(t, "signed GET", resp, string(TEST_BLOCK))
-
- // Test GET with an unsigned locator.
- test_url = "http://localhost:25107/" + TEST_HASH
- resp = httptest.NewRecorder()
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+known_token)
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "unsigned locator", resp, PermissionError.HTTPCode)
-
- // Test GET with a signed locator and an unauthenticated request.
- test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expiry)
- resp = httptest.NewRecorder()
- req, _ = http.NewRequest("GET", test_url, nil)
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "signed locator", resp, PermissionError.HTTPCode)
-
- // Test GET with an expired, signed locator.
- expired_ts := time.Now().Add(-time.Hour)
- test_url = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expired_ts)
- resp = httptest.NewRecorder()
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+known_token)
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "expired signature", resp, ExpiredError.HTTPCode)
+ permission_ttl = time.Duration(300) * time.Second
+
+ var (
+ expiration = time.Now().Add(permission_ttl)
+ expired_timestamp = time.Now().Add(-time.Hour)
+ signed_locator = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expiration)
+ expired_locator = "http://localhost:25107/" + SignLocator(TEST_HASH, known_token, expired_timestamp)
+ )
+
+ // Authenticated request, signed locator
+ // => OK
+ response = IssueRequest(rest, &RequestTester{
+ method: "GET",
+ uri: signed_locator,
+ api_token: known_token,
+ })
+ ExpectStatusCode(t, "signed GET (permissions on)", http.StatusOK, response)
+ ExpectBody(t, "signed GET (permissions on)", string(TEST_BLOCK), response)
+
+ // Authenticated request, unsigned locator
+ // => PermissionError
+ response = IssueRequest(rest, &RequestTester{
+ method: "GET",
+ uri: unsigned_locator,
+ api_token: known_token,
+ })
+ ExpectStatusCode(t, "unsigned locator", PermissionError.HTTPCode, response)
+
+ // Unauthenticated request, signed locator
+ // => PermissionError
+ response = IssueRequest(rest, &RequestTester{
+ method: "GET",
+ uri: signed_locator,
+ })
+ ExpectStatusCode(t, "signed locator", PermissionError.HTTPCode, response)
+
+ // Authenticated request, expired locator
+ // => ExpiredError
+ response = IssueRequest(rest, &RequestTester{
+ method: "GET",
+ uri: expired_locator,
+ api_token: known_token,
+ })
+ ExpectStatusCode(t, "expired signature", ExpiredError.HTTPCode, response)
}
+// Test PutBlockHandler on the following situations:
+// - no server key
+// - with server key, authenticated request, unsigned locator
+// - with server key, unauthenticated request, unsigned locator
+//
func TestPutHandler(t *testing.T) {
defer teardown()
@@ -96,48 +131,71 @@ func TestPutHandler(t *testing.T) {
// Set up a REST router for testing the handlers.
rest := NewRESTRouter()
- // Execute a PUT request.
- test_url := "http://localhost:25107/" + TEST_HASH
- test_body := bytes.NewReader(TEST_BLOCK)
- req, _ := http.NewRequest("PUT", test_url, test_body)
- resp := httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
+ // --------------
+ // No server key.
- ExpectStatusCode(t, "permissions off", resp, http.StatusOK)
- ExpectBody(t, "permissions off", resp, TEST_HASH)
+ // Unauthenticated request, no server key
+ // => OK (unsigned response)
+ unsigned_locator := "http://localhost:25107/" + TEST_HASH
+ response := IssueRequest(rest,
+ &RequestTester{
+ method: "PUT",
+ uri: unsigned_locator,
+ request_body: TEST_BLOCK,
+ })
+
+ ExpectStatusCode(t,
+ "unauthenticated PUT (no server key)", http.StatusOK, response)
+ ExpectBody(t, "unauthenticated PUT (no server key)", TEST_HASH, response)
+
+ // ------------------
+ // With a server key.
- // Add a permission key.
- // When a permission key is available, the locator returned
- // from a PUT request will be signed.
PermissionSecret = []byte(known_key)
permission_ttl = time.Duration(300) * time.Second
- // An authenticated PUT request returns a signed locator.
- test_url = "http://localhost:25107/" + TEST_HASH
- test_body = bytes.NewReader(TEST_BLOCK)
- req, _ = http.NewRequest("PUT", test_url, test_body)
- req.Header.Set("Authorization", "OAuth "+known_token)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "authenticated PUT", resp, http.StatusOK)
- if !VerifySignature(resp.Body.String(), known_token) {
- t.Errorf("authenticated PUT: response '%s' failed signature check",
- resp.Body.String())
+ // When a permission key is available, the locator returned
+ // from an authenticated PUT request will be signed.
+
+ // Authenticated PUT, signed locator
+ // => OK (signed response)
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "PUT",
+ uri: unsigned_locator,
+ request_body: TEST_BLOCK,
+ api_token: known_token,
+ })
+
+ ExpectStatusCode(t,
+ "authenticated PUT (with server key)", http.StatusOK, response)
+ if !VerifySignature(response.Body.String(), known_token) {
+ t.Errorf("authenticated PUT (with server key): response '%s' does not contain a valid signature",
+ response.Body.String())
}
- // An unauthenticated PUT request returns an unsigned locator
- // even when a permission key is available.
- test_url = "http://localhost:25107/" + TEST_HASH
- test_body = bytes.NewReader(TEST_BLOCK)
- req, _ = http.NewRequest("PUT", test_url, test_body)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "anon PUT with server key", resp, http.StatusOK)
- ExpectBody(t, "anon PUT with server key", resp, TEST_HASH)
+ // Unauthenticated PUT, unsigned locator
+ // => OK
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "PUT",
+ uri: unsigned_locator,
+ request_body: TEST_BLOCK,
+ })
+
+ ExpectStatusCode(t,
+ "unauthenticated PUT (with server key)", http.StatusOK, response)
+ ExpectBody(t,
+ "unauthenticated PUT (with server key)", TEST_HASH, response)
}
+// Test /index requests:
+// - unauthenticated /index/{prefix} request
+// - unauthenticated /index request
+// - authenticated /index request, non-superuser
+// - authenticated /index request by superuser, enforce_permissions = false
+// - authenticated /index request by superuser, enforce_permissions = true
+//
func TestIndexHandler(t *testing.T) {
defer teardown()
@@ -154,64 +212,102 @@ func TestIndexHandler(t *testing.T) {
// Set up a REST router for testing the handlers.
rest := NewRESTRouter()
- // Requests for /index with a prefix are okay even if unauthenticated.
- test_url := "http://localhost:25107/index/" + TEST_HASH[0:5]
- req, _ := http.NewRequest("GET", test_url, nil)
- resp := httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
+ // Unauthenticated /index/{prefix}
+ // => OK
+ response := IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: "http://localhost:25107/index/" + TEST_HASH[0:5],
+ })
expected := `^` + TEST_HASH + `\+\d+ \d+\n$`
- match, _ := regexp.MatchString(expected, resp.Body.String())
+ match, _ := regexp.MatchString(expected, response.Body.String())
if !match {
t.Errorf("IndexHandler expected: %s, returned:\n%s",
- expected, resp.Body.String())
+ expected, response.Body.String())
}
- // Unauthenticated /index requests: fail.
- test_url = "http://localhost:25107/index"
- req, _ = http.NewRequest("GET", test_url, nil)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "unauthenticated /index", resp, PermissionError.HTTPCode)
-
- // Authenticated /index requests by a non-superuser: also fail.
- test_url = "http://localhost:25107/index"
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+known_token)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
-
- ExpectStatusCode(t, "authenticated /index", resp, PermissionError.HTTPCode)
-
- // Even superuser /index requests fail if enforce_permissions is off!
+ // Unauthenticated /index
+ // => PermissionError
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: "http://localhost:25107/index",
+ })
+
+ ExpectStatusCode(t,
+ "unauthenticated /index", PermissionError.HTTPCode, response)
+
+ // Authenticated /index request by non-superuser
+ // => PermissionError
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: "http://localhost:25107/index",
+ api_token: known_token,
+ })
+
+ ExpectStatusCode(t,
+ "authenticated /index by non-superuser",
+ PermissionError.HTTPCode,
+ response)
+
+ // Authenticated /index request by superuser, enforce_permissions = false
+ // => PermissionError
enforce_permissions = false
data_manager_token = "DATA MANAGER TOKEN"
- test_url = "http://localhost:25107/index"
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+data_manager_token)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
- ExpectStatusCode(t, "superuser /index (permissions off)", resp, PermissionError.HTTPCode)
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: "http://localhost:25107/index",
+ api_token: data_manager_token,
+ })
- // Superuser /index requests with enforce_permissions set: succeed!
+ ExpectStatusCode(t,
+ "authenticated /index request by superuser (permissions off)",
+ PermissionError.HTTPCode,
+ response)
+
+ // Authenticated /index request by superuser, enforce_permissions = true
+ // => OK
enforce_permissions = true
- data_manager_token = "DATA MANAGER TOKEN"
- test_url = "http://localhost:25107/index"
- req, _ = http.NewRequest("GET", test_url, nil)
- req.Header.Set("Authorization", "OAuth "+data_manager_token)
- resp = httptest.NewRecorder()
- rest.ServeHTTP(resp, req)
+ response = IssueRequest(rest,
+ &RequestTester{
+ method: "GET",
+ uri: "http://localhost:25107/index",
+ api_token: data_manager_token,
+ })
+
+ ExpectStatusCode(t,
+ "authenticated /index request by superuser (permissions on)",
+ http.StatusOK,
+ response)
- ExpectStatusCode(t, "superuser /index (permissions on)", resp, http.StatusOK)
expected = `^` + TEST_HASH + `\+\d+ \d+\n` +
TEST_HASH_2 + `\+\d+ \d+\n$`
- match, _ = regexp.MatchString(expected, resp.Body.String())
+ match, _ = regexp.MatchString(expected, response.Body.String())
if !match {
t.Errorf("superuser /index: expected %s, got:\n%s",
- expected, resp.Body.String())
+ expected, response.Body.String())
+ }
+}
+
+// ====================
+// Helper functions
+// ====================
+
+// IssueTestRequest executes an HTTP request described by rt, to a
+// specified REST router. It returns the HTTP response to the request.
+func IssueRequest(router *mux.Router, rt *RequestTester) *httptest.ResponseRecorder {
+ response := httptest.NewRecorder()
+ body := bytes.NewReader(rt.request_body)
+ req, _ := http.NewRequest(rt.method, rt.uri, body)
+ if rt.api_token != "" {
+ req.Header.Set("Authorization", "OAuth "+rt.api_token)
}
+ router.ServeHTTP(response, req)
+ return response
}
// ExpectStatusCode checks whether a response has the specified status code,
@@ -219,8 +315,8 @@ func TestIndexHandler(t *testing.T) {
func ExpectStatusCode(
t *testing.T,
testname string,
- response *httptest.ResponseRecorder,
- expected_status int) {
+ expected_status int,
+ response *httptest.ResponseRecorder) {
if response.Code != expected_status {
t.Errorf("%s: expected status %s, got %+v",
testname, expected_status, response)
@@ -230,8 +326,8 @@ func ExpectStatusCode(
func ExpectBody(
t *testing.T,
testname string,
- response *httptest.ResponseRecorder,
- expected_body string) {
+ expected_body string,
+ response *httptest.ResponseRecorder) {
if response.Body.String() != expected_body {
t.Errorf("%s: expected response body '%s', got %+v",
testname, expected_body, response)
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list