From 89e81617d5fd00f9ebb56dc545b13a0924a9ff24 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 20 Jun 2021 21:52:43 +0200 Subject: [PATCH] test: cover response --- handler.go | 2 +- response.go | 40 ++++++++++---------- response_test.go | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 response_test.go diff --git a/handler.go b/handler.go index 856ae17..b6a8b25 100644 --- a/handler.go +++ b/handler.go @@ -102,7 +102,7 @@ func (s *Handler) handle(c context.Context, input *reqdata.T, handler *apiHandle // find original name from 'rename' field for name, param := range service.Output { if param.Rename == key { - res.SetValue(name, value) + res.WithValue(name, value) } } } diff --git a/response.go b/response.go index d8a8c6a..b4ec028 100644 --- a/response.go +++ b/response.go @@ -9,42 +9,41 @@ import ( // response for an service call type response struct { - Data map[string]interface{} - Status int - Headers http.Header - err api.Err + Data map[string]interface{} + Status int + err api.Err } // newResponse creates an empty response. func newResponse() *response { return &response{ - Status: http.StatusOK, - Data: make(map[string]interface{}), - err: api.ErrFailure, - Headers: make(http.Header), + Status: http.StatusOK, + Data: make(map[string]interface{}), + err: api.ErrFailure, } } // WithError sets the response error -func (res *response) WithError(err api.Err) *response { - res.err = err - return res +func (r *response) WithError(err api.Err) *response { + r.err = err + return r } -// SetValue sets a response value -func (res *response) SetValue(name string, value interface{}) { - res.Data[name] = value +// WithValue sets a response value +func (r *response) WithValue(name string, value interface{}) *response { + r.Data[name] = value + return r } // MarshalJSON generates the JSON representation of the response // // implements json.Marshaler -func (res *response) MarshalJSON() ([]byte, error) { +func (r *response) MarshalJSON() ([]byte, error) { fmt := make(map[string]interface{}) - for k, v := range res.Data { + for k, v := range r.Data { fmt[k] = v } - fmt["error"] = res.err + fmt["error"] = r.err return json.Marshal(fmt) } @@ -54,9 +53,8 @@ func (res *response) MarshalJSON() ([]byte, error) { func (res *response) ServeHTTP(w http.ResponseWriter, r *http.Request) error { w.WriteHeader(res.err.Status) encoded, err := json.Marshal(res) - if err != nil { - return err + if err == nil { + w.Write(encoded) } - w.Write(encoded) - return nil + return err } diff --git a/response_test.go b/response_test.go new file mode 100644 index 0000000..7807450 --- /dev/null +++ b/response_test.go @@ -0,0 +1,95 @@ +package aicra + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/xdrm-io/aicra/api" +) + +func printEscaped(raw string) string { + raw = strings.ReplaceAll(raw, "\n", "\\n") + raw = strings.ReplaceAll(raw, "\r", "\\r") + return raw +} + +func TestResponseJSON(t *testing.T) { + t.Parallel() + + tt := []struct { + name string + err api.Err + data map[string]interface{} + json string + }{ + { + name: "empty success response", + err: api.ErrSuccess, + data: map[string]interface{}{}, + json: `{"error":{"code":0,"reason":"all right"}}`, + }, + { + name: "empty failure response", + err: api.ErrFailure, + data: map[string]interface{}{}, + json: `{"error":{"code":1,"reason":"it failed"}}`, + }, + { + name: "empty unknown error response", + err: api.ErrUnknown, + data: map[string]interface{}{}, + json: `{"error":{"code":-1,"reason":"unknown error"}}`, + }, + { + name: "success with data before err", + err: api.ErrSuccess, + data: map[string]interface{}{"a": 12}, + json: `{"a":12,"error":{"code":0,"reason":"all right"}}`, + }, + { + name: "success with data right before err", + err: api.ErrSuccess, + data: map[string]interface{}{"e": 12}, + json: `{"e":12,"error":{"code":0,"reason":"all right"}}`, + }, + { + name: "success with data right after err", + err: api.ErrSuccess, + data: map[string]interface{}{"f": 12}, + json: `{"error":{"code":0,"reason":"all right"},"f":12}`, + }, + { + name: "success with data after err", + err: api.ErrSuccess, + data: map[string]interface{}{"z": 12}, + json: `{"error":{"code":0,"reason":"all right"},"z":12}`, + }, + { + name: "success with data around err", + err: api.ErrSuccess, + data: map[string]interface{}{"d": "before", "f": "after"}, + json: `{"d":"before","error":{"code":0,"reason":"all right"},"f":"after"}`, + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + res := newResponse().WithError(tc.err) + for k, v := range tc.data { + res.WithValue(k, v) + } + + raw, err := json.Marshal(res) + if err != nil { + t.Fatalf("cannot marshal to json: %s", err) + } + + if string(raw) != tc.json { + t.Fatalf("mismatching json:\nexpect: %v\nactual: %v", printEscaped(tc.json), printEscaped(string(raw))) + } + + }) + } + +}