package integration import ( "encoding/json" "io" "net/http" "strings" "sync" "edge-infra.dev/pkg/edge/api/testutils" "edge-infra.dev/pkg/edge/api/utils" "github.com/google/uuid" ) type MockCouchDBServer struct { sync.Mutex *utils.MockHTTPTestServer data map[string]bool } func NewMockCouchDBServer() *MockCouchDBServer { testServer := utils.NewMockHTTPTestServer().AddAllowedContentType("application/json") server := &MockCouchDBServer{ MockHTTPTestServer: testServer, data: make(map[string]bool), } return server.init() } func (c *MockCouchDBServer) init() *MockCouchDBServer { c.Head("Ping", "/_up", c.emptyOk, nil) c.AddNotFound(func(w http.ResponseWriter, r *http.Request) { c.Lock() defer c.Unlock() log.Info("Not Found, request not mocked", "Method", r.Method, "URL", r.URL, "Header", r.Header, ) w.WriteHeader(404) _, _ = w.Write([]byte(nil)) }) c.Post("Session", "/_session", func(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() data := map[string]interface{}{ "ok": true, "userCtx": map[string]interface{}{ "name": cushionNS, "roles": []string{"_admin"}, }, } c.ok(w, data) }, nil) return c } func (c *MockCouchDBServer) MockDB(db string) { c.Head("Database Exists", "/"+db, func(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() if _, ok := c.data[db]; !ok { w.WriteHeader(404) _, _ = w.Write([]byte(nil)) return } log.Info("db found", "db", db) c.ok(w, struct{}{}) }, nil) c.Put("Create Database", "/"+db, func(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() if _, ok := c.data[db]; !ok { c.data[db] = true } c.ok(w, struct{}{}) }, nil) c.Post("Post Bulk Docs", "/"+db+"/_bulk_docs", func(w http.ResponseWriter, r *http.Request) { c.Lock() defer c.Unlock() if _, ok := c.data[db]; !ok { w.WriteHeader(404) _, _ = w.Write([]byte(nil)) return } data := map[string][]map[string]interface{}{} body, _ := io.ReadAll(r.Body) log.Info("Request HEADERS _bulk_docs", "Header", r.Header) log.Info("Request Body _bulk_docs", "body", string(body)) err := json.Unmarshal(body, &data) if err != nil { log.Error(err, "fail to post _bulk_docs") testutils.WriteHTTPBadResponse(w) return } newDocs := data["docs"] var res []map[string]interface{} for _, doc := range newDocs { id := doc["_id"].(string) rev := "1-" + strings.ReplaceAll(uuid.NewString(), "-", "") doc["_rev"] = rev res = append(res, map[string]interface{}{ "ok": true, "id": id, "rev": rev, }) c.Get("Get Document "+id, "/"+db+"/"+id, func(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() log.Info("doc found", "db", db) c.ok(w, doc) }, nil) } c.ok(w, res) }, nil) // replication doc if strings.HasPrefix(db, "repl-") { c.Put("Create Database", "/"+db+"/repl_doc", func(w http.ResponseWriter, r *http.Request) { c.Lock() defer c.Unlock() if _, ok := c.data[db]; !ok { c.data[db] = true } data := map[string]interface{}{} body, _ := io.ReadAll(r.Body) err := json.Unmarshal(body, &data) if err != nil { log.Error(err, "fail to post _bulk_docs") testutils.WriteHTTPBadResponse(w) return } c.Get("Get Replication Document", "/"+db+"/repl_doc", func(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() log.Info("doc found", "db", db) c.ok(w, data) }, nil) c.ok(w, map[string]interface{}{ "ok": true, }) }, nil) } } func (c *MockCouchDBServer) emptyOk(w http.ResponseWriter, _ *http.Request) { c.Lock() defer c.Unlock() c.ok(w, struct{}{}) } func (c *MockCouchDBServer) ok(w http.ResponseWriter, data interface{}) { res, err := json.Marshal(data) if err != nil { testutils.WriteHTTPBadResponse(w) return } w.Header().Set("Content-Type", "application/json") _, _ = w.Write(res) }