From 4aea1173303949c19c57aa0ea9f34cd65df15a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Carranza=20V=C3=A9lez?= Date: Wed, 26 Aug 2015 22:42:10 +0000 Subject: [PATCH] Purge handles strings and numbers, and is tested with a table --- gosuper/gosuper/main_test.go | 72 +++++++++++++++++++++++------------- gosuper/gosuper/purge.go | 26 +++++++++++-- src/api.coffee | 2 +- 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/gosuper/gosuper/main_test.go b/gosuper/gosuper/main_test.go index c0635551..ac62fdc8 100644 --- a/gosuper/gosuper/main_test.go +++ b/gosuper/gosuper/main_test.go @@ -9,36 +9,58 @@ import ( "testing" ) +var purgeTests = []struct { + JsonInput string + AppId string + JsonResponse string + IsSuccess bool + HttpStatus int +}{ + {`{"applicationId": "1"}`, "1", `{"Status":"OK","Error":""}`, true, http.StatusOK}, + {`{"applicationId": 1}`, "1", `{"Status":"OK","Error":""}`, true, http.StatusOK}, + {`{"applicationId": "hi"}`, "1", `{"Status":"Error","Error":"Invalid applicationId 'hi'"}`, false, http.StatusBadRequest}, + {`{"applicationId": "2"}`, "1", `{"Status":"Error","Error":"Invalid applicationId '2': Directory does not exist"}`, false, http.StatusNotFound}, + {`{}`, "1", `{"Status":"Error","Error":"applicationId is required"}`, false, http.StatusBadRequest}, +} + func TestPurge(t *testing.T) { - appId := "1" - request, err := http.NewRequest("POST", "/v1/purge", strings.NewReader(`{"applicationId": "`+appId+`"}`)) - if err != nil { - t.Fatal(err) - } - request.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") - writer := httptest.NewRecorder() - ResinDataPath = "test-data/" - dataPath := ResinDataPath + appId + for i, testCase := range purgeTests { + t.Logf("Testing Purge case #%d", i) + request, err := http.NewRequest("POST", "/v1/purge", strings.NewReader(testCase.JsonInput)) + if err != nil { + t.Fatal(err) + } + request.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") + writer := httptest.NewRecorder() + ResinDataPath = "test-data/" + dataPath := ResinDataPath + testCase.AppId + testFile := dataPath + "/test" - if err = os.MkdirAll(dataPath, 0755); err != nil { - t.Fatal("Could not create test directory for purge") - } else if err = ioutil.WriteFile(dataPath+"/test", []byte("test"), 0777); err != nil { - t.Fatal("Could not create test file for purge") - } + if err = os.MkdirAll(dataPath, 0755); err != nil { + t.Fatal("Could not create test directory for purge") + } else if err = ioutil.WriteFile(testFile, []byte("test"), 0777); err != nil { + t.Fatal("Could not create test file for purge") + } - PurgeHandler(writer, request) + PurgeHandler(writer, request) - if writer.Code != http.StatusOK { - t.Errorf("Purge didn't return %v", http.StatusOK) - } - if !strings.EqualFold(writer.Body.String(), `{"Status":"OK","Error":""}`) { - t.Errorf("Purge response didn't match the expected JSON, got: %s", writer.Body.String()) - } + if writer.Code != testCase.HttpStatus { + t.Errorf("Purge didn't return %v, got %v", testCase.HttpStatus, writer.Code) + } + if !strings.EqualFold(writer.Body.String(), testCase.JsonResponse) { + t.Errorf(`Purge response didn't match the expected JSON, expected "%s" got: "%s"`, testCase.JsonResponse, writer.Body.String()) + } - if dirContents, err := ioutil.ReadDir(dataPath); err != nil { - t.Errorf("Could not read the data path after purge: %s", err) - } else if len(dirContents) > 0 { - t.Error("Data directory not empty after purge") + if dirContents, err := ioutil.ReadDir(dataPath); err != nil { + t.Errorf("Could not read the data path after purge: %s", err) + } else { + fileCount := len(dirContents) + if fileCount > 0 && testCase.IsSuccess { + t.Error("Data directory not empty after purge") + } else if fileCount == 0 && !testCase.IsSuccess { + t.Error("Data directory empty after purge (but it failed)") + } + } } } diff --git a/gosuper/gosuper/purge.go b/gosuper/gosuper/purge.go index 2d09f7ff..083c8086 100644 --- a/gosuper/gosuper/purge.go +++ b/gosuper/gosuper/purge.go @@ -6,6 +6,7 @@ import ( "log" "net/http" "os" + "strconv" ) type ApiResponse struct { @@ -14,7 +15,7 @@ type ApiResponse struct { } type PurgeBody struct { - ApplicationId string + ApplicationId interface{} } func jsonResponse(writer http.ResponseWriter, response interface{}, status int) { @@ -32,9 +33,26 @@ func parseJsonBody(destination interface{}, request *http.Request) error { return decoder.Decode(&destination) } +func parsePurgeBody(request *http.Request) (appId string, err error) { + var body PurgeBody + if err = parseJsonBody(&body, request); err != nil { + return + } + switch v := body.ApplicationId.(type) { + case string: + appId = v + case float64: + if v != 0 { + appId = strconv.Itoa(int(v)) + } + default: + log.Printf("Invalid appId type %T\n", v) + } + return +} + func PurgeHandler(writer http.ResponseWriter, request *http.Request) { log.Println("Purging /data") - var body PurgeBody sendResponse := func(statusMsg, errorMsg string, statusCode int) { jsonResponse(writer, ApiResponse{statusMsg, errorMsg}, statusCode) @@ -46,9 +64,9 @@ func PurgeHandler(writer http.ResponseWriter, request *http.Request) { sendResponse("Error", errorMsg, http.StatusBadRequest) } - if err := parseJsonBody(&body, request); err != nil { + if appId, err := parsePurgeBody(request); err != nil { sendBadRequest("Invalid request") - } else if appId := body.ApplicationId; appId == "" { + } else if appId == "" { sendBadRequest("applicationId is required") } else if !IsValidAppId(appId) { sendBadRequest(fmt.Sprintf("Invalid applicationId '%s'", appId)) diff --git a/src/api.coffee b/src/api.coffee index 8bd893af..24902704 100644 --- a/src/api.coffee +++ b/src/api.coffee @@ -75,7 +75,7 @@ module.exports = (secret) -> application.kill(app) .then -> new Promise (resolve, reject) -> - request.post(config.gosuperAddress + '/v1/purge', { json: true, body: applicationId: appId.toString() }) + request.post(config.gosuperAddress + '/v1/purge', { json: true, body: applicationId: appId }) .on 'error', reject .on 'response', -> resolve() .pipe(res)