dndex/view/who_test.go

300 lines
8.2 KiB
Go

package view
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"local/dndex/config"
"local/dndex/storage"
"local/dndex/storage/entity"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
"time"
"github.com/google/uuid"
)
func TestWho(t *testing.T) {
os.Args = os.Args[:1]
if _, ok := os.LookupEnv("DBURI"); !ok {
f, err := ioutil.TempFile(os.TempDir(), "pattern*")
if err != nil {
t.Fatal(err)
}
f.Close()
defer os.Remove(f.Name())
os.Setenv("DBURI", f.Name())
}
t.Logf("config: %+v", config.New())
g := storage.NewGraph()
ones := fillDB(t, g)
want := ones[len(ones)-1]
handler := jsonHandler(g)
t.Log(handler, want)
t.Run("get no namespace is 404", func(t *testing.T) {
iwant := want
r := httptest.NewRequest(http.MethodGet, "/who?id="+iwant.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusNotFound {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("get fake", func(t *testing.T) {
iwant := want
r := httptest.NewRequest(http.MethodGet, "/who/col?id=FAKER"+iwant.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusNotFound {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("get real", func(t *testing.T) {
iwant := want
r := httptest.NewRequest(http.MethodGet, "/who/col?id="+iwant.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
o := entity.One{}
if err := json.Unmarshal(w.Body.Bytes(), &o); err != nil {
t.Fatal(err)
}
if fmt.Sprint(o) == fmt.Sprint(iwant) {
t.Fatal(o, iwant)
}
if len(o.Connections) != len(iwant.Connections) {
t.Fatal(len(o.Connections), len(iwant.Connections))
}
iwant.Connections = o.Connections
iwant.Modified = 0
o.Modified = 0
if fmt.Sprint(o) != fmt.Sprint(iwant) {
t.Fatalf("after resolving connections and modified, iwant and got differ: \nwant %+v\n got %+v", iwant, o)
}
b, _ := json.MarshalIndent(o, "", " ")
t.Logf("POST GET:\n%s", b)
})
t.Run("put fake", func(t *testing.T) {
iwant := want
r := httptest.NewRequest(http.MethodPut, "/who/col?id=FAKER"+iwant.Name, strings.NewReader(`{"title":"this should fail to find someone"}`))
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusNotFound {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("put real", func(t *testing.T) {
iwant := want
r := httptest.NewRequest(http.MethodPut, "/who/col?id="+iwant.Name, strings.NewReader(`{"title":"this should work"}`))
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
o := entity.One{}
if err := json.Unmarshal(w.Body.Bytes(), &o); err != nil {
t.Fatal(err)
}
if len(o.Connections) != len(iwant.Connections) {
t.Fatalf("wrong number of connections returned: want %v, got %v", len(iwant.Connections), len(o.Connections))
}
if o.Title != "this should work" {
t.Fatalf("failed to PUT a new title: %+v", o)
}
b, _ := json.MarshalIndent(o, "", " ")
t.Logf("POST PUT:\n%s", b)
})
t.Run("post exists", func(t *testing.T) {
iwant := want
iwant.Name = ""
r := httptest.NewRequest(http.MethodPost, "/who/col?id="+want.Name, strings.NewReader(`{"title":"this should fail to insert"}`))
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusConflict {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("post real", func(t *testing.T) {
iwant := want
iwant.Name = ""
b, err := json.Marshal(iwant)
if err != nil {
t.Fatal(err)
}
r := httptest.NewRequest(http.MethodPost, "/who/col?id=NEWBIE"+want.Name, bytes.NewReader(b))
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
o := entity.One{}
if err := json.Unmarshal(w.Body.Bytes(), &o); err != nil {
t.Fatal(err)
}
if len(o.Connections) != len(iwant.Connections) {
t.Fatalf("wrong number of connections returned: want %v, got %v", len(iwant.Connections), len(o.Connections))
}
if o.Name != "NEWBIE"+want.Name {
t.Fatalf("failed to POST specified name: %+v", o)
}
b, _ = json.MarshalIndent(o, "", " ")
t.Logf("POST POST:\n%s", b)
})
t.Run("delete real", func(t *testing.T) {
r := httptest.NewRequest(http.MethodDelete, "/who/col?id=NEWBIE"+want.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
r = httptest.NewRequest(http.MethodGet, "/who/col?id=NEWBIE"+want.Name, nil)
w = httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusNotFound {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("delete fake", func(t *testing.T) {
r := httptest.NewRequest(http.MethodDelete, "/who/col?id=FAKER"+want.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("patch fake", func(t *testing.T) {
r := httptest.NewRequest(http.MethodPatch, "/who/col?id=FAKER"+want.Name, nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code == http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
want = ones[2]
t.Run("patch real", func(t *testing.T) {
iwant := want
iwant.Relationship = "spawn"
iwant.Name = "child of " + want.Name
b, err := json.Marshal(iwant)
if err != nil {
t.Fatal(err)
}
r := httptest.NewRequest(http.MethodPatch, "/who/col?id="+want.Name, bytes.NewReader(b))
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
got := entity.One{}
if err := json.NewDecoder(w.Body).Decode(&got); err != nil {
t.Fatal(err)
}
if fmt.Sprint(got) == fmt.Sprint(entity.One{}) {
t.Fatal(got)
}
iwant = want
if len(got.Connections) != len(want.Connections)+1 {
t.Fatal(len(got.Connections), len(want.Connections)+1)
}
got.Connections = want.Connections
got.Modified = 0
want.Modified = 0
if fmt.Sprint(got) != fmt.Sprint(want) {
t.Fatalf("withotu connections and modified, got != want: want \n %+v, got \n %+v", want, got)
}
t.Logf("%s", w.Body.Bytes())
})
t.Run("trace fake", func(t *testing.T) {
r := httptest.NewRequest(http.MethodTrace, "/who/notcol", nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
})
t.Run("trace real", func(t *testing.T) {
r := httptest.NewRequest(http.MethodTrace, "/who/col", nil)
w := httptest.NewRecorder()
handler.ServeHTTP(w, r)
if w.Code != http.StatusOK {
t.Fatalf("%d: %s", w.Code, w.Body.Bytes())
}
var v []string
if err := json.Unmarshal(w.Body.Bytes(), &v); err != nil {
t.Fatalf("%v: %s", err, w.Body.Bytes())
}
if len(v) < 5 {
t.Fatal(len(v))
}
t.Logf("%+v", v)
})
}
func fillDB(t *testing.T, g storage.Graph) []entity.One {
ones := make([]entity.One, 5)
for i := range ones {
ones[i] = randomOne()
if i > 0 {
ones[i].Connections[ones[i-1].Name] = entity.One{
Name: ones[i-1].Name,
Relationship: ":D",
}
}
}
for i := range ones {
if err := g.Insert(context.TODO(), "col", ones[i]); err != nil {
t.Fatal(err)
}
if results, err := g.List(context.TODO(), "col", ones[i].Name); err != nil {
t.Fatal(err)
} else if len(results) != 1 {
t.Fatal(len(results))
} else if len(results[0].Connections) != len(ones[i].Connections) {
t.Fatal(len(results[0].Connections), len(ones[i].Connections))
} else if len(results[0].Connections) > 0 {
for k, v := range results[0].Connections {
if k == "" || v.Name == "" {
t.Fatalf("name is gone: %q:%+v", k, v)
}
}
}
}
return ones
}
func randomOne() entity.One {
return entity.One{
Name: "name-" + uuid.New().String()[:5],
Type: "type-" + uuid.New().String()[:5],
Title: "titl-" + uuid.New().String()[:5],
Image: "imge-" + uuid.New().String()[:5],
Text: "text-" + uuid.New().String()[:5],
Modified: time.Now().UnixNano(),
Connections: map[string]entity.One{},
}
}