123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- package megauploader
- import (
- "bytes"
- "encoding/json"
- "flag"
- "fmt"
- "io/ioutil"
- "mime/multipart"
- "net/http"
- "net/http/httptest"
- "os"
- "strconv"
- "strings"
- "testing"
- "github.com/Flaque/filet"
- "github.com/headzoo/surf"
- )
- var (
- doHTTP = flag.Bool("http-tests", false, "run HTTP integration tests")
- )
- func TestMain(m *testing.M) {
- flag.Parse()
- result := m.Run()
- os.Exit(result)
- }
- func getServer(cfg string) *httptest.Server {
- conf, err := ParseConf([]byte(cfg))
- if err != nil {
- panic("Error parsing conf in getServer")
- }
- mu := NewMegaUploader(conf)
- ts := httptest.NewServer(mu.SetupRoutes())
- return ts
- }
- // ask home page without authentication; 401 expected
- func TestAuthDeny(t *testing.T) {
- if !*doHTTP {
- return
- }
- ts := getServer(``)
- defer ts.Close()
- resp, err := ts.Client().Get(ts.URL)
- if err != nil {
- t.Fatalf("Error asking home to test server")
- return
- }
- if resp.StatusCode != 401 {
- t.Errorf("Viewing home should require authentication; got `%s` instead",
- resp.Status,
- )
- }
- }
- // ask for non-existing page without authentication; 404 expected
- func TestNotFoundWhenUnauthenticated(t *testing.T) {
- if !*doHTTP {
- return
- }
- ts := getServer(``)
- defer ts.Close()
- resp, err := ts.Client().Get(ts.URL + "/dontexist")
- if err != nil {
- t.Fatalf("Error asking non-existent URL to test server: \n%s\n", err)
- return
- }
- if resp.StatusCode != 404 {
- t.Errorf("Asked not existing endpoint, expected 404; got `%s` instead",
- resp.Status,
- )
- }
- }
- func userRequest(url, user string, t *testing.T) *http.Request {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- t.Fatalf("error preparing request: \n%s\n", err)
- return nil
- }
- req.Header.Add("X-Forwarded-User", user)
- return req
- }
- // ask for home with valid user
- func TestAuthOk(t *testing.T) {
- if !*doHTTP {
- return
- }
- ts := getServer(``)
- defer ts.Close()
- cl := ts.Client()
- req := userRequest(ts.URL, "someone", t)
- resp, err := cl.Do(req)
- if err != nil {
- t.Fatalf("Error asking home to test server")
- return
- }
- if resp.StatusCode != 200 {
- t.Errorf("Viewing home should require authentication; got `%s` instead",
- resp.Status,
- )
- }
- }
- func getShareList(ts *httptest.Server, user string, t *testing.T) []Share {
- req := userRequest(ts.URL+"/api/share", user, t)
- cl := ts.Client()
- resp, err := cl.Do(req)
- if err != nil {
- t.Fatalf("Error asking share list to test server: \n%s\n", err)
- return []Share{}
- }
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatal("Error reading response", err)
- return []Share{}
- }
- var shares []Share
- err = json.Unmarshal(body, &shares)
- if err != nil {
- t.Fatal("Invalid JSON received", err)
- return []Share{}
- }
- return shares
- }
- // share list with invalid user
- func TestShareRejected(t *testing.T) {
- if !*doHTTP {
- return
- }
- ts := getServer(`
- global:
- excluded:
- - john@doe.us
- - foo bar
- shares:
- - name: foo
- authorized: ["*"]
- description: foo
- `)
- defer ts.Close()
- shares := getShareList(ts, "john@doe.us", t)
- if len(shares) != 0 {
- t.Fatal("Asked share list with banned user, expected empty, got", shares)
- return
- }
- }
- // share list with valid user
- func TestShareOk(t *testing.T) {
- if !*doHTTP {
- return
- }
- ts := getServer(`
- global:
- excluded:
- - john@doe.us
- - foo bar
- shares:
- - name: foo
- authorized: ["*"]
- description: foo
- `)
- defer ts.Close()
- shares := getShareList(ts, "someone elese", t)
- if len(shares) == 0 {
- t.Fatal("Asked share list with not banned user, expected [foo], got", shares)
- return
- }
- if shares[0].Name != "foo" {
- t.Error("The only share should be `foo`, got", shares[0].Name)
- return
- }
- }
- func TestUpload(t *testing.T) {
- if !*doHTTP {
- return
- }
- defer filet.CleanUp(t)
- d := filet.TmpDir(t, "")
- conf := `
- shares:
- - name: foo
- dir: DIR
- authorized: ["*"]
- description: foo
- `
- conf = strings.Replace(conf, "DIR", d, 1)
- ts := getServer(conf)
- cl := ts.Client()
- bodyBuf := bytes.Buffer{}
- bodyWriter := multipart.NewWriter(&bodyBuf)
- fileWriter, err := bodyWriter.CreateFormFile("file", "foo.txt")
- if err != nil {
- t.Fatal("error creating form file", err)
- return
- }
- _, err = fileWriter.Write([]byte(`example content`))
- if err != nil {
- t.Fatal("error writing on form file", err)
- return
- }
- contentType := bodyWriter.FormDataContentType()
- bodyWriter.Close()
- req := userRequest(ts.URL+"/api/upload/foo", "someone", t)
- req.Method = "POST"
- req.Header.Set("Content-Type", contentType)
- req.ContentLength = int64(bodyBuf.Len())
- req.Body = ioutil.NopCloser(&bodyBuf)
- resp, err := cl.Do(req)
- if err != nil {
- t.Fatal("Error POSTing file", err)
- return
- }
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatal("Error reading server response", err)
- return
- }
- if resp.StatusCode < 200 || resp.StatusCode > 299 {
- t.Error("Server status is not success:", resp.Status, respBody)
- }
- fname := d + "/" + string(respBody)
- if !filet.Exists(t, fname) {
- t.Error("File does not exist", fname)
- } else if !filet.FileSays(t, fname, []byte("example content")) {
- t.Error("File exists but has wrong content")
- }
- }
- func TestUploadBig(t *testing.T) {
- if !*doHTTP {
- return
- }
- limit := 21
- if testing.Short() {
- limit = 2
- }
- // test with 1,5,9,13,17,21MB
- for i := 1; i < limit; i += 4 {
- t.Run(fmt.Sprintf("S=%d", i), testUploadBig)
- }
- }
- func testUploadBig(t *testing.T) {
- size, err := strconv.Atoi(strings.SplitN(t.Name(), "=", 2)[1])
- if err != nil {
- t.Fatalf("Cannot convert size %s to int: %s", t.Name(), err)
- return
- }
- size *= 1024 * 1024
- defer filet.CleanUp(t)
- d := filet.TmpDir(t, "")
- conf := `
- shares:
- - name: foo
- dir: DIR
- authorized: ["*"]
- description: foo
- `
- conf = strings.Replace(conf, "DIR", d, 1)
- ts := getServer(conf)
- cl := ts.Client()
- bodyBuf := bytes.Buffer{}
- bodyWriter := multipart.NewWriter(&bodyBuf)
- fileWriter, err := bodyWriter.CreateFormFile("file", "foo.txt")
- if err != nil {
- t.Fatal("error creating form file", err)
- return
- }
- // write 3MB made of 'a'
- for i := 0; i < size; i++ {
- _, err = fileWriter.Write([]byte(`a`))
- if err != nil {
- t.Fatal("error writing on form file", err)
- return
- }
- }
- contentType := bodyWriter.FormDataContentType()
- bodyWriter.Close()
- req := userRequest(ts.URL+"/api/upload/foo", "someone", t)
- req.Method = "POST"
- req.Header.Set("Content-Type", contentType)
- req.ContentLength = int64(bodyBuf.Len())
- req.Body = ioutil.NopCloser(&bodyBuf)
- resp, err := cl.Do(req)
- if err != nil {
- t.Fatal("Error POSTing file", err)
- return
- }
- defer resp.Body.Close()
- respBody, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatal("Error reading server response", err)
- return
- }
- if resp.StatusCode < 200 || resp.StatusCode > 299 {
- t.Error("Server status is not success:", resp.Status, respBody)
- }
- fname := d + "/" + string(respBody)
- if !filet.Exists(t, fname) {
- t.Error("File does not exist", fname)
- } else {
- info, err := os.Stat(fname)
- if err != nil {
- t.Fatal("error reading info on uploaded file", err)
- return
- }
- if info.Size() != int64(size) {
- t.Errorf("File exists but has wrong size: expected %d, found %d", size, info.Size())
- }
- }
- }
- func TestUploadTooBig(t *testing.T) {
- size := 900*1024 + 1
- defer filet.CleanUp(t)
- d := filet.TmpDir(t, "")
- conf := `
- shares:
- - name: foo
- dir: DIR
- sizelimit: 900K
- authorized: ["*"]
- description: foo
- `
- conf = strings.Replace(conf, "DIR", d, 1)
- ts := getServer(conf)
- cl := ts.Client()
- bodyBuf := bytes.Buffer{}
- bodyWriter := multipart.NewWriter(&bodyBuf)
- fileWriter, err := bodyWriter.CreateFormFile("file", "foo.txt")
- if err != nil {
- t.Fatal("error creating form file", err)
- return
- }
- // write 3MB made of 'a'
- for i := 0; i < size; i++ {
- _, err = fileWriter.Write([]byte(`a`))
- if err != nil {
- t.Fatal("error writing on form file", err)
- return
- }
- }
- contentType := bodyWriter.FormDataContentType()
- bodyWriter.Close()
- req := userRequest(ts.URL+"/api/upload/foo", "someone", t)
- req.Method = "POST"
- req.Header.Set("Content-Type", contentType)
- req.ContentLength = int64(bodyBuf.Len())
- req.Body = ioutil.NopCloser(&bodyBuf)
- resp, err := cl.Do(req)
- if err != nil {
- t.Fatal("Error POSTing file", err)
- return
- }
- defer resp.Body.Close()
- _, err = ioutil.ReadAll(resp.Body)
- if err != nil {
- t.Fatal("Error reading server response", err)
- return
- }
- if resp.StatusCode < 299 {
- t.Error("Upload succeeded despite high size", resp.Status)
- }
- files, err := ioutil.ReadDir(d)
- if err != nil {
- t.Fatal("Error checking if upload dir is empty", err)
- }
- if len(files) != 0 {
- t.Error("Upload dir not empty; should be refused!", len(files))
- t.Log(files[0])
- }
- }
- func TestSurfUpload(t *testing.T) {
- if !*doHTTP {
- return
- }
- defer filet.CleanUp(t)
- d := filet.TmpDir(t, "")
- conf := `
- shares:
- - name: foo
- dir: DIR
- authorized: ["*"]
- description: example
- sizelimit: 1M
- `
- conf = strings.Replace(conf, "DIR", d, 1)
- ts := getServer(conf)
- bow := surf.NewBrowser()
- bow.AddRequestHeader("X-Forwarded-User", "someone")
- var err error
- if err = bow.Open(ts.URL); err != nil {
- t.Fatal("error opening home", err)
- return
- }
- if err = bow.Click("li a"); err != nil {
- t.Fatal("error clicking on share", err)
- return
- }
- form, err := bow.Form("form")
- if err != nil {
- t.Fatal("can't find form", err)
- return
- }
- form.SetFile("file", "foo.txt", strings.NewReader("example content"))
- if err = form.Submit(); err != nil {
- t.Error("error submitting form", err)
- }
- if bow.StatusCode() > 299 {
- t.Error("Invalid status code", bow.StatusCode(), bow.Body())
- }
- fname := d + "/" + bow.Body()
- if !filet.Exists(t, fname) {
- t.Error("File does not exist", fname)
- } else if !filet.FileSays(t, fname, []byte("example content")) {
- t.Error("File exists but has wrong content")
- }
- }
|