From 9640e2c7ce9f34cde602e6aaba8bdcd9de3f671f Mon Sep 17 00:00:00 2001 From: andreimarcu Date: Wed, 7 Oct 2015 03:00:03 -0400 Subject: [PATCH] Tests + fixes --- csp_test.go | 11 ++ display.go | 2 +- pages.go | 4 +- server_test.go | 434 +++++++++++++++++++++++++++++++++++++++++++------ upload.go | 1 - util.go | 33 ---- 6 files changed, 399 insertions(+), 86 deletions(-) diff --git a/csp_test.go b/csp_test.go index d2b6eee..87f5dd9 100644 --- a/csp_test.go +++ b/csp_test.go @@ -3,6 +3,8 @@ package main import ( "net/http" "net/http/httptest" + "os" + "path" "testing" "github.com/zenazn/goji" @@ -14,6 +16,15 @@ var testCSPHeaders = map[string]string{ } func TestContentSecurityPolicy(t *testing.T) { + Config.siteURL = "http://linx.example.org/" + Config.filesDir = path.Join(os.TempDir(), generateBarename()) + Config.metaDir = Config.filesDir + "_meta" + Config.noLogs = true + Config.siteName = "linx" + Config.contentSecurityPolicy = "default-src 'none'; style-src 'self';" + Config.xFrameOptions = "SAMEORIGIN" + setup() + w := httptest.NewRecorder() req, err := http.NewRequest("GET", "/", nil) diff --git a/display.go b/display.go index 6503c28..b966077 100644 --- a/display.go +++ b/display.go @@ -31,7 +31,7 @@ func fileDisplayHandler(c web.C, w http.ResponseWriter, r *http.Request) { expiry, _ := metadataGetExpiry(fileName) var expiryHuman string - if !expiry.IsZero() { + if expiry != neverExpire { expiryHuman = humanize.RelTime(time.Now(), expiry, "", "") } sizeHuman := humanize.Bytes(uint64(fileInfo.Size())) diff --git a/pages.go b/pages.go index c4676a4..ac1b7f1 100644 --- a/pages.go +++ b/pages.go @@ -47,13 +47,13 @@ func oopsHandler(c web.C, w http.ResponseWriter, r *http.Request, rt RespType, m } if rt == RespHTML { - Templates["oops.html"].ExecuteWriter(pongo2.Context{"msg": msg}, w) w.WriteHeader(500) + Templates["oops.html"].ExecuteWriter(pongo2.Context{"msg": msg}, w) return } else if rt == RespPLAIN { - fmt.Fprintf(w, "%s", msg) w.WriteHeader(500) + fmt.Fprintf(w, "%s", msg) return } else if rt == RespJSON { diff --git a/server_test.go b/server_test.go index 4fc426f..b117117 100644 --- a/server_test.go +++ b/server_test.go @@ -1,21 +1,37 @@ package main import ( + "bytes" "encoding/json" + "mime/multipart" "net/http" "net/http/httptest" + "net/url" "os" "path" "strconv" "strings" "testing" + "time" "github.com/zenazn/goji" ) +type RespOkJSON struct { + Filename string + Url string + Delete_Key string + Expiry string + Size string +} + +type RespErrJSON struct { + Error string +} + func TestSetup(t *testing.T) { Config.siteURL = "http://linx.example.org/" - Config.filesDir = path.Join(os.TempDir(), randomString(10)) + Config.filesDir = path.Join(os.TempDir(), generateBarename()) Config.metaDir = Config.filesDir + "_meta" Config.noLogs = true Config.siteName = "linx" @@ -55,7 +71,7 @@ func TestNotFound(t *testing.T) { func TestFileNotFound(t *testing.T) { w := httptest.NewRecorder() - filename := randomString(10) + filename := generateBarename() req, err := http.NewRequest("GET", "/selif/"+filename, nil) if err != nil { @@ -72,7 +88,7 @@ func TestFileNotFound(t *testing.T) { func TestDisplayNotFound(t *testing.T) { w := httptest.NewRecorder() - filename := randomString(10) + filename := generateBarename() req, err := http.NewRequest("GET", "/"+filename, nil) if err != nil { @@ -86,10 +102,346 @@ func TestDisplayNotFound(t *testing.T) { } } +func TestPostCodeUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + extension := "txt" + + form := url.Values{} + form.Add("content", "File content") + form.Add("filename", filename) + form.Add("extension", extension) + + req, err := http.NewRequest("POST", "/upload/", nil) + if err != nil { + t.Fatal(err) + } + req.PostForm = form + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 301 { + t.Fatalf("Status code is not 301, but %d", w.Code) + } + + if w.Header().Get("Location") != "/"+filename+"."+extension { + t.Fatalf("Was redirected to %s instead of /%s", w.Header().Get("Location"), filename) + } +} + +func TestPostCodeExpiryJSONUpload(t *testing.T) { + w := httptest.NewRecorder() + + form := url.Values{} + form.Add("content", "File content") + form.Add("filename", "") + form.Add("expires", "60") + + req, err := http.NewRequest("POST", "/upload/", nil) + if err != nil { + t.Fatal(err) + } + req.PostForm = form + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + req.Header.Set("Accept", "application/json") + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 200 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 200, but %d", w.Code) + } + + var myjson RespOkJSON + err = json.Unmarshal([]byte(w.Body.String()), &myjson) + if err != nil { + t.Fatal(err) + } + + myExp, err := strconv.ParseInt(myjson.Expiry, 10, 64) + if err != nil { + t.Fatal(err) + } + curTime := time.Now().Unix() + + if myExp < curTime { + t.Fatalf("File expiry (%d) is smaller than current time (%d)", myExp, curTime) + } + + if myjson.Size != "12" { + t.Fatalf("File size was not 12 but %s", myjson.Size) + } +} + +func TestPostUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + + fw.Write([]byte("File content")) + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 301 { + t.Fatalf("Status code is not 301, but %d", w.Code) + } + + if w.Header().Get("Location") != "/"+filename { + t.Fatalf("Was redirected to %s instead of /%s", w.Header().Get("Location"), filename) + } +} + +func TestPostJSONUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + + fw.Write([]byte("File content")) + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + req.Header.Set("Accept", "application/json") + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 200 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 200, but %d", w.Code) + } + + var myjson RespOkJSON + err = json.Unmarshal([]byte(w.Body.String()), &myjson) + if err != nil { + t.Fatal(err) + } + + if myjson.Filename != filename { + t.Fatalf("Filename is not '%s' but '%s' ", filename, myjson.Filename) + } + + if myjson.Expiry != "0" { + t.Fatalf("File expiry is not 0 but %s", myjson.Expiry) + } + + if myjson.Size != "12" { + t.Fatalf("File size was not 12 but %s", myjson.Size) + } +} + +func TestPostExpiresJSONUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + fw.Write([]byte("File content")) + + exp, err := mw.CreateFormField("expires") + if err != nil { + t.Fatal(err) + } + exp.Write([]byte("60")) + + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + req.Header.Set("Accept", "application/json") + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 200 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 200, but %d", w.Code) + } + + var myjson RespOkJSON + err = json.Unmarshal([]byte(w.Body.String()), &myjson) + if err != nil { + t.Fatal(err) + } + + if myjson.Filename != filename { + t.Fatalf("Filename is not '%s' but '%s' ", filename, myjson.Filename) + } + + myExp, err := strconv.ParseInt(myjson.Expiry, 10, 64) + if err != nil { + t.Fatal(err) + } + curTime := time.Now().Unix() + + if myExp < curTime { + t.Fatalf("File expiry (%d) is smaller than current time (%d)", myExp, curTime) + } + + if myjson.Size != "12" { + t.Fatalf("File size was not 12 but %s", myjson.Size) + } +} + +func TestPostRandomizeJSONUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + fw.Write([]byte("File content")) + + rnd, err := mw.CreateFormField("randomize") + if err != nil { + t.Fatal(err) + } + rnd.Write([]byte("true")) + + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + req.Header.Set("Accept", "application/json") + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 200 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 200, but %d", w.Code) + } + + var myjson RespOkJSON + err = json.Unmarshal([]byte(w.Body.String()), &myjson) + if err != nil { + t.Fatal(err) + } + + if myjson.Filename == filename { + t.Fatalf("Filename is not random", filename, myjson.Filename) + } + + if myjson.Size != "12" { + t.Fatalf("File size was not 12 but %s", myjson.Size) + } +} + +func TestPostEmptyUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + + fw.Write([]byte("")) + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 500 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 500, but %d", w.Code) + } + + if !strings.Contains(w.Body.String(), "Empty file") { + t.Fatal("Response did not contain 'Empty file'") + } +} + +func TestPostEmptyJSONUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() + ".txt" + + var b bytes.Buffer + mw := multipart.NewWriter(&b) + fw, err := mw.CreateFormFile("file", filename) + if err != nil { + t.Fatal(err) + } + + fw.Write([]byte("")) + mw.Close() + + req, err := http.NewRequest("POST", "/upload/", &b) + req.Header.Set("Content-Type", mw.FormDataContentType()) + req.Header.Set("Accept", "application/json") + if err != nil { + t.Fatal(err) + } + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Code != 500 { + t.Log(w.Body.String()) + t.Fatalf("Status code is not 500, but %d", w.Code) + } + + var myjson RespErrJSON + err = json.Unmarshal([]byte(w.Body.String()), &myjson) + if err != nil { + t.Fatal(err) + } + + if myjson.Error != "Could not upload file: Empty file" { + t.Fatal("Json 'error' was not 'Empty file' but " + myjson.Error) + } +} + func TestPutUpload(t *testing.T) { w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) if err != nil { @@ -106,7 +458,26 @@ func TestPutUpload(t *testing.T) { func TestPutRandomizedUpload(t *testing.T) { w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" + + req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) + if err != nil { + t.Fatal(err) + } + + req.Header.Set("Linx-Randomize", "yes") + + goji.DefaultMux.ServeHTTP(w, req) + + if w.Body.String() == Config.siteURL+filename { + t.Fatal("Filename was not random") + } +} + +func TestPutNoExtensionUpload(t *testing.T) { + w := httptest.NewRecorder() + + filename := generateBarename() req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) if err != nil { @@ -125,7 +496,7 @@ func TestPutRandomizedUpload(t *testing.T) { func TestPutEmptyUpload(t *testing.T) { w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("")) if err != nil { @@ -142,18 +513,11 @@ func TestPutEmptyUpload(t *testing.T) { } func TestPutJSONUpload(t *testing.T) { - type RespJSON struct { - Filename string - Url string - Delete_Key string - Expiry string - Size string - } - var myjson RespJSON + var myjson RespOkJSON w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) if err != nil { @@ -175,18 +539,11 @@ func TestPutJSONUpload(t *testing.T) { } func TestPutRandomizedJSONUpload(t *testing.T) { - type RespJSON struct { - Filename string - Url string - Delete_Key string - Expiry string - Size string - } - var myjson RespJSON + var myjson RespOkJSON w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) if err != nil { @@ -209,18 +566,11 @@ func TestPutRandomizedJSONUpload(t *testing.T) { } func TestPutExpireJSONUpload(t *testing.T) { - type RespJSON struct { - Filename string - Url string - Delete_Key string - Expiry string - Size string - } - var myjson RespJSON + var myjson RespOkJSON w := httptest.NewRecorder() - filename := randomString(10) + ".ext" + filename := generateBarename() + ".ext" req, err := http.NewRequest("PUT", "/upload/"+filename, strings.NewReader("File content")) if err != nil { @@ -247,14 +597,7 @@ func TestPutExpireJSONUpload(t *testing.T) { } func TestPutAndDelete(t *testing.T) { - type RespJSON struct { - Filename string - Url string - Delete_Key string - Expiry string - Size string - } - var myjson RespJSON + var myjson RespOkJSON w := httptest.NewRecorder() @@ -302,14 +645,7 @@ func TestPutAndDelete(t *testing.T) { } func TestPutAndSpecificDelete(t *testing.T) { - type RespJSON struct { - Filename string - Url string - Delete_Key string - Expiry string - Size string - } - var myjson RespJSON + var myjson RespOkJSON w := httptest.NewRecorder() diff --git a/upload.go b/upload.go index 06392fc..6ea9247 100644 --- a/upload.go +++ b/upload.go @@ -248,7 +248,6 @@ func processUpload(upReq UploadRequest) (upload Upload, err error) { // Get the rest of the metadata needed for storage if upReq.expiry == 0 { upload.Expiry = neverExpire - } else { upload.Expiry = time.Now().Add(upReq.expiry) } diff --git a/util.go b/util.go index 71016bd..fd463d5 100644 --- a/util.go +++ b/util.go @@ -1,38 +1,5 @@ package main -import ( - "math/rand" - "time" -) - -// from http://stackoverflow.com/a/31832326 -var src = rand.NewSource(time.Now().UnixNano()) - -const letterBytes = "abcdefghijklmnopqrstuvwxyz1234567890" -const ( - letterIdxBits = 6 // 6 bits to represent a letter index - letterIdxMask = 1<= 0; { - if remain == 0 { - cache, remain = src.Int63(), letterIdxMax - } - if idx := int(cache & letterIdxMask); idx < len(letterBytes) { - b[i] = letterBytes[idx] - i-- - } - cache >>= letterIdxBits - remain-- - } - - return string(b) -} - func extensionToHlAndAceLangs(extension string) (hlExt, aceExt string) { hlExt, exists := extensionToHl[extension] if !exists {