...

Source file src/edge-infra.dev/pkg/edge/datasync/cushion/integration/couchdb_server_mock_test.go

Documentation: edge-infra.dev/pkg/edge/datasync/cushion/integration

     1  package integration
     2  
     3  import (
     4  	"encoding/json"
     5  	"io"
     6  	"net/http"
     7  	"strings"
     8  	"sync"
     9  
    10  	"edge-infra.dev/pkg/edge/api/testutils"
    11  	"edge-infra.dev/pkg/edge/api/utils"
    12  
    13  	"github.com/google/uuid"
    14  )
    15  
    16  type MockCouchDBServer struct {
    17  	sync.Mutex
    18  	*utils.MockHTTPTestServer
    19  	data map[string]bool
    20  }
    21  
    22  func NewMockCouchDBServer() *MockCouchDBServer {
    23  	testServer := utils.NewMockHTTPTestServer().AddAllowedContentType("application/json")
    24  
    25  	server := &MockCouchDBServer{
    26  		MockHTTPTestServer: testServer,
    27  		data:               make(map[string]bool),
    28  	}
    29  
    30  	return server.init()
    31  }
    32  
    33  func (c *MockCouchDBServer) init() *MockCouchDBServer {
    34  	c.Head("Ping", "/_up", c.emptyOk, nil)
    35  
    36  	c.AddNotFound(func(w http.ResponseWriter, r *http.Request) {
    37  		c.Lock()
    38  		defer c.Unlock()
    39  		log.Info("Not Found, request not mocked",
    40  			"Method", r.Method,
    41  			"URL", r.URL,
    42  			"Header", r.Header,
    43  		)
    44  		w.WriteHeader(404)
    45  		_, _ = w.Write([]byte(nil))
    46  	})
    47  
    48  	c.Post("Session", "/_session", func(w http.ResponseWriter, _ *http.Request) {
    49  		c.Lock()
    50  		defer c.Unlock()
    51  		data := map[string]interface{}{
    52  			"ok": true,
    53  			"userCtx": map[string]interface{}{
    54  				"name":  cushionNS,
    55  				"roles": []string{"_admin"},
    56  			},
    57  		}
    58  		c.ok(w, data)
    59  	}, nil)
    60  	return c
    61  }
    62  
    63  func (c *MockCouchDBServer) MockDB(db string) {
    64  	c.Head("Database Exists", "/"+db, func(w http.ResponseWriter, _ *http.Request) {
    65  		c.Lock()
    66  		defer c.Unlock()
    67  		if _, ok := c.data[db]; !ok {
    68  			w.WriteHeader(404)
    69  			_, _ = w.Write([]byte(nil))
    70  			return
    71  		}
    72  		log.Info("db found", "db", db)
    73  		c.ok(w, struct{}{})
    74  	}, nil)
    75  
    76  	c.Put("Create Database", "/"+db, func(w http.ResponseWriter, _ *http.Request) {
    77  		c.Lock()
    78  		defer c.Unlock()
    79  		if _, ok := c.data[db]; !ok {
    80  			c.data[db] = true
    81  		}
    82  		c.ok(w, struct{}{})
    83  	}, nil)
    84  
    85  	c.Post("Post Bulk Docs", "/"+db+"/_bulk_docs", func(w http.ResponseWriter, r *http.Request) {
    86  		c.Lock()
    87  		defer c.Unlock()
    88  
    89  		if _, ok := c.data[db]; !ok {
    90  			w.WriteHeader(404)
    91  			_, _ = w.Write([]byte(nil))
    92  			return
    93  		}
    94  
    95  		data := map[string][]map[string]interface{}{}
    96  		body, _ := io.ReadAll(r.Body)
    97  		log.Info("Request HEADERS _bulk_docs", "Header", r.Header)
    98  		log.Info("Request Body _bulk_docs", "body", string(body))
    99  		err := json.Unmarshal(body, &data)
   100  		if err != nil {
   101  			log.Error(err, "fail to post _bulk_docs")
   102  			testutils.WriteHTTPBadResponse(w)
   103  			return
   104  		}
   105  
   106  		newDocs := data["docs"]
   107  		var res []map[string]interface{}
   108  		for _, doc := range newDocs {
   109  			id := doc["_id"].(string)
   110  			rev := "1-" + strings.ReplaceAll(uuid.NewString(), "-", "")
   111  			doc["_rev"] = rev
   112  			res = append(res, map[string]interface{}{
   113  				"ok":  true,
   114  				"id":  id,
   115  				"rev": rev,
   116  			})
   117  			c.Get("Get Document "+id, "/"+db+"/"+id, func(w http.ResponseWriter, _ *http.Request) {
   118  				c.Lock()
   119  				defer c.Unlock()
   120  				log.Info("doc found", "db", db)
   121  				c.ok(w, doc)
   122  			}, nil)
   123  		}
   124  		c.ok(w, res)
   125  	}, nil)
   126  
   127  	// replication doc
   128  	if strings.HasPrefix(db, "repl-") {
   129  		c.Put("Create Database", "/"+db+"/repl_doc", func(w http.ResponseWriter, r *http.Request) {
   130  			c.Lock()
   131  			defer c.Unlock()
   132  			if _, ok := c.data[db]; !ok {
   133  				c.data[db] = true
   134  			}
   135  
   136  			data := map[string]interface{}{}
   137  			body, _ := io.ReadAll(r.Body)
   138  			err := json.Unmarshal(body, &data)
   139  			if err != nil {
   140  				log.Error(err, "fail to post _bulk_docs")
   141  				testutils.WriteHTTPBadResponse(w)
   142  				return
   143  			}
   144  
   145  			c.Get("Get Replication Document", "/"+db+"/repl_doc", func(w http.ResponseWriter, _ *http.Request) {
   146  				c.Lock()
   147  				defer c.Unlock()
   148  				log.Info("doc found", "db", db)
   149  				c.ok(w, data)
   150  			}, nil)
   151  
   152  			c.ok(w, map[string]interface{}{
   153  				"ok": true,
   154  			})
   155  		}, nil)
   156  	}
   157  }
   158  
   159  func (c *MockCouchDBServer) emptyOk(w http.ResponseWriter, _ *http.Request) {
   160  	c.Lock()
   161  	defer c.Unlock()
   162  	c.ok(w, struct{}{})
   163  }
   164  
   165  func (c *MockCouchDBServer) ok(w http.ResponseWriter, data interface{}) {
   166  	res, err := json.Marshal(data)
   167  	if err != nil {
   168  		testutils.WriteHTTPBadResponse(w)
   169  		return
   170  	}
   171  	w.Header().Set("Content-Type", "application/json")
   172  	_, _ = w.Write(res)
   173  }
   174  

View as plain text