package server import ( "bytes" "net/http" "net/http/httptest" "strings" "testing" "github.com/google/uuid" ) func TestFiles(t *testing.T) { cases := map[string]func(*testing.T, *REST, func(*http.Request)){ "create-get": func(t *testing.T, rest *REST, scope func(r *http.Request)) { content := uuid.New().String() w := testFilesPost(t, rest, scope, content) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } s := string(w.Body.Bytes()) w = testFilesGet(t, rest, s, scope) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } if s2 := string(w.Body.Bytes()); s2 != content { t.Fatalf("want %q, got %q", content, s2) } }, "delete": func(t *testing.T, rest *REST, scope func(r *http.Request)) { w := testFilesPost(t, rest, scope, uuid.New().String()) s := string(w.Body.Bytes()) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } w = testFilesDelete(t, rest, s, scope) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } w = testFilesGet(t, rest, s, scope) if w.Code != http.StatusNotFound { t.Fatal(w.Code, string(w.Body.Bytes())) } }, "404": func(t *testing.T, rest *REST, scope func(r *http.Request)) { s := uuid.New().String() w := testFilesGet(t, rest, s, scope) if w.Code != http.StatusNotFound { t.Fatal(w.Code, string(w.Body.Bytes())) } }, "update": func(t *testing.T, rest *REST, scope func(r *http.Request)) { w := testFilesPost(t, rest, scope, uuid.New().String()) s := string(w.Body.Bytes()) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } w = testFilesPut(t, rest, s, scope, s+"new") if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } w = testFilesGet(t, rest, s, scope) if w.Code != http.StatusOK { t.Fatal(w.Code, string(w.Body.Bytes())) } if v := string(w.Body.Bytes()); v != s+"new" { t.Fatal(v) } }, } for name, foo := range cases { bar := foo t.Run(name, func(t *testing.T) { rest, scope, clean := testREST(t) bar(t, rest, scope) defer clean() }) } } func testFilesDelete(t *testing.T, rest *REST, id string, scope func(*http.Request)) *httptest.ResponseRecorder { return testFilesReq(t, rest, id, scope, http.MethodDelete, "") } func testFilesGet(t *testing.T, rest *REST, id string, scope func(*http.Request)) *httptest.ResponseRecorder { return testFilesReq(t, rest, id, scope, http.MethodGet, "") } func testFilesPut(t *testing.T, rest *REST, id string, scope func(*http.Request), body string) *httptest.ResponseRecorder { return testFilesReq(t, rest, id, scope, http.MethodPut, body) } func testFilesPost(t *testing.T, rest *REST, scope func(*http.Request), body string) *httptest.ResponseRecorder { return testFilesReq(t, rest, "", scope, http.MethodPost, body) } func testFilesReq(t *testing.T, rest *REST, id string, scope func(*http.Request), method, body string) *httptest.ResponseRecorder { r := httptest.NewRequest(method, "/"+id, strings.NewReader(body)) scope(r) w := httptest.NewRecorder() rest.files(w, r) return w } func TestFilesStream(t *testing.T) { rest, _, clean := testREST(t) defer clean() t.Run("simple upload", func(t *testing.T) { value := uuid.New().String() r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(value)) buff := bytes.NewBuffer(nil) if err := rest.filesStream(r, buff); err != nil { t.Fatal(err) } if s := string(buff.Bytes()); s != value { t.Fatal(s) } }) t.Run("direct upload", func(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(http.NotFound)) defer s.Close() r := httptest.NewRequest(http.MethodPost, "/?direct", strings.NewReader(s.URL)) buff := bytes.NewBuffer(nil) if err := rest.filesStream(r, buff); err != nil { t.Fatal(err) } w := httptest.NewRecorder() http.NotFound(w, nil) want := string(w.Body.Bytes()) got := string(buff.Bytes()) if want != got { t.Fatal(want, got) } }) }