package server import ( "context" "fmt" "io/ioutil" "local/dndex/config" "local/dndex/server/auth" "local/dndex/storage" "local/dndex/storage/entity" "net/http" "net/http/httptest" "os" "path" "strings" "testing" "time" "github.com/google/uuid" ) var ( testNamespace = "col-" + uuid.New().String()[:10] testEntityName = "ent-name-" + uuid.New().String()[:10] testEntityID = "ent-id-" + uuid.New().String()[:10] testFilename = "filename-" + uuid.New().String()[:10] testContent = "content-" + uuid.New().String()[:10] ) func TestRESTRouter(t *testing.T) { _, _, clean := testREST(t) clean() cases := map[string]struct { method string is404 bool }{ fmt.Sprintf(`%s`, config.New().FilePrefix): { method: http.MethodGet, is404: true, }, fmt.Sprintf(`%s/`, config.New().FilePrefix): { method: http.MethodGet, is404: true, }, fmt.Sprintf(`%s/%s?g`, config.New().FilePrefix, testFilename): { method: http.MethodGet, }, fmt.Sprintf(`%s/%s?pu`, config.New().FilePrefix, testFilename): { method: http.MethodPut, }, fmt.Sprintf(`%s?po`, config.New().FilePrefix): { method: http.MethodPost, }, fmt.Sprintf(`%s/%s?d`, config.New().FilePrefix, testFilename): { method: http.MethodDelete, }, fmt.Sprintf(`%s/fake.fake`, config.New().FilePrefix): { method: http.MethodGet, is404: true, }, fmt.Sprintf("/users/%s", testNamespace): { method: http.MethodGet, is404: true, }, "/users/register": { method: http.MethodPost, }, "/users/login": { method: http.MethodPost, }, "/users/": { method: http.MethodPost, is404: true, }, "/users": { method: http.MethodPost, is404: true, }, "/users?": { method: http.MethodPost, is404: true, }, "/entities": { method: http.MethodGet, }, "/entities/": { method: http.MethodGet, }, fmt.Sprintf("/entities/fake-%s", testEntityID): { method: http.MethodGet, is404: true, }, fmt.Sprintf("/entities/%s", testEntityID): { method: http.MethodGet, }, fmt.Sprintf("/entities/%s", testEntityID): { method: http.MethodPatch, }, fmt.Sprintf("/entities/%s", testEntityID): { method: http.MethodPost, }, fmt.Sprintf("/entities/%s", testEntityID): { method: http.MethodPut, }, fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): { method: http.MethodPatch, }, fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): { method: http.MethodPut, }, fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): { method: http.MethodPost, is404: true, }, fmt.Sprintf("/entities/%s/connections/", testEntityID): { method: http.MethodPost, }, fmt.Sprintf("/entities/%s/connections/", testEntityID): { method: http.MethodPut, }, fmt.Sprintf("/entities/%s/connections/", testEntityID): { method: http.MethodPatch, }, fmt.Sprintf("/entities/%s/connections", testEntityID): { method: http.MethodPost, }, fmt.Sprintf("/entities/%s/connections", testEntityID): { method: http.MethodPut, }, fmt.Sprintf("/entities/%s/connections", testEntityID): { method: http.MethodPatch, }, "/version": { method: http.MethodGet, }, fmt.Sprintf("/entities/%s/connections/uuid/", testEntityID): { method: http.MethodDelete, }, fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): { method: http.MethodDelete, }, fmt.Sprintf("/entities/%s/connections/?d", testEntityID): { method: http.MethodDelete, }, fmt.Sprintf("/entities/%s/connections?d", testEntityID): { method: http.MethodDelete, }, fmt.Sprintf("/entities/%s/?d", testEntityID): { method: http.MethodDelete, }, fmt.Sprintf("/entities/%s?d", testEntityID): { method: http.MethodDelete, }, "/entities/?d": { method: http.MethodDelete, is404: true, }, "/entities?d": { method: http.MethodDelete, is404: true, }, } for name, d := range cases { c := d path := name rest, setAuth, clean := testREST(t) defer clean() r := httptest.NewRequest(c.method, path, strings.NewReader(``)) setAuth(r) w := httptest.NewRecorder() rest.router.ServeHTTP(w, r) if (w.Code == http.StatusNotFound) != c.is404 { t.Errorf("%s: want 404==%v, got %d: %+v: %s", name, c.is404, w.Code, c, w.Body.Bytes()) } } } func testREST(t *testing.T) (*REST, func(r *http.Request), func()) { d, err := ioutil.TempDir(os.TempDir(), "tempdir.*") if err != nil { t.Fatal(err) } os.MkdirAll(path.Join(d, testNamespace), os.ModePerm) if err := ioutil.WriteFile(path.Join(d, testNamespace, testFilename), []byte(testContent), os.ModePerm); err != nil { t.Fatal(err) } os.Setenv("FILEROOT", d) os.Setenv("DRIVER_TYPE", "map") os.Setenv("AUTH", "true") os.Args = os.Args[:1] config.New() rest, err := NewREST(storage.NewRateLimitedGraph("")) if err != nil { t.Fatal(err) } ctx, can := context.WithTimeout(context.Background(), time.Second*5) defer can() one := randomOne() one.Name = testEntityName one.ID = testEntityID if err := rest.g.Insert(ctx, testNamespace, one); err != nil { t.Fatal(err) } register := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(fmt.Sprintf("%s=%s&%s=%s", auth.UserKey, testNamespace, auth.AuthKey, "password"))) register.Header.Set("Content-Type", "application/x-www-form-urlencoded") if err := auth.Register(rest.g, register); err != nil { t.Fatal(err) } login := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(auth.UserKey+"="+testNamespace)) login.Header.Set("Content-Type", "application/x-www-form-urlencoded") token, err := auth.GeneratePlain(rest.g, login) if err != nil { t.Fatal(err) } return rest, func(r *http.Request) { r.AddCookie(&http.Cookie{Name: auth.AuthKey, Value: token}) }, func() { os.RemoveAll(d) } } func randomOne() entity.One { return entity.One{ ID: "iddd-" + uuid.New().String()[:5], Name: "name-" + uuid.New().String()[:5], Type: "type-" + uuid.New().String()[:5], Title: "titl-" + uuid.New().String()[:5], Text: "text-" + uuid.New().String()[:5], Modified: time.Now().UnixNano(), Connections: map[string]entity.Connection{}, Attachments: map[string]entity.Attachment{ uuid.New().String()[:5]: entity.Attachment{Location: uuid.New().String()[:5]}, }, } }