From bd592ea92d9bc30059523648886e2fa6379b9d63 Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Sat, 17 Sep 2022 16:26:48 -0400 Subject: [PATCH 1/7] Added basic http client --- go.mod | 12 ++++++++- go.sum | 17 ++++++++++++ httpclient/client.go | 54 +++++++++++++++++++++++++++++++++++++++ httpclient/client_test.go | 16 ++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 httpclient/client.go create mode 100644 httpclient/client_test.go diff --git a/go.mod b/go.mod index 44e4fcc..293cf30 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,14 @@ module github.com/surrealdb/surrealdb.go go 1.18 -require github.com/gorilla/websocket v1.5.0 +require ( + github.com/gorilla/websocket v1.5.0 + github.com/test-go/testify v1.1.4 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index e5a03d4..16dc1a2 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,19 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/httpclient/client.go b/httpclient/client.go new file mode 100644 index 0000000..2344c63 --- /dev/null +++ b/httpclient/client.go @@ -0,0 +1,54 @@ +package httpclient + +import ( + "bytes" + "io/ioutil" + "net/http" +) + +// SurrealClient is a wrapper to more easily make HTTP calls to the SurrealDB engine +type SurrealClient struct { + // URL is the endpoint in SurrealDB to be called, needs to have /sql at the end + URL string + // DB that you want to connect to + DB string + // Namespace that you want to connect to + NS string + User string + Password string +} + +// New creates a new instance of a SurrealClient +func New(url, db, ns, user, password string) SurrealClient { + return SurrealClient{ + URL: url, + DB: db, + NS: ns, + User: user, + Password: password, + } +} + +// RunQuery executes a POST with the given query, returning the raw JSON response as a string +// TODO: marshal the response into something nicer, depending on what the community decides +func (sc SurrealClient) RunQuery(query string) (string, error) { + client := &http.Client{} + + req, err := http.NewRequest("POST", sc.URL, bytes.NewBufferString(query)) + if err != nil { + return "", err + } + req.Header.Set("NS", sc.NS) + req.Header.Set("DB", sc.DB) + req.Header.Set("Content-Type", "application/json") + req.SetBasicAuth(sc.User, sc.Password) + + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + data, err := ioutil.ReadAll(resp.Body) + return string(data), err +} diff --git a/httpclient/client_test.go b/httpclient/client_test.go new file mode 100644 index 0000000..af8a31f --- /dev/null +++ b/httpclient/client_test.go @@ -0,0 +1,16 @@ +package httpclient + +import ( + "fmt" + "testing" + + "github.com/test-go/testify/require" +) + +func Test_Nominal(t *testing.T) { + client := New("http://localhost:8000/sql", "test", "test", "root", "root") + + resp, err := client.RunQuery("INFO FOR DB;") + require.Nil(t, err) + fmt.Println(resp) +} From 2ace48b185cc162a3481cf71cfc1ef3ac351fa71 Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Sun, 18 Sep 2022 10:53:24 -0400 Subject: [PATCH 2/7] Added support for all http endpoints and a unit test for each --- go.mod | 12 ++++- go.sum | 17 +++++++ httpclient/client.go | 91 +++++++++++++++++++++++++++++++++ httpclient/client_test.go | 103 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 httpclient/client.go create mode 100644 httpclient/client_test.go diff --git a/go.mod b/go.mod index 44e4fcc..293cf30 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,14 @@ module github.com/surrealdb/surrealdb.go go 1.18 -require github.com/gorilla/websocket v1.5.0 +require ( + github.com/gorilla/websocket v1.5.0 + github.com/test-go/testify v1.1.4 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.8.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index e5a03d4..16dc1a2 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,19 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= +github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/httpclient/client.go b/httpclient/client.go new file mode 100644 index 0000000..b953e2b --- /dev/null +++ b/httpclient/client.go @@ -0,0 +1,91 @@ +package httpclient + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" +) + +// SurrealClient is a wrapper to more easily make HTTP calls to the SurrealDB engine +type SurrealClient struct { + // URL is the base URL in SurrealDB to be called + URL string + // DB that you want to connect to + DB string + // Namespace that you want to connect to + NS string + User string + Password string +} + +// New creates a new instance of a SurrealClient +func New(url, db, ns, user, password string) SurrealClient { + return SurrealClient{ + URL: url, + DB: db, + NS: ns, + User: user, + Password: password, + } +} + +// Execute executes a POST with the given query, returning the raw JSON response as a string +// TODO: marshal the response into something nicer, depending on what the community decides +func (sc SurrealClient) Execute(query string) ([]byte, error) { + return sc.Request("/sql", "POST", query) +} + +func (sc SurrealClient) CreateOne(table, id, query string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "POST", query) +} + +func (sc SurrealClient) CreateAll(table string, query string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s", table), "POST", query) +} + +func (sc SurrealClient) SelectAll(table string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s", table), "GET", "") +} + +func (sc SurrealClient) SelectOne(table string, id string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "GET", "") +} + +func (sc SurrealClient) ReplaceOne(table, id, query string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PUT", query) +} + +func (sc SurrealClient) UpsertOne(table, id, query string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PATCH", query) +} + +func (sc SurrealClient) DeleteOne(table, id string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "DELETE", "") +} + +func (sc SurrealClient) DeleteAll(table string) ([]byte, error) { + return sc.Request(fmt.Sprintf("/key/%s", table), "DELETE", "") +} + +func (sc SurrealClient) Request(endpoint string, requestType string, body string) ([]byte, error) { + client := &http.Client{} + + // TODO: verify its a valid requesttype + req, err := http.NewRequest(requestType, sc.URL+endpoint, bytes.NewBufferString(body)) + if err != nil { + return []byte{}, err + } + req.Header.Set("NS", sc.NS) + req.Header.Set("DB", sc.DB) + req.Header.Set("Content-Type", "application/json") + req.SetBasicAuth(sc.User, sc.Password) + + resp, err := client.Do(req) + if err != nil { + return []byte{}, err + } + defer resp.Body.Close() + + return ioutil.ReadAll(resp.Body) +} diff --git a/httpclient/client_test.go b/httpclient/client_test.go new file mode 100644 index 0000000..c1447d3 --- /dev/null +++ b/httpclient/client_test.go @@ -0,0 +1,103 @@ +package httpclient + +import ( + "fmt" + "testing" + + "github.com/test-go/testify/require" +) + +func Test_Nominal(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + resp, err := client.Execute("INFO FOR DB;") + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_CreateAll(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + resp, err := client.CreateAll("person", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_CreateOne(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + resp, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_SelectAll(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + resp, err := client.SelectAll("transaction") + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_SelectOne(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + resp, err := client.SelectOne("transaction", "3b1wx6plrru4lizvs6j8") + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_ReplaceOne(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + _, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + + resp, err := client.ReplaceOne("person", "surreal", `{child: "DB", name: "FooBar", age: 1000}`) + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_UpsertOne(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + _, err := client.CreateOne("person", "surrealupsert", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + + resp, err := client.UpsertOne("person", "surrealupsert", `{child: "DB", name: "FooBar"}`) + require.Nil(t, err) + fmt.Println(string(resp)) +} + +func Test_DeleteOne(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + _, err := client.CreateOne("person", "surrealdelete", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + + resp, err := client.DeleteOne("person", "surrealdelete") + require.Nil(t, err) + fmt.Println(string(resp)) + + resp2, err := client.SelectOne("person", "surrealdelete") + require.Nil(t, err) + fmt.Println(string(resp2)) +} + +func Test_DeleteAll(t *testing.T) { + client := New("http://localhost:8000", "test", "test", "root", "root") + + _, err := client.CreateOne("person", "surrealdeleteall1", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + + _, err = client.CreateOne("person", "surrealdeleteall2", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + + resp, err := client.DeleteAll("person") + require.Nil(t, err) + fmt.Println(string(resp)) + + resp2, err := client.SelectAll("person") + require.Nil(t, err) + fmt.Println(string(resp2)) +} From 00c00b8d6871e0958da58c2d4bda307397d946f2 Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Sun, 18 Sep 2022 20:59:38 -0400 Subject: [PATCH 3/7] Added function docs, basic unmarshaling of response data, updated tests --- httpclient/client.go | 74 +++++++++++++++++++++++++++++++-------- httpclient/client_test.go | 44 ++++++++++++++--------- 2 files changed, 87 insertions(+), 31 deletions(-) diff --git a/httpclient/client.go b/httpclient/client.go index b953e2b..b77f515 100644 --- a/httpclient/client.go +++ b/httpclient/client.go @@ -2,6 +2,7 @@ package httpclient import ( "bytes" + "encoding/json" "fmt" "io/ioutil" "net/http" @@ -19,6 +20,12 @@ type SurrealClient struct { Password string } +type Response struct { + Time string `json:"time"` + Status string `json:"status"` + Result any `json:"result"` +} + // New creates a new instance of a SurrealClient func New(url, db, ns, user, password string) SurrealClient { return SurrealClient{ @@ -30,51 +37,77 @@ func New(url, db, ns, user, password string) SurrealClient { } } -// Execute executes a POST with the given query, returning the raw JSON response as a string -// TODO: marshal the response into something nicer, depending on what the community decides -func (sc SurrealClient) Execute(query string) ([]byte, error) { +// Execute calls the endpoint POST /sql, executing whatever given statement +func (sc SurrealClient) Execute(query string) (Response, error) { return sc.Request("/sql", "POST", query) } -func (sc SurrealClient) CreateOne(table, id, query string) ([]byte, error) { +// CreateOne calls the endpoint POST /key/:table/:id, executing the statement +// +// CREATE type::table($table) CONTENT $body; +func (sc SurrealClient) CreateOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "POST", query) } -func (sc SurrealClient) CreateAll(table string, query string) ([]byte, error) { +// CreateAll calls the endpoint POST /key/:table, executing the statement +// +// CREATE type::thing($table, $id) CONTENT $body; +func (sc SurrealClient) CreateAll(table string, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "POST", query) } -func (sc SurrealClient) SelectAll(table string) ([]byte, error) { +// SelectAll calls the endpoint GET /key/:table, executing the statement +// +// SELECT * FROM type::table($table); +func (sc SurrealClient) SelectAll(table string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "GET", "") } -func (sc SurrealClient) SelectOne(table string, id string) ([]byte, error) { +// SelectOne calls the endpoint GET /key/:table/:id, executing the statement +// +// SELECT * FROM type::thing(:table, :id); +func (sc SurrealClient) SelectOne(table string, id string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "GET", "") } -func (sc SurrealClient) ReplaceOne(table, id, query string) ([]byte, error) { +// ReplaceOne calls the endpoint PUT /key/:table/:id, executing the statement +// +// UPDATE type::thing($table, $id) CONTENT $body; +func (sc SurrealClient) ReplaceOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PUT", query) } -func (sc SurrealClient) UpsertOne(table, id, query string) ([]byte, error) { +// UpsertOne calls the endpoint PUT /key/:table/:id, executing the statement +// +// UPDATE type::thing($table, $id) MERGE $body; +func (sc SurrealClient) UpsertOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PATCH", query) } -func (sc SurrealClient) DeleteOne(table, id string) ([]byte, error) { +// DeleteOne calls the endpoint DELETE /key/:table/:id, executing the statement +// +// DELETE FROM type::thing($table, $id); +func (sc SurrealClient) DeleteOne(table, id string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "DELETE", "") } -func (sc SurrealClient) DeleteAll(table string) ([]byte, error) { +// DeleteAll calls the endpoint DELETE /key/:table/, executing the statement +// +// DELETE FROM type::table($table); +func (sc SurrealClient) DeleteAll(table string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "DELETE", "") } -func (sc SurrealClient) Request(endpoint string, requestType string, body string) ([]byte, error) { +// Request makes a request to surrealdb to the given endpoint, with the given data. Responses returned from +// surrealdb vary, and this function will only return the first response +// TODO: have it return the array, or some other data type that more properly reflects the responses +func (sc SurrealClient) Request(endpoint string, requestType string, body string) (Response, error) { client := &http.Client{} // TODO: verify its a valid requesttype req, err := http.NewRequest(requestType, sc.URL+endpoint, bytes.NewBufferString(body)) if err != nil { - return []byte{}, err + return Response{}, err } req.Header.Set("NS", sc.NS) req.Header.Set("DB", sc.DB) @@ -83,9 +116,20 @@ func (sc SurrealClient) Request(endpoint string, requestType string, body string resp, err := client.Do(req) if err != nil { - return []byte{}, err + return Response{}, err } defer resp.Body.Close() - return ioutil.ReadAll(resp.Body) + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return Response{}, err + } + + var realResp []Response + err = json.Unmarshal(data, &realResp) + if err != nil { + return Response{}, err + } + + return realResp[0], err } diff --git a/httpclient/client_test.go b/httpclient/client_test.go index c1447d3..39c5891 100644 --- a/httpclient/client_test.go +++ b/httpclient/client_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/test-go/testify/assert" "github.com/test-go/testify/require" ) @@ -12,7 +13,7 @@ func Test_Nominal(t *testing.T) { resp, err := client.Execute("INFO FOR DB;") require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) } func Test_CreateAll(t *testing.T) { @@ -20,42 +21,53 @@ func Test_CreateAll(t *testing.T) { resp, err := client.CreateAll("person", `{child: null, name: "FooBar"}`) require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) + + fmt.Println(resp.Result) } func Test_CreateOne(t *testing.T) { client := New("http://localhost:8000", "test", "test", "root", "root") - resp, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + resp, err := client.CreateOne("person", "surrealcreate", `{child: null, name: "FooBar"}`) require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) } func Test_SelectAll(t *testing.T) { client := New("http://localhost:8000", "test", "test", "root", "root") - resp, err := client.SelectAll("transaction") + resp, err := client.SelectAll("person") require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) } func Test_SelectOne(t *testing.T) { client := New("http://localhost:8000", "test", "test", "root", "root") - resp, err := client.SelectOne("transaction", "3b1wx6plrru4lizvs6j8") + resp, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + fmt.Println(resp.Result) + + resp, err = client.SelectOne("person", "surreal") require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) } func Test_ReplaceOne(t *testing.T) { client := New("http://localhost:8000", "test", "test", "root", "root") - _, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + resp, err := client.CreateOne("personreplace", "surreal", `{child: null, name: "FooBar"}`) require.Nil(t, err) + fmt.Println(resp.Result) - resp, err := client.ReplaceOne("person", "surreal", `{child: "DB", name: "FooBar", age: 1000}`) + resp, err = client.ReplaceOne("personreplace", "surreal", `{child: "DB", name: "FooBar", age: 1000}`) require.Nil(t, err) - fmt.Println(string(resp)) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) } func Test_UpsertOne(t *testing.T) { @@ -66,7 +78,7 @@ func Test_UpsertOne(t *testing.T) { resp, err := client.UpsertOne("person", "surrealupsert", `{child: "DB", name: "FooBar"}`) require.Nil(t, err) - fmt.Println(string(resp)) + fmt.Println(resp.Result) } func Test_DeleteOne(t *testing.T) { @@ -77,11 +89,11 @@ func Test_DeleteOne(t *testing.T) { resp, err := client.DeleteOne("person", "surrealdelete") require.Nil(t, err) - fmt.Println(string(resp)) + fmt.Println(resp.Result) resp2, err := client.SelectOne("person", "surrealdelete") require.Nil(t, err) - fmt.Println(string(resp2)) + fmt.Println(resp2.Result) } func Test_DeleteAll(t *testing.T) { @@ -95,9 +107,9 @@ func Test_DeleteAll(t *testing.T) { resp, err := client.DeleteAll("person") require.Nil(t, err) - fmt.Println(string(resp)) + fmt.Println(resp.Result) resp2, err := client.SelectAll("person") require.Nil(t, err) - fmt.Println(string(resp2)) + fmt.Println(resp2.Result) } From b94ac1bc87564c4ce17ae2f5746b899111d0965d Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Tue, 20 Sep 2022 22:52:26 -0400 Subject: [PATCH 4/7] changed client to surrealdb package, removed any, some renaming --- httpclient/client.go => client.go | 62 +++++++++++---------- httpclient/client_test.go => client_test.go | 20 +++---- 2 files changed, 42 insertions(+), 40 deletions(-) rename httpclient/client.go => client.go (67%) rename httpclient/client_test.go => client_test.go (78%) diff --git a/httpclient/client.go b/client.go similarity index 67% rename from httpclient/client.go rename to client.go index b77f515..83d9e08 100644 --- a/httpclient/client.go +++ b/client.go @@ -1,4 +1,4 @@ -package httpclient +package surrealdb import ( "bytes" @@ -8,100 +8,102 @@ import ( "net/http" ) -// SurrealClient is a wrapper to more easily make HTTP calls to the SurrealDB engine -type SurrealClient struct { +// Client is a wrapper to more easily make HTTP calls to the SurrealDB engine +type Client struct { // URL is the base URL in SurrealDB to be called URL string - // DB that you want to connect to - DB string // Namespace that you want to connect to - NS string - User string - Password string + NS string + // Database that you want to connect to + DB string + // The user to authenticate as + User string + // The password to authenticate with + Pass string } type Response struct { - Time string `json:"time"` - Status string `json:"status"` - Result any `json:"result"` + Time string `json:"time"` + Status string `json:"status"` + Result interface{} `json:"result"` } -// New creates a new instance of a SurrealClient -func New(url, db, ns, user, password string) SurrealClient { - return SurrealClient{ - URL: url, - DB: db, - NS: ns, - User: user, - Password: password, +// New creates a new instance of a Client +func NewClient(url, ns, db, user, pass string) Client { + return Client{ + URL: url, + NS: ns, + DB: db, + User: user, + Pass: pass, } } // Execute calls the endpoint POST /sql, executing whatever given statement -func (sc SurrealClient) Execute(query string) (Response, error) { +func (sc Client) Execute(query string) (Response, error) { return sc.Request("/sql", "POST", query) } // CreateOne calls the endpoint POST /key/:table/:id, executing the statement // // CREATE type::table($table) CONTENT $body; -func (sc SurrealClient) CreateOne(table, id, query string) (Response, error) { +func (sc Client) CreateOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "POST", query) } // CreateAll calls the endpoint POST /key/:table, executing the statement // // CREATE type::thing($table, $id) CONTENT $body; -func (sc SurrealClient) CreateAll(table string, query string) (Response, error) { +func (sc Client) CreateAll(table string, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "POST", query) } // SelectAll calls the endpoint GET /key/:table, executing the statement // // SELECT * FROM type::table($table); -func (sc SurrealClient) SelectAll(table string) (Response, error) { +func (sc Client) SelectAll(table string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "GET", "") } // SelectOne calls the endpoint GET /key/:table/:id, executing the statement // // SELECT * FROM type::thing(:table, :id); -func (sc SurrealClient) SelectOne(table string, id string) (Response, error) { +func (sc Client) SelectOne(table string, id string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "GET", "") } // ReplaceOne calls the endpoint PUT /key/:table/:id, executing the statement // // UPDATE type::thing($table, $id) CONTENT $body; -func (sc SurrealClient) ReplaceOne(table, id, query string) (Response, error) { +func (sc Client) ReplaceOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PUT", query) } // UpsertOne calls the endpoint PUT /key/:table/:id, executing the statement // // UPDATE type::thing($table, $id) MERGE $body; -func (sc SurrealClient) UpsertOne(table, id, query string) (Response, error) { +func (sc Client) UpsertOne(table, id, query string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PATCH", query) } // DeleteOne calls the endpoint DELETE /key/:table/:id, executing the statement // // DELETE FROM type::thing($table, $id); -func (sc SurrealClient) DeleteOne(table, id string) (Response, error) { +func (sc Client) DeleteOne(table, id string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "DELETE", "") } // DeleteAll calls the endpoint DELETE /key/:table/, executing the statement // // DELETE FROM type::table($table); -func (sc SurrealClient) DeleteAll(table string) (Response, error) { +func (sc Client) DeleteAll(table string) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "DELETE", "") } // Request makes a request to surrealdb to the given endpoint, with the given data. Responses returned from // surrealdb vary, and this function will only return the first response // TODO: have it return the array, or some other data type that more properly reflects the responses -func (sc SurrealClient) Request(endpoint string, requestType string, body string) (Response, error) { +func (sc Client) Request(endpoint string, requestType string, body string) (Response, error) { client := &http.Client{} // TODO: verify its a valid requesttype @@ -112,7 +114,7 @@ func (sc SurrealClient) Request(endpoint string, requestType string, body string req.Header.Set("NS", sc.NS) req.Header.Set("DB", sc.DB) req.Header.Set("Content-Type", "application/json") - req.SetBasicAuth(sc.User, sc.Password) + req.SetBasicAuth(sc.User, sc.Pass) resp, err := client.Do(req) if err != nil { diff --git a/httpclient/client_test.go b/client_test.go similarity index 78% rename from httpclient/client_test.go rename to client_test.go index 39c5891..d867542 100644 --- a/httpclient/client_test.go +++ b/client_test.go @@ -1,4 +1,4 @@ -package httpclient +package surrealdb import ( "fmt" @@ -9,7 +9,7 @@ import ( ) func Test_Nominal(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.Execute("INFO FOR DB;") require.Nil(t, err) @@ -17,7 +17,7 @@ func Test_Nominal(t *testing.T) { } func Test_CreateAll(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateAll("person", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -27,7 +27,7 @@ func Test_CreateAll(t *testing.T) { } func Test_CreateOne(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateOne("person", "surrealcreate", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -36,7 +36,7 @@ func Test_CreateOne(t *testing.T) { } func Test_SelectAll(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.SelectAll("person") require.Nil(t, err) @@ -45,7 +45,7 @@ func Test_SelectAll(t *testing.T) { } func Test_SelectOne(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -58,7 +58,7 @@ func Test_SelectOne(t *testing.T) { } func Test_ReplaceOne(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateOne("personreplace", "surreal", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -71,7 +71,7 @@ func Test_ReplaceOne(t *testing.T) { } func Test_UpsertOne(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") _, err := client.CreateOne("person", "surrealupsert", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -82,7 +82,7 @@ func Test_UpsertOne(t *testing.T) { } func Test_DeleteOne(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") _, err := client.CreateOne("person", "surrealdelete", `{child: null, name: "FooBar"}`) require.Nil(t, err) @@ -97,7 +97,7 @@ func Test_DeleteOne(t *testing.T) { } func Test_DeleteAll(t *testing.T) { - client := New("http://localhost:8000", "test", "test", "root", "root") + client := NewClient("http://localhost:8000", "test", "test", "root", "root") _, err := client.CreateOne("person", "surrealdeleteall1", `{child: null, name: "FooBar"}`) require.Nil(t, err) From 4f407b09c7561646b4e2be9572ac3ffd125e8c5d Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Tue, 20 Sep 2022 22:56:24 -0400 Subject: [PATCH 5/7] used correct testify library in gomod --- client_test.go | 4 ++-- go.mod | 3 +-- go.sum | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client_test.go b/client_test.go index d867542..513d4b3 100644 --- a/client_test.go +++ b/client_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/test-go/testify/assert" - "github.com/test-go/testify/require" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_Nominal(t *testing.T) { diff --git a/go.mod b/go.mod index 293cf30..a64b798 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,11 @@ go 1.18 require ( github.com/gorilla/websocket v1.5.0 - github.com/test-go/testify v1.1.4 + github.com/stretchr/testify v1.8.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 16dc1a2..7138eb1 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= From 3ea0ff544174dd0504e0b115495d19e4c127d979 Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Thu, 22 Sep 2022 21:55:24 -0400 Subject: [PATCH 6/7] Changed http request body to accept interface, improved testing even more --- client.go | 38 ++++++++++++++++++-------- client_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/client.go b/client.go index 83d9e08..9761fa1 100644 --- a/client.go +++ b/client.go @@ -8,7 +8,10 @@ import ( "net/http" ) -// Client is a wrapper to more easily make HTTP calls to the SurrealDB engine +// Client is a wrapper to more easily make HTTP calls to the SurrealDB engine. +// Any function that accepts a body of type interface{} will do one of two things depending on type. +// If it is of type string, the body will be the plaintext string, otherwise it will attempt to marshal +// it into JSON and send that type Client struct { // URL is the base URL in SurrealDB to be called URL string @@ -47,15 +50,15 @@ func (sc Client) Execute(query string) (Response, error) { // CreateOne calls the endpoint POST /key/:table/:id, executing the statement // // CREATE type::table($table) CONTENT $body; -func (sc Client) CreateOne(table, id, query string) (Response, error) { - return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "POST", query) +func (sc Client) CreateOne(table, id, body interface{}) (Response, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "POST", body) } // CreateAll calls the endpoint POST /key/:table, executing the statement // // CREATE type::thing($table, $id) CONTENT $body; -func (sc Client) CreateAll(table string, query string) (Response, error) { - return sc.Request(fmt.Sprintf("/key/%s", table), "POST", query) +func (sc Client) CreateAll(table string, body interface{}) (Response, error) { + return sc.Request(fmt.Sprintf("/key/%s", table), "POST", body) } // SelectAll calls the endpoint GET /key/:table, executing the statement @@ -75,15 +78,15 @@ func (sc Client) SelectOne(table string, id string) (Response, error) { // ReplaceOne calls the endpoint PUT /key/:table/:id, executing the statement // // UPDATE type::thing($table, $id) CONTENT $body; -func (sc Client) ReplaceOne(table, id, query string) (Response, error) { - return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PUT", query) +func (sc Client) ReplaceOne(table, id string, body interface{}) (Response, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PUT", body) } // UpsertOne calls the endpoint PUT /key/:table/:id, executing the statement // // UPDATE type::thing($table, $id) MERGE $body; -func (sc Client) UpsertOne(table, id, query string) (Response, error) { - return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PATCH", query) +func (sc Client) UpsertOne(table, id string, body interface{}) (Response, error) { + return sc.Request(fmt.Sprintf("/key/%s/%s", table, id), "PATCH", body) } // DeleteOne calls the endpoint DELETE /key/:table/:id, executing the statement @@ -103,11 +106,24 @@ func (sc Client) DeleteAll(table string) (Response, error) { // Request makes a request to surrealdb to the given endpoint, with the given data. Responses returned from // surrealdb vary, and this function will only return the first response // TODO: have it return the array, or some other data type that more properly reflects the responses -func (sc Client) Request(endpoint string, requestType string, body string) (Response, error) { +func (sc Client) Request(endpoint string, requestType string, body interface{}) (Response, error) { client := &http.Client{} + var bodyBytes []byte + var err error + + // If it is a string, send it directly though, otherwise try to unmarshal, throwing an error if it fails + switch v := body.(type) { + case string: + bodyBytes = []byte(v) + default: + bodyBytes, err = json.Marshal(v) + if err != nil { + return Response{}, err + } + } // TODO: verify its a valid requesttype - req, err := http.NewRequest(requestType, sc.URL+endpoint, bytes.NewBufferString(body)) + req, err := http.NewRequest(requestType, sc.URL+endpoint, bytes.NewBuffer(bodyBytes)) if err != nil { return Response{}, err } diff --git a/client_test.go b/client_test.go index 513d4b3..2e940af 100644 --- a/client_test.go +++ b/client_test.go @@ -8,6 +8,15 @@ import ( "github.com/stretchr/testify/require" ) +// TODO for testing: adding in more edge case detections, including NULLs and other weird scenarios. Most of these are just +// best case scenarios + +type person struct { + Child string `json:"child"` + Name string `json:"name"` + Age int `json:"age"` +} + func Test_Nominal(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") @@ -47,7 +56,12 @@ func Test_SelectAll(t *testing.T) { func Test_SelectOne(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") - resp, err := client.CreateOne("person", "surreal", `{child: null, name: "FooBar"}`) + expectedPerson := person{ + Child: "hello", + Name: "FooBar", + } + + resp, err := client.CreateOne("person", "surreal", `{child: "hello", name: "FooBar"}`) require.Nil(t, err) fmt.Println(resp.Result) @@ -55,6 +69,11 @@ func Test_SelectOne(t *testing.T) { require.Nil(t, err) assert.Equal(t, "OK", resp.Status) fmt.Println(resp.Result) + + var actualPerson person + err = Unmarshal(resp.Result, &actualPerson) + require.Nil(t, err) + assert.Equal(t, expectedPerson, actualPerson) } func Test_ReplaceOne(t *testing.T) { @@ -70,15 +89,57 @@ func Test_ReplaceOne(t *testing.T) { fmt.Println(resp.Result) } +func Test_ReplaceOne_PassInInterface(t *testing.T) { + client := NewClient("http://localhost:8000", "test", "test", "root", "root") + + expectedPerson := person{ + Child: "interface", + Name: "interface", + Age: 100, + } + + resp, err := client.CreateOne("personreplace", "surrealinterface", `{child: null, name: "FooBar"}`) + require.Nil(t, err) + fmt.Println(resp.Result) + + // Replace with the struct + resp, err = client.ReplaceOne("personreplace", "surrealinterface", expectedPerson) + require.Nil(t, err) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) + + // Now select it to ensure that it is correct still + resp, err = client.SelectOne("personreplace", "surrealinterface") + require.Nil(t, err) + assert.Equal(t, "OK", resp.Status) + fmt.Println(resp.Result) + + // Unmarshal and verify its the same + var actualPerson person + err = Unmarshal(resp.Result, &actualPerson) + require.Nil(t, err) + assert.Equal(t, expectedPerson, actualPerson) +} + func Test_UpsertOne(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") + expectedPerson := person{ + Child: "DB", + Name: "FooBar", + Age: 0, + } _, err := client.CreateOne("person", "surrealupsert", `{child: null, name: "FooBar"}`) require.Nil(t, err) resp, err := client.UpsertOne("person", "surrealupsert", `{child: "DB", name: "FooBar"}`) require.Nil(t, err) - fmt.Println(resp.Result) + + // Unmarshal and verify its the same + var actualPerson person + err = Unmarshal(resp.Result, &actualPerson) + require.Nil(t, err) + assert.Equal(t, expectedPerson, actualPerson) } func Test_DeleteOne(t *testing.T) { @@ -89,11 +150,11 @@ func Test_DeleteOne(t *testing.T) { resp, err := client.DeleteOne("person", "surrealdelete") require.Nil(t, err) - fmt.Println(resp.Result) + assert.Equal(t, []interface{}{}, resp.Result) resp2, err := client.SelectOne("person", "surrealdelete") require.Nil(t, err) - fmt.Println(resp2.Result) + assert.Equal(t, []interface{}{}, resp2.Result) } func Test_DeleteAll(t *testing.T) { @@ -107,9 +168,9 @@ func Test_DeleteAll(t *testing.T) { resp, err := client.DeleteAll("person") require.Nil(t, err) - fmt.Println(resp.Result) + assert.Equal(t, []interface{}{}, resp.Result) resp2, err := client.SelectAll("person") require.Nil(t, err) - fmt.Println(resp2.Result) + assert.Equal(t, []interface{}{}, resp2.Result) } From c70d6a9c9e2f5bc707fd1e1aab221f900b9fcd6f Mon Sep 17 00:00:00 2001 From: MrShutCo Date: Sun, 25 Sep 2022 10:30:59 -0400 Subject: [PATCH 7/7] Removed testify dependency, updated few fields --- client.go | 3 +- client_test.go | 120 +++++++++++++++++++++++++++++++------------------ go.mod | 11 +---- go.sum | 18 -------- 4 files changed, 80 insertions(+), 72 deletions(-) diff --git a/client.go b/client.go index 9761fa1..62ebbbb 100644 --- a/client.go +++ b/client.go @@ -57,7 +57,7 @@ func (sc Client) CreateOne(table, id, body interface{}) (Response, error) { // CreateAll calls the endpoint POST /key/:table, executing the statement // // CREATE type::thing($table, $id) CONTENT $body; -func (sc Client) CreateAll(table string, body interface{}) (Response, error) { +func (sc Client) Create(table string, body interface{}) (Response, error) { return sc.Request(fmt.Sprintf("/key/%s", table), "POST", body) } @@ -130,6 +130,7 @@ func (sc Client) Request(endpoint string, requestType string, body interface{}) req.Header.Set("NS", sc.NS) req.Header.Set("DB", sc.DB) req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") req.SetBasicAuth(sc.User, sc.Pass) resp, err := client.Do(req) diff --git a/client_test.go b/client_test.go index 2e940af..7cbf05b 100644 --- a/client_test.go +++ b/client_test.go @@ -1,11 +1,10 @@ package surrealdb import ( + "bytes" "fmt" + "reflect" "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // TODO for testing: adding in more edge case detections, including NULLs and other weird scenarios. Most of these are just @@ -21,16 +20,16 @@ func Test_Nominal(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.Execute("INFO FOR DB;") - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) } -func Test_CreateAll(t *testing.T) { +func Test_Create(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") - resp, err := client.CreateAll("person", `{child: null, name: "FooBar"}`) - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + resp, err := client.Create("person", `{child: null, name: "FooBar"}`) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) } @@ -39,8 +38,8 @@ func Test_CreateOne(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateOne("person", "surrealcreate", `{child: null, name: "FooBar"}`) - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) } @@ -48,8 +47,8 @@ func Test_SelectAll(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.SelectAll("person") - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) } @@ -62,30 +61,30 @@ func Test_SelectOne(t *testing.T) { } resp, err := client.CreateOne("person", "surreal", `{child: "hello", name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) fmt.Println(resp.Result) resp, err = client.SelectOne("person", "surreal") - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) var actualPerson person err = Unmarshal(resp.Result, &actualPerson) - require.Nil(t, err) - assert.Equal(t, expectedPerson, actualPerson) + IsEqual(t, nil, err) + IsEqual(t, expectedPerson, actualPerson) } func Test_ReplaceOne(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") resp, err := client.CreateOne("personreplace", "surreal", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) fmt.Println(resp.Result) resp, err = client.ReplaceOne("personreplace", "surreal", `{child: "DB", name: "FooBar", age: 1000}`) - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) } @@ -99,26 +98,26 @@ func Test_ReplaceOne_PassInInterface(t *testing.T) { } resp, err := client.CreateOne("personreplace", "surrealinterface", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) fmt.Println(resp.Result) // Replace with the struct resp, err = client.ReplaceOne("personreplace", "surrealinterface", expectedPerson) - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) // Now select it to ensure that it is correct still resp, err = client.SelectOne("personreplace", "surrealinterface") - require.Nil(t, err) - assert.Equal(t, "OK", resp.Status) + IsEqual(t, nil, err) + IsEqual(t, "OK", resp.Status) fmt.Println(resp.Result) // Unmarshal and verify its the same var actualPerson person err = Unmarshal(resp.Result, &actualPerson) - require.Nil(t, err) - assert.Equal(t, expectedPerson, actualPerson) + IsEqual(t, nil, err) + IsEqual(t, expectedPerson, actualPerson) } func Test_UpsertOne(t *testing.T) { @@ -130,47 +129,82 @@ func Test_UpsertOne(t *testing.T) { } _, err := client.CreateOne("person", "surrealupsert", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) resp, err := client.UpsertOne("person", "surrealupsert", `{child: "DB", name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) // Unmarshal and verify its the same var actualPerson person err = Unmarshal(resp.Result, &actualPerson) - require.Nil(t, err) - assert.Equal(t, expectedPerson, actualPerson) + IsEqual(t, nil, err) + IsEqual(t, expectedPerson, actualPerson) } func Test_DeleteOne(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") _, err := client.CreateOne("person", "surrealdelete", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) resp, err := client.DeleteOne("person", "surrealdelete") - require.Nil(t, err) - assert.Equal(t, []interface{}{}, resp.Result) + IsEqual(t, nil, err) + IsEqual(t, []interface{}{}, resp.Result) resp2, err := client.SelectOne("person", "surrealdelete") - require.Nil(t, err) - assert.Equal(t, []interface{}{}, resp2.Result) + IsEqual(t, nil, err) + IsEqual(t, []interface{}{}, resp2.Result) } func Test_DeleteAll(t *testing.T) { client := NewClient("http://localhost:8000", "test", "test", "root", "root") _, err := client.CreateOne("person", "surrealdeleteall1", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) _, err = client.CreateOne("person", "surrealdeleteall2", `{child: null, name: "FooBar"}`) - require.Nil(t, err) + IsEqual(t, nil, err) resp, err := client.DeleteAll("person") - require.Nil(t, err) - assert.Equal(t, []interface{}{}, resp.Result) + IsEqual(t, nil, err) + IsEqual(t, []interface{}{}, resp.Result) resp2, err := client.SelectAll("person") - require.Nil(t, err) - assert.Equal(t, []interface{}{}, resp2.Result) + IsEqual(t, nil, err) + IsEqual(t, []interface{}{}, resp2.Result) +} + +// Testing helpers brought in from testify, with extras removed + +func IsEqual(t *testing.T, expected, actual interface{}) bool { + if !ObjectsAreEqual(expected, actual) { + t.Errorf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s", expected, actual) + return false + } + return true +} + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + if expected == nil || actual == nil { + return expected == actual + } + + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) } diff --git a/go.mod b/go.mod index a64b798..44e4fcc 100644 --- a/go.mod +++ b/go.mod @@ -2,13 +2,4 @@ module github.com/surrealdb/surrealdb.go go 1.18 -require ( - github.com/gorilla/websocket v1.5.0 - github.com/stretchr/testify v1.8.0 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) +require github.com/gorilla/websocket v1.5.0 diff --git a/go.sum b/go.sum index 7138eb1..e5a03d4 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,2 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= -github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=