test: cover response

This commit is contained in:
Adrien Marquès 2021-06-20 21:52:43 +02:00
parent cff4106bf5
commit 89e81617d5
3 changed files with 115 additions and 22 deletions

View File

@ -102,7 +102,7 @@ func (s *Handler) handle(c context.Context, input *reqdata.T, handler *apiHandle
// find original name from 'rename' field // find original name from 'rename' field
for name, param := range service.Output { for name, param := range service.Output {
if param.Rename == key { if param.Rename == key {
res.SetValue(name, value) res.WithValue(name, value)
} }
} }
} }

View File

@ -9,42 +9,41 @@ import (
// response for an service call // response for an service call
type response struct { type response struct {
Data map[string]interface{} Data map[string]interface{}
Status int Status int
Headers http.Header err api.Err
err api.Err
} }
// newResponse creates an empty response. // newResponse creates an empty response.
func newResponse() *response { func newResponse() *response {
return &response{ return &response{
Status: http.StatusOK, Status: http.StatusOK,
Data: make(map[string]interface{}), Data: make(map[string]interface{}),
err: api.ErrFailure, err: api.ErrFailure,
Headers: make(http.Header),
} }
} }
// WithError sets the response error // WithError sets the response error
func (res *response) WithError(err api.Err) *response { func (r *response) WithError(err api.Err) *response {
res.err = err r.err = err
return res return r
} }
// SetValue sets a response value // WithValue sets a response value
func (res *response) SetValue(name string, value interface{}) { func (r *response) WithValue(name string, value interface{}) *response {
res.Data[name] = value r.Data[name] = value
return r
} }
// MarshalJSON generates the JSON representation of the response // MarshalJSON generates the JSON representation of the response
// //
// implements json.Marshaler // implements json.Marshaler
func (res *response) MarshalJSON() ([]byte, error) { func (r *response) MarshalJSON() ([]byte, error) {
fmt := make(map[string]interface{}) fmt := make(map[string]interface{})
for k, v := range res.Data { for k, v := range r.Data {
fmt[k] = v fmt[k] = v
} }
fmt["error"] = res.err fmt["error"] = r.err
return json.Marshal(fmt) 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 { func (res *response) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
w.WriteHeader(res.err.Status) w.WriteHeader(res.err.Status)
encoded, err := json.Marshal(res) encoded, err := json.Marshal(res)
if err != nil { if err == nil {
return err w.Write(encoded)
} }
w.Write(encoded) return err
return nil
} }

95
response_test.go Normal file
View File

@ -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)))
}
})
}
}