From 2b66ccfd566f16e7010ca55632d1e7a90e0993f7 Mon Sep 17 00:00:00 2001 From: Acconut Date: Tue, 17 Feb 2015 15:44:12 +0100 Subject: [PATCH] refactor tests using httpTest --- concat_test.go | 135 ++++++++++++++++++++++-------------------------- cors_test.go | 64 ++++++++++------------- datastore.go | 4 +- get_test.go | 26 ++++------ handler_test.go | 52 +++++++++++++++++++ head_test.go | 49 ++++++++---------- options_test.go | 47 +++++++---------- patch_test.go | 101 +++++++++++++++++++----------------- post_test.go | 48 +++++++++-------- 9 files changed, 270 insertions(+), 256 deletions(-) diff --git a/concat_test.go b/concat_test.go index b839069..ee3d09d 100644 --- a/concat_test.go +++ b/concat_test.go @@ -4,7 +4,6 @@ import ( "io" "io/ioutil" "net/http" - "net/http/httptest" "reflect" "strings" "testing" @@ -46,31 +45,29 @@ func TestConcatPartial(t *testing.T) { }, }) - // Test successful POST request - req, _ := http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Entity-Length", "300") - req.Header.Set("Concat", "partial") - req.Host = "tus.io" - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusCreated { - t.Errorf("Expected 201 Created (got %v)", w.Code) - } + (&httpTest{ + Name: "Successful POST request", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Entity-Length": "300", + "Concat": "partial", + }, + Code: http.StatusCreated, + }).Run(handler, t) - // Test successful HEAD request - req, _ = http.NewRequest("HEAD", "foo", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Host = "tus.io" - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected 204 No Content (got %v)", w.Code) - } - - if w.HeaderMap.Get("Concat") != "partial" { - t.Errorf("Expect Concat header to be set") - } + (&httpTest{ + Name: "Successful HEAD request", + Method: "HEAD", + URL: "foo", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + }, + Code: http.StatusNoContent, + ResHeader: map[string]string{ + "Concat": "partial", + }, + }).Run(handler, t) } type concatFinalStore struct { @@ -161,47 +158,40 @@ func TestConcatFinal(t *testing.T) { }, }) - // Test successful POST request - req, _ := http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Concat", "final; http://tus.io/files/a /files/b/") - req.Host = "tus.io" - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusCreated { - t.Errorf("Expected 201 Created (got %v)", w.Code) - } + (&httpTest{ + Name: "Successful POST request", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Concat": "final; http://tus.io/files/a /files/b/", + }, + Code: http.StatusCreated, + }).Run(handler, t) - // Test successful HEAD request - req, _ = http.NewRequest("HEAD", "foo", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Host = "tus.io" - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected 204 No Content (got %v)", w.Code) - } + (&httpTest{ + Name: "Successful HEAD request", + Method: "HEAD", + URL: "foo", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + }, + Code: http.StatusNoContent, + ResHeader: map[string]string{ + "Concat": "final; http://tus.io/files/a http://tus.io/files/b", + "Entity-Length": "10", + }, + }).Run(handler, t) - if w.HeaderMap.Get("Concat") != "final; http://tus.io/files/a http://tus.io/files/b" { - t.Errorf("Expect Concat header to be set") - } + (&httpTest{ + Name: "Concatenating non finished upload (id: c)", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Concat": "final; http://tus.io/files/c", + }, + Code: http.StatusBadRequest, + }).Run(handler, t) - if w.HeaderMap.Get("Entity-Length") != "10" { - t.Errorf("Expect Entity-Length header to be 10") - } - - // Test concatenating non finished upload (id: c) - req, _ = http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Concat", "final; http://tus.io/files/c") - req.Host = "tus.io" - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusBadRequest { - t.Errorf("Expected 201 Created (got %v)", w.Code) - } - - // Test exceeding max. size handler, _ = NewHandler(Config{ MaxSize: 9, BasePath: "files", @@ -210,14 +200,13 @@ func TestConcatFinal(t *testing.T) { }, }) - req, _ = http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Concat", "final; http://tus.io/files/a /files/b/") - req.Host = "tus.io" - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusRequestEntityTooLarge { - t.Errorf("Expected 201 Created (got %v)", w.Code) - } - + (&httpTest{ + Name: "Exceeding MaxSize", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Concat": "final; http://tus.io/files/a /files/b/", + }, + Code: http.StatusRequestEntityTooLarge, + }).Run(handler, t) } diff --git a/cors_test.go b/cors_test.go index 7e92c5a..c1b24ae 100644 --- a/cors_test.go +++ b/cors_test.go @@ -2,49 +2,37 @@ package tusd import ( "net/http" - "net/http/httptest" "testing" ) func TestCORS(t *testing.T) { handler, _ := NewHandler(Config{}) - // Test preflight request - req, _ := http.NewRequest("OPTIONS", "", nil) - req.Header.Set("Origin", "tus.io") - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected 204 No Content for OPTIONS request (got %v)", w.Code) - } + (&httpTest{ + Name: "Preflight request", + Method: "OPTIONS", + ReqHeader: map[string]string{ + "Origin": "tus.io", + }, + Code: http.StatusNoContent, + ResHeader: map[string]string{ + "Access-Control-Allow-Headers": "", + "Access-Control-Allow-Methods": "", + "Access-Control-Max-Age": "", + "Access-Control-Allow-Origin": "tus.io", + }, + }).Run(handler, t) - headers := []string{ - "Access-Control-Allow-Headers", - "Access-Control-Allow-Methods", - "Access-Control-Max-Age", - } - for _, header := range headers { - if _, ok := w.HeaderMap[header]; !ok { - t.Errorf("Header '%s' not contained in response", header) - } - } - - origin := w.HeaderMap.Get("Access-Control-Allow-Origin") - if origin != "tus.io" { - t.Errorf("Allowed origin not 'tus.io' but '%s'", origin) - } - - // Test actual request - req, _ = http.NewRequest("GET", "", nil) - req.Header.Set("Origin", "tus.io") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - - origin = w.HeaderMap.Get("Access-Control-Allow-Origin") - if origin != "tus.io" { - t.Errorf("Allowed origin not 'tus.io' but '%s'", origin) - } - if _, ok := w.HeaderMap["Access-Control-Expose-Headers"]; !ok { - t.Error("Expose-Headers not contained in response") - } + (&httpTest{ + Name: "Actual request", + Method: "GET", + ReqHeader: map[string]string{ + "Origin": "tus.io", + }, + Code: http.StatusMethodNotAllowed, + ResHeader: map[string]string{ + "Access-Control-Expose-Headers": "", + "Access-Control-Allow-Origin": "tus.io", + }, + }).Run(handler, t) } diff --git a/datastore.go b/datastore.go index 4922077..a5a07e4 100644 --- a/datastore.go +++ b/datastore.go @@ -16,9 +16,9 @@ type FileInfo struct { // Indicates that this is a partial upload which will later be used to form // a final upload by concatenation. Partial uploads should not be processed // when they are finished since they are only incomplete chunks of files. - IsPartial bool + IsPartial bool // Indicates that this is a final upload - IsFinal bool + IsFinal bool // If the upload is a final one (see IsFinal) this will be a non-empty // ordered slice containing the ids of the uploads of which the final upload // will consist after concatenation. diff --git a/get_test.go b/get_test.go index 63de25a..60da8b4 100644 --- a/get_test.go +++ b/get_test.go @@ -3,7 +3,6 @@ package tusd import ( "io" "net/http" - "net/http/httptest" "os" "strings" "testing" @@ -33,19 +32,14 @@ func TestGet(t *testing.T) { DataStore: getStore{}, }) - // Test successfull download - req, _ := http.NewRequest("GET", "yes", nil) - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusOK { - t.Errorf("Expected %v (got %v)", http.StatusOK, w.Code) - } - - if string(w.Body.Bytes()) != "hello" { - t.Errorf("Expected response body to be 'hello'") - } - - if w.HeaderMap.Get("Content-Length") != "5" { - t.Errorf("Expected Content-Length to be 5") - } + (&httpTest{ + Name: "Successful download", + Method: "GET", + URL: "yes", + Code: http.StatusOK, + ResBody: "hello", + ResHeader: map[string]string{ + "Content-Length": "5", + }, + }).Run(handler, t) } diff --git a/handler_test.go b/handler_test.go index 85d679e..fc33de5 100644 --- a/handler_test.go +++ b/handler_test.go @@ -2,6 +2,9 @@ package tusd import ( "io" + "net/http" + "net/http/httptest" + "testing" ) type zeroStore struct{} @@ -20,3 +23,52 @@ func (store zeroStore) GetInfo(id string) (FileInfo, error) { func (store zeroStore) GetReader(id string) (io.Reader, error) { return nil, ErrNotImplemented } + +type httpTest struct { + Name string + + Method string + URL string + + ReqBody io.Reader + ReqHeader map[string]string + + Code int + ResBody string + ResHeader map[string]string +} + +func (test *httpTest) Run(handler http.Handler, t *testing.T) { + t.Log(test.Name) + + req, _ := http.NewRequest(test.Method, test.URL, test.ReqBody) + + // Add headers + for key, value := range test.ReqHeader { + req.Header.Set(key, value) + } + + req.Host = "tus.io" + w := httptest.NewRecorder() + handler.ServeHTTP(w, req) + + if w.Code != test.Code { + t.Errorf("Expected %v as status code (got %v)", test.Code, w.Code) + } + + for key, value := range test.ResHeader { + header := w.HeaderMap.Get(key) + + if value == "" && header == "" { + t.Errorf("Expected '%s' in response", key) + } + + if value != "" && value != header { + t.Errorf("Expected '%s' as '%s' (got '%s')", value, key, header) + } + } + + if test.ResBody != "" && string(w.Body.Bytes()) != test.ResBody { + t.Errorf("Expected '%s' as body (got '%s'", test.ResBody, string(w.Body.Bytes())) + } +} diff --git a/head_test.go b/head_test.go index 99182b3..e0ad2a3 100644 --- a/head_test.go +++ b/head_test.go @@ -2,7 +2,6 @@ package tusd import ( "net/http" - "net/http/httptest" "os" "testing" ) @@ -28,31 +27,27 @@ func TestHead(t *testing.T) { DataStore: headStore{}, }) - // Test successful request - req, _ := http.NewRequest("HEAD", "yes", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) - } + (&httpTest{ + Name: "Successful request", + Method: "HEAD", + URL: "yes", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + }, + Code: http.StatusNoContent, + ResHeader: map[string]string{ + "Offset": "11", + "Entity-Length": "44", + }, + }).Run(handler, t) - headers := map[string]string{ - "Offset": "11", - "Entity-Length": "44", - } - for header, value := range headers { - if v := w.HeaderMap.Get(header); value != v { - t.Errorf("Unexpected header value '%s': %v", header, v) - } - } - - // Test non-existing file - req, _ = http.NewRequest("HEAD", "no", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNotFound { - t.Errorf("Expected %v (got %v)", http.StatusNotFound, w.Code) - } + (&httpTest{ + Name: "Non-existing file", + Method: "HEAD", + URL: "no", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + }, + Code: http.StatusNotFound, + }).Run(handler, t) } diff --git a/options_test.go b/options_test.go index 552e7ef..465485a 100644 --- a/options_test.go +++ b/options_test.go @@ -2,7 +2,6 @@ package tusd import ( "net/http" - "net/http/httptest" "testing" ) @@ -11,32 +10,24 @@ func TestOptions(t *testing.T) { MaxSize: 400, }) - // Test successful OPTIONS request - req, _ := http.NewRequest("OPTIONS", "", nil) - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected 204 No Content for OPTIONS request (got %v)", w.Code) - } + (&httpTest{ + Name: "Successful request", + Method: "OPTIONS", + Code: http.StatusNoContent, + ResHeader: map[string]string{ + "TUS-Extension": "file-creation,metadata,concatenation", + "TUS-Version": "1.0.0", + "TUS-Resumable": "1.0.0", + "TUS-Max-Size": "400", + }, + }).Run(handler, t) - headers := map[string]string{ - "TUS-Extension": "file-creation,metadata,concatenation", - "TUS-Version": "1.0.0", - "TUS-Resumable": "1.0.0", - "TUS-Max-Size": "400", - } - for header, value := range headers { - if v := w.HeaderMap.Get(header); value != v { - t.Errorf("Header '%s' not contained in response", header) - } - } - - // Invalid or unsupported version - req, _ = http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "foo") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusPreconditionFailed { - t.Errorf("Expected 412 Precondition Failed (got %v)", w.Code) - } + (&httpTest{ + Name: "Invalid or unsupported version", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "foo", + }, + Code: http.StatusPreconditionFailed, + }).Run(handler, t) } diff --git a/patch_test.go b/patch_test.go index c85c077..cd0a708 100644 --- a/patch_test.go +++ b/patch_test.go @@ -4,7 +4,6 @@ import ( "io" "io/ioutil" "net/http" - "net/http/httptest" "os" "strings" "testing" @@ -57,45 +56,51 @@ func TestPatch(t *testing.T) { }, }) - // Test successful request - req, _ := http.NewRequest("PATCH", "yes", strings.NewReader("hello")) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Offset", "5") - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) - } + (&httpTest{ + Name: "Successful request", + Method: "PATCH", + URL: "yes", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Offset": "5", + }, + ReqBody: strings.NewReader("hello"), + Code: http.StatusNoContent, + }).Run(handler, t) - // Test non-existing file - req, _ = http.NewRequest("PATCH", "no", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Offset", "0") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNotFound { - t.Errorf("Expected %v (got %v)", http.StatusNotFound, w.Code) - } + (&httpTest{ + Name: "Non-existing file", + Method: "PATCH", + URL: "no", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Offset": "5", + }, + Code: http.StatusNotFound, + }).Run(handler, t) - // Test wrong offset - req, _ = http.NewRequest("PATCH", "yes", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Offset", "4") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusConflict { - t.Errorf("Expected %v (got %v)", http.StatusConflict, w.Code) - } + (&httpTest{ + Name: "Wrong offset", + Method: "PATCH", + URL: "yes", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Offset": "4", + }, + Code: http.StatusConflict, + }).Run(handler, t) - // Test exceeding file size - req, _ = http.NewRequest("PATCH", "yes", strings.NewReader("hellothisismorethan15bytes")) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Offset", "5") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusRequestEntityTooLarge { - t.Errorf("Expected %v (got %v)", http.StatusRequestEntityTooLarge, w.Code) - } + (&httpTest{ + Name: "Exceeding file size", + Method: "PATCH", + URL: "yes", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Offset": "5", + }, + ReqBody: strings.NewReader("hellothisismorethan15bytes"), + Code: http.StatusRequestEntityTooLarge, + }).Run(handler, t) } type overflowPatchStore struct { @@ -180,14 +185,16 @@ func TestPatchOverflow(t *testing.T) { body.Close() }() - // Test too big body exceeding file size - req, _ := http.NewRequest("PATCH", "yes", body) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Offset", "5") - req.Header.Set("Content-Length", "3") - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusNoContent { - t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) - } + (&httpTest{ + Name: "Too big body exceeding file size", + Method: "PATCH", + URL: "yes", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Offset": "5", + "Content-Length": "3", + }, + ReqBody: body, + Code: http.StatusNoContent, + }).Run(handler, t) } diff --git a/post_test.go b/post_test.go index a4dac3f..78f7280 100644 --- a/post_test.go +++ b/post_test.go @@ -2,7 +2,6 @@ package tusd import ( "net/http" - "net/http/httptest" "testing" ) @@ -41,29 +40,28 @@ func TestPost(t *testing.T) { }, }) - // Test successful request - req, _ := http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Entity-Length", "300") - req.Header.Set("Metadata", "foo aGVsbG8=, bar d29ybGQ=") - req.Host = "tus.io" - w := httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusCreated { - t.Errorf("Expected 201 Created for OPTIONS request (got %v)", w.Code) - } + (&httpTest{ + Name: "Successful request", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Entity-Length": "300", + "Metadata": "foo aGVsbG8=, bar d29ybGQ=", + }, + Code: http.StatusCreated, + ResHeader: map[string]string{ + "Location": "http://tus.io/files/foo", + }, + }).Run(handler, t) - if location := w.HeaderMap.Get("Location"); location != "http://tus.io/files/foo" { - t.Errorf("Unexpected location header (got '%v')", location) - } - - // Test exceeding MaxSize - req, _ = http.NewRequest("POST", "", nil) - req.Header.Set("TUS-Resumable", "1.0.0") - req.Header.Set("Entity-Length", "500") - w = httptest.NewRecorder() - handler.ServeHTTP(w, req) - if w.Code != http.StatusRequestEntityTooLarge { - t.Errorf("Expected %v for OPTIONS request (got %v)", http.StatusRequestEntityTooLarge, w.Code) - } + (&httpTest{ + Name: "Exceeding MaxSize", + Method: "POST", + ReqHeader: map[string]string{ + "TUS-Resumable": "1.0.0", + "Entity-Length": "500", + "Metadata": "foo aGVsbG8=, bar d29ybGQ=", + }, + Code: http.StatusRequestEntityTooLarge, + }).Run(handler, t) }