tests: Add helper function for API handler anonymous request tests. (#2876)

- Add helper function for API handler anonymous request tests.
- Add PutObject Part Anonymous request case using the new helper
  function to validate its functionality.
This commit is contained in:
Karthic Rao
2016-10-07 23:46:11 +05:30
committed by Harshavardhana
parent f1bc9343a1
commit d1df5e0ae1
2 changed files with 89 additions and 101 deletions

View File

@@ -1387,6 +1387,76 @@ func initAPIHandlerTest(obj ObjectLayer, endPoints []string) (bucketName, rootPa
return bucketName, rootPath, apiRouter, nil
}
// ExecObjectLayerAPIAnonTest - Helper function to validate object Layer API handler response for anonymous/unsigned HTTP request.
// Here is the brief description of some of the arguments to the function below.
// apiRouter - http.Handler with the relevant API endPoint (API endPoint under test) registered.
// anonReq - unsigned *http.Request to invoke the handler's response for anonymous requests.
// policyFunc - function to return bucketPolicy statement which would permit the anonymous request to be served.
// The test works in 2 steps, here is the description of the steps.
// STEP 1: Call the handler with the unsigned HTTP request (anonReq), assert for the `ErrAccessDenied` error response.
// STEP 2: Set the policy to allow the unsigned request, use the policyFunc to obtain the relevant statement and call the handler again to verify its success.
func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, instanceType string, apiRouter http.Handler,
anonReq *http.Request, policyFunc func(string, string) policyStatement) {
// simple function which ends the test by printing the common message which gives the context of the test
// and then followed by the the actual error message.
failTest := func(failMsg string) {
t.Fatalf("Minio %s: Anonymous HTTP request test Fail for \"%s\": \n<Error> %s.", instanceType, testName, failMsg)
}
// httptest Recorder to capture all the response by the http handler.
rec := httptest.NewRecorder()
// reading the body to preserve it so that it can be used again for second attempt of sending unsigned HTTP request.
// If the body is read in the handler the same request cannot be made use of.
buf, err := ioutil.ReadAll(anonReq.Body)
if err != nil {
failTest(err.Error())
}
// creating 2 read closer (to set as request body) from the body content.
readerOne := ioutil.NopCloser(bytes.NewBuffer(buf))
readerTwo := ioutil.NopCloser(bytes.NewBuffer(buf))
anonReq.Body = readerOne
// call the HTTP handler.
apiRouter.ServeHTTP(rec, anonReq)
// expected error response when the unsigned HTTP request is not permitted.
accesDeniedHTTPStatus := getAPIError(ErrAccessDenied).HTTPStatusCode
if rec.Code != accesDeniedHTTPStatus {
failTest(fmt.Sprintf("Object API Nil Test expected to fail with %d, but failed with %d.", accesDeniedHTTPStatus, rec.Code))
}
// expected error response in bytes when objectLayer is not initialized, or set to `nil`.
expectedErrResponse := encodeResponse(getAPIErrorResponse(getAPIError(ErrAccessDenied), getGetObjectURL("", bucketName, objectName)))
// read the response body.
actualContent, err := ioutil.ReadAll(rec.Body)
if err != nil {
failTest(fmt.Sprintf("Failed parsing response body: <ERROR> %v.", err))
}
// verify whether actual error response (from the response body), matches the expected error response.
if !bytes.Equal(expectedErrResponse, actualContent) {
failTest("Object content differs from expected value.")
}
// Set write only policy on bucket to allow anonymous HTTP request for the operation under test.
// request to go through.
policy := bucketPolicy{
Version: "1.0",
Statements: []policyStatement{policyFunc(bucketName, "")},
}
globalBucketPolicies.SetBucketPolicy(bucketName, &policy)
// now call the handler again with the unsigned/anonymous request, it should be accepted.
rec = httptest.NewRecorder()
anonReq.Body = readerTwo
apiRouter.ServeHTTP(rec, anonReq)
if rec.Code != http.StatusOK {
failTest(fmt.Sprintf("Expected the anonymous HTTP request to be served after the policy changes\n,Expected response HTTP status code to be %d, got %d.",
http.StatusOK, rec.Code))
}
}
// ExecObjectLayerAPINilTest - Sets the object layer to `nil`, and calls rhe registered object layer API endpoint, and assert the error response.
// The purpose is to validate the API handlers response when the object layer is uninitialized.
// Usage hint: Should be used at the end of the API end points tests (ex: check the last few lines of `testAPIListObjectPartsHandler`), need a sample HTTP request
@@ -1606,19 +1676,6 @@ func registerAPIFunctions(muxRouter *router.Router, objLayer ObjectLayer, apiFun
registerBucketLevelFunc(bucketRouter, api, apiFunctions...)
}
// Returns a http.Handler capable of routing API requests to handlers corresponding to apiFunctions,
// with ObjectAPI set to nil.
func initTestNilObjAPIEndPoints(apiFunctions []string) http.Handler {
muxRouter := router.NewRouter()
if len(apiFunctions) > 0 {
// Iterate the list of API functions requested for and register them in mux HTTP handler.
registerAPIFunctions(muxRouter, nil, apiFunctions...)
return muxRouter
}
registerAPIRouter(muxRouter)
return muxRouter
}
// Takes in XL/FS object layer, and the list of API end points to be tested/required, registers the API end points and returns the HTTP handler.
// Need isolated registration of API end points while writing unit tests for end points.
// All the API end points are registered only for the default case.