refactor tests using httpTest

This commit is contained in:
Acconut 2015-02-17 15:44:12 +01:00
parent 93eb701e14
commit 2b66ccfd56
9 changed files with 270 additions and 256 deletions

View File

@ -4,7 +4,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
@ -46,31 +45,29 @@ func TestConcatPartial(t *testing.T) {
}, },
}) })
// Test successful POST request (&httpTest{
req, _ := http.NewRequest("POST", "", nil) Name: "Successful POST request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "POST",
req.Header.Set("Entity-Length", "300") ReqHeader: map[string]string{
req.Header.Set("Concat", "partial") "TUS-Resumable": "1.0.0",
req.Host = "tus.io" "Entity-Length": "300",
w := httptest.NewRecorder() "Concat": "partial",
handler.ServeHTTP(w, req) },
if w.Code != http.StatusCreated { Code: http.StatusCreated,
t.Errorf("Expected 201 Created (got %v)", w.Code) }).Run(handler, t)
}
// Test successful HEAD request (&httpTest{
req, _ = http.NewRequest("HEAD", "foo", nil) Name: "Successful HEAD request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "HEAD",
req.Host = "tus.io" URL: "foo",
w = httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusNoContent { },
t.Errorf("Expected 204 No Content (got %v)", w.Code) Code: http.StatusNoContent,
} ResHeader: map[string]string{
"Concat": "partial",
if w.HeaderMap.Get("Concat") != "partial" { },
t.Errorf("Expect Concat header to be set") }).Run(handler, t)
}
} }
type concatFinalStore struct { type concatFinalStore struct {
@ -161,47 +158,40 @@ func TestConcatFinal(t *testing.T) {
}, },
}) })
// Test successful POST request (&httpTest{
req, _ := http.NewRequest("POST", "", nil) Name: "Successful POST request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "POST",
req.Header.Set("Concat", "final; http://tus.io/files/a /files/b/") ReqHeader: map[string]string{
req.Host = "tus.io" "TUS-Resumable": "1.0.0",
w := httptest.NewRecorder() "Concat": "final; http://tus.io/files/a /files/b/",
handler.ServeHTTP(w, req) },
if w.Code != http.StatusCreated { Code: http.StatusCreated,
t.Errorf("Expected 201 Created (got %v)", w.Code) }).Run(handler, t)
}
// Test successful HEAD request (&httpTest{
req, _ = http.NewRequest("HEAD", "foo", nil) Name: "Successful HEAD request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "HEAD",
req.Host = "tus.io" URL: "foo",
w = httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusNoContent { },
t.Errorf("Expected 204 No Content (got %v)", w.Code) 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" { (&httpTest{
t.Errorf("Expect Concat header to be set") 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{ handler, _ = NewHandler(Config{
MaxSize: 9, MaxSize: 9,
BasePath: "files", BasePath: "files",
@ -210,14 +200,13 @@ func TestConcatFinal(t *testing.T) {
}, },
}) })
req, _ = http.NewRequest("POST", "", nil) (&httpTest{
req.Header.Set("TUS-Resumable", "1.0.0") Name: "Exceeding MaxSize",
req.Header.Set("Concat", "final; http://tus.io/files/a /files/b/") Method: "POST",
req.Host = "tus.io" ReqHeader: map[string]string{
w = httptest.NewRecorder() "TUS-Resumable": "1.0.0",
handler.ServeHTTP(w, req) "Concat": "final; http://tus.io/files/a /files/b/",
if w.Code != http.StatusRequestEntityTooLarge { },
t.Errorf("Expected 201 Created (got %v)", w.Code) Code: http.StatusRequestEntityTooLarge,
} }).Run(handler, t)
} }

View File

@ -2,49 +2,37 @@ package tusd
import ( import (
"net/http" "net/http"
"net/http/httptest"
"testing" "testing"
) )
func TestCORS(t *testing.T) { func TestCORS(t *testing.T) {
handler, _ := NewHandler(Config{}) handler, _ := NewHandler(Config{})
// Test preflight request (&httpTest{
req, _ := http.NewRequest("OPTIONS", "", nil) Name: "Preflight request",
req.Header.Set("Origin", "tus.io") Method: "OPTIONS",
w := httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "Origin": "tus.io",
if w.Code != http.StatusNoContent { },
t.Errorf("Expected 204 No Content for OPTIONS request (got %v)", w.Code) 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{ (&httpTest{
"Access-Control-Allow-Headers", Name: "Actual request",
"Access-Control-Allow-Methods", Method: "GET",
"Access-Control-Max-Age", ReqHeader: map[string]string{
} "Origin": "tus.io",
for _, header := range headers { },
if _, ok := w.HeaderMap[header]; !ok { Code: http.StatusMethodNotAllowed,
t.Errorf("Header '%s' not contained in response", header) ResHeader: map[string]string{
} "Access-Control-Expose-Headers": "",
} "Access-Control-Allow-Origin": "tus.io",
},
origin := w.HeaderMap.Get("Access-Control-Allow-Origin") }).Run(handler, t)
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")
}
} }

View File

@ -16,9 +16,9 @@ type FileInfo struct {
// Indicates that this is a partial upload which will later be used to form // 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 // a final upload by concatenation. Partial uploads should not be processed
// when they are finished since they are only incomplete chunks of files. // when they are finished since they are only incomplete chunks of files.
IsPartial bool IsPartial bool
// Indicates that this is a final upload // 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 // 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 // ordered slice containing the ids of the uploads of which the final upload
// will consist after concatenation. // will consist after concatenation.

View File

@ -3,7 +3,6 @@ package tusd
import ( import (
"io" "io"
"net/http" "net/http"
"net/http/httptest"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -33,19 +32,14 @@ func TestGet(t *testing.T) {
DataStore: getStore{}, DataStore: getStore{},
}) })
// Test successfull download (&httpTest{
req, _ := http.NewRequest("GET", "yes", nil) Name: "Successful download",
w := httptest.NewRecorder() Method: "GET",
handler.ServeHTTP(w, req) URL: "yes",
if w.Code != http.StatusOK { Code: http.StatusOK,
t.Errorf("Expected %v (got %v)", http.StatusOK, w.Code) ResBody: "hello",
} ResHeader: map[string]string{
"Content-Length": "5",
if string(w.Body.Bytes()) != "hello" { },
t.Errorf("Expected response body to be 'hello'") }).Run(handler, t)
}
if w.HeaderMap.Get("Content-Length") != "5" {
t.Errorf("Expected Content-Length to be 5")
}
} }

View File

@ -2,6 +2,9 @@ package tusd
import ( import (
"io" "io"
"net/http"
"net/http/httptest"
"testing"
) )
type zeroStore struct{} type zeroStore struct{}
@ -20,3 +23,52 @@ func (store zeroStore) GetInfo(id string) (FileInfo, error) {
func (store zeroStore) GetReader(id string) (io.Reader, error) { func (store zeroStore) GetReader(id string) (io.Reader, error) {
return nil, ErrNotImplemented 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()))
}
}

View File

@ -2,7 +2,6 @@ package tusd
import ( import (
"net/http" "net/http"
"net/http/httptest"
"os" "os"
"testing" "testing"
) )
@ -28,31 +27,27 @@ func TestHead(t *testing.T) {
DataStore: headStore{}, DataStore: headStore{},
}) })
// Test successful request (&httpTest{
req, _ := http.NewRequest("HEAD", "yes", nil) Name: "Successful request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "HEAD",
w := httptest.NewRecorder() URL: "yes",
handler.ServeHTTP(w, req) ReqHeader: map[string]string{
if w.Code != http.StatusNoContent { "TUS-Resumable": "1.0.0",
t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) },
} Code: http.StatusNoContent,
ResHeader: map[string]string{
"Offset": "11",
"Entity-Length": "44",
},
}).Run(handler, t)
headers := map[string]string{ (&httpTest{
"Offset": "11", Name: "Non-existing file",
"Entity-Length": "44", Method: "HEAD",
} URL: "no",
for header, value := range headers { ReqHeader: map[string]string{
if v := w.HeaderMap.Get(header); value != v { "TUS-Resumable": "1.0.0",
t.Errorf("Unexpected header value '%s': %v", header, v) },
} Code: http.StatusNotFound,
} }).Run(handler, t)
// 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)
}
} }

View File

@ -2,7 +2,6 @@ package tusd
import ( import (
"net/http" "net/http"
"net/http/httptest"
"testing" "testing"
) )
@ -11,32 +10,24 @@ func TestOptions(t *testing.T) {
MaxSize: 400, MaxSize: 400,
}) })
// Test successful OPTIONS request (&httpTest{
req, _ := http.NewRequest("OPTIONS", "", nil) Name: "Successful request",
w := httptest.NewRecorder() Method: "OPTIONS",
handler.ServeHTTP(w, req) Code: http.StatusNoContent,
if w.Code != http.StatusNoContent { ResHeader: map[string]string{
t.Errorf("Expected 204 No Content for OPTIONS request (got %v)", w.Code) "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{ (&httpTest{
"TUS-Extension": "file-creation,metadata,concatenation", Name: "Invalid or unsupported version",
"TUS-Version": "1.0.0", Method: "POST",
"TUS-Resumable": "1.0.0", ReqHeader: map[string]string{
"TUS-Max-Size": "400", "TUS-Resumable": "foo",
} },
for header, value := range headers { Code: http.StatusPreconditionFailed,
if v := w.HeaderMap.Get(header); value != v { }).Run(handler, t)
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)
}
} }

View File

@ -4,7 +4,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest"
"os" "os"
"strings" "strings"
"testing" "testing"
@ -57,45 +56,51 @@ func TestPatch(t *testing.T) {
}, },
}) })
// Test successful request (&httpTest{
req, _ := http.NewRequest("PATCH", "yes", strings.NewReader("hello")) Name: "Successful request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "PATCH",
req.Header.Set("Offset", "5") URL: "yes",
w := httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusNoContent { "Offset": "5",
t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) },
} ReqBody: strings.NewReader("hello"),
Code: http.StatusNoContent,
}).Run(handler, t)
// Test non-existing file (&httpTest{
req, _ = http.NewRequest("PATCH", "no", nil) Name: "Non-existing file",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "PATCH",
req.Header.Set("Offset", "0") URL: "no",
w = httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusNotFound { "Offset": "5",
t.Errorf("Expected %v (got %v)", http.StatusNotFound, w.Code) },
} Code: http.StatusNotFound,
}).Run(handler, t)
// Test wrong offset (&httpTest{
req, _ = http.NewRequest("PATCH", "yes", nil) Name: "Wrong offset",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "PATCH",
req.Header.Set("Offset", "4") URL: "yes",
w = httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusConflict { "Offset": "4",
t.Errorf("Expected %v (got %v)", http.StatusConflict, w.Code) },
} Code: http.StatusConflict,
}).Run(handler, t)
// Test exceeding file size (&httpTest{
req, _ = http.NewRequest("PATCH", "yes", strings.NewReader("hellothisismorethan15bytes")) Name: "Exceeding file size",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "PATCH",
req.Header.Set("Offset", "5") URL: "yes",
w = httptest.NewRecorder() ReqHeader: map[string]string{
handler.ServeHTTP(w, req) "TUS-Resumable": "1.0.0",
if w.Code != http.StatusRequestEntityTooLarge { "Offset": "5",
t.Errorf("Expected %v (got %v)", http.StatusRequestEntityTooLarge, w.Code) },
} ReqBody: strings.NewReader("hellothisismorethan15bytes"),
Code: http.StatusRequestEntityTooLarge,
}).Run(handler, t)
} }
type overflowPatchStore struct { type overflowPatchStore struct {
@ -180,14 +185,16 @@ func TestPatchOverflow(t *testing.T) {
body.Close() body.Close()
}() }()
// Test too big body exceeding file size (&httpTest{
req, _ := http.NewRequest("PATCH", "yes", body) Name: "Too big body exceeding file size",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "PATCH",
req.Header.Set("Offset", "5") URL: "yes",
req.Header.Set("Content-Length", "3") ReqHeader: map[string]string{
w := httptest.NewRecorder() "TUS-Resumable": "1.0.0",
handler.ServeHTTP(w, req) "Offset": "5",
if w.Code != http.StatusNoContent { "Content-Length": "3",
t.Errorf("Expected %v (got %v)", http.StatusNoContent, w.Code) },
} ReqBody: body,
Code: http.StatusNoContent,
}).Run(handler, t)
} }

View File

@ -2,7 +2,6 @@ package tusd
import ( import (
"net/http" "net/http"
"net/http/httptest"
"testing" "testing"
) )
@ -41,29 +40,28 @@ func TestPost(t *testing.T) {
}, },
}) })
// Test successful request (&httpTest{
req, _ := http.NewRequest("POST", "", nil) Name: "Successful request",
req.Header.Set("TUS-Resumable", "1.0.0") Method: "POST",
req.Header.Set("Entity-Length", "300") ReqHeader: map[string]string{
req.Header.Set("Metadata", "foo aGVsbG8=, bar d29ybGQ=") "TUS-Resumable": "1.0.0",
req.Host = "tus.io" "Entity-Length": "300",
w := httptest.NewRecorder() "Metadata": "foo aGVsbG8=, bar d29ybGQ=",
handler.ServeHTTP(w, req) },
if w.Code != http.StatusCreated { Code: http.StatusCreated,
t.Errorf("Expected 201 Created for OPTIONS request (got %v)", w.Code) 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" { (&httpTest{
t.Errorf("Unexpected location header (got '%v')", location) Name: "Exceeding MaxSize",
} Method: "POST",
ReqHeader: map[string]string{
// Test exceeding MaxSize "TUS-Resumable": "1.0.0",
req, _ = http.NewRequest("POST", "", nil) "Entity-Length": "500",
req.Header.Set("TUS-Resumable", "1.0.0") "Metadata": "foo aGVsbG8=, bar d29ybGQ=",
req.Header.Set("Entity-Length", "500") },
w = httptest.NewRecorder() Code: http.StatusRequestEntityTooLarge,
handler.ServeHTTP(w, req) }).Run(handler, t)
if w.Code != http.StatusRequestEntityTooLarge {
t.Errorf("Expected %v for OPTIONS request (got %v)", http.StatusRequestEntityTooLarge, w.Code)
}
} }