megauploader/http_test.go

282 lines
6.2 KiB
Go

package megauploader
import (
"bytes"
"encoding/json"
"flag"
"io/ioutil"
"mime/multipart"
"net/http"
"net/http/httptest"
"os"
"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 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")
}
}