1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package errors
16
17 import (
18 "errors"
19 "fmt"
20 "net/http"
21 "net/http/httptest"
22 "strings"
23 "testing"
24
25 "github.com/stretchr/testify/assert"
26 "github.com/stretchr/testify/require"
27 )
28
29 type customError struct {
30 apiError
31 }
32
33 func TestServeError(t *testing.T) {
34
35
36 err := MethodNotAllowed("GET", []string{"POST", "PUT"})
37 recorder := httptest.NewRecorder()
38 ServeError(recorder, nil, err)
39 assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code)
40 assert.Equal(t, "POST,PUT", recorder.Header().Get("Allow"))
41
42 assert.Equal(t, `{"code":405,"message":"method GET is not allowed, but [POST,PUT] are"}`, recorder.Body.String())
43
44
45 err = NotFound("")
46 recorder = httptest.NewRecorder()
47 ServeError(recorder, nil, err)
48 assert.Equal(t, http.StatusNotFound, recorder.Code)
49
50 assert.Equal(t, `{"code":404,"message":"Not found"}`, recorder.Body.String())
51
52
53 err = InvalidTypeName("someType")
54 recorder = httptest.NewRecorder()
55 ServeError(recorder, nil, err)
56 assert.Equal(t, http.StatusUnprocessableEntity, recorder.Code)
57
58 assert.Equal(t, `{"code":601,"message":"someType is an invalid type name"}`, recorder.Body.String())
59
60
61 func() {
62 oldDefaultHTTPCode := DefaultHTTPCode
63 defer func() { DefaultHTTPCode = oldDefaultHTTPCode }()
64 DefaultHTTPCode = http.StatusBadRequest
65
66 err = InvalidTypeName("someType")
67 recorder = httptest.NewRecorder()
68 ServeError(recorder, nil, err)
69 assert.Equal(t, http.StatusBadRequest, recorder.Code)
70
71 assert.Equal(t, `{"code":601,"message":"someType is an invalid type name"}`, recorder.Body.String())
72 }()
73
74
75 simpleErr := errors.New("some error")
76 recorder = httptest.NewRecorder()
77 ServeError(recorder, nil, simpleErr)
78 assert.Equal(t, http.StatusInternalServerError, recorder.Code)
79
80 assert.Equal(t, `{"code":500,"message":"some error"}`, recorder.Body.String())
81
82
83
84
85 compositeErr := &CompositeError{
86 Errors: []error{
87 errors.New("firstError"),
88 errors.New("anotherError"),
89 },
90 }
91 recorder = httptest.NewRecorder()
92 ServeError(recorder, nil, compositeErr)
93 assert.Equal(t, http.StatusInternalServerError, recorder.Code)
94 assert.Equal(t, `{"code":500,"message":"firstError"}`, recorder.Body.String())
95
96
97 compositeErr = &CompositeError{
98 Errors: []error{
99 New(600, "myApiError"),
100 New(601, "myOtherApiError"),
101 },
102 }
103 recorder = httptest.NewRecorder()
104 ServeError(recorder, nil, compositeErr)
105 assert.Equal(t, CompositeErrorCode, recorder.Code)
106 assert.Equal(t, `{"code":600,"message":"myApiError"}`, recorder.Body.String())
107
108
109 compositeErr = &CompositeError{
110 Errors: []error{
111 &CompositeError{
112 Errors: []error{
113 New(600, "myApiError"),
114 New(601, "myOtherApiError"),
115 },
116 },
117 },
118 }
119 recorder = httptest.NewRecorder()
120 ServeError(recorder, nil, compositeErr)
121 assert.Equal(t, CompositeErrorCode, recorder.Code)
122 assert.Equal(t, `{"code":600,"message":"myApiError"}`, recorder.Body.String())
123
124
125 compositeErr = &CompositeError{
126 Errors: []error{
127 &CompositeError{
128 Errors: []error{},
129 },
130 },
131 }
132 recorder = httptest.NewRecorder()
133 ServeError(recorder, nil, compositeErr)
134 assert.Equal(t, http.StatusInternalServerError, recorder.Code)
135 assert.Equal(t, `{"code":500,"message":"Unknown error"}`, recorder.Body.String())
136
137
138 recorder = httptest.NewRecorder()
139 ServeError(recorder, nil, nil)
140 assert.Equal(t, http.StatusInternalServerError, recorder.Code)
141 assert.Equal(t, `{"code":500,"message":"Unknown error"}`, recorder.Body.String())
142
143 recorder = httptest.NewRecorder()
144 var z *customError
145 ServeError(recorder, nil, z)
146 assert.Equal(t, http.StatusInternalServerError, recorder.Code)
147 assert.Equal(t, `{"code":500,"message":"Unknown error"}`, recorder.Body.String())
148 }
149
150 func TestAPIErrors(t *testing.T) {
151 err := New(402, "this failed %s", "yada")
152 require.Error(t, err)
153 assert.EqualValues(t, 402, err.Code())
154 assert.EqualValues(t, "this failed yada", err.Error())
155
156 err = NotFound("this failed %d", 1)
157 require.Error(t, err)
158 assert.EqualValues(t, http.StatusNotFound, err.Code())
159 assert.EqualValues(t, "this failed 1", err.Error())
160
161 err = NotFound("")
162 require.Error(t, err)
163 assert.EqualValues(t, http.StatusNotFound, err.Code())
164 assert.EqualValues(t, "Not found", err.Error())
165
166 err = NotImplemented("not implemented")
167 require.Error(t, err)
168 assert.EqualValues(t, http.StatusNotImplemented, err.Code())
169 assert.EqualValues(t, "not implemented", err.Error())
170
171 err = MethodNotAllowed("GET", []string{"POST", "PUT"})
172 require.Error(t, err)
173 assert.EqualValues(t, http.StatusMethodNotAllowed, err.Code())
174 assert.EqualValues(t, "method GET is not allowed, but [POST,PUT] are", err.Error())
175
176 err = InvalidContentType("application/saml", []string{"application/json", "application/x-yaml"})
177 require.Error(t, err)
178 assert.EqualValues(t, http.StatusUnsupportedMediaType, err.Code())
179 assert.EqualValues(t, "unsupported media type \"application/saml\", only [application/json application/x-yaml] are allowed", err.Error())
180
181 err = InvalidResponseFormat("application/saml", []string{"application/json", "application/x-yaml"})
182 require.Error(t, err)
183 assert.EqualValues(t, http.StatusNotAcceptable, err.Code())
184 assert.EqualValues(t, "unsupported media type requested, only [application/json application/x-yaml] are available", err.Error())
185 }
186
187 func TestValidateName(t *testing.T) {
188 v := &Validation{Name: "myValidation", message: "myMessage"}
189
190
191 vv := v.ValidateName("")
192 assert.EqualValues(t, "myValidation", vv.Name)
193 assert.EqualValues(t, "myMessage", vv.message)
194
195
196 vv = v.ValidateName("myNewName")
197 assert.EqualValues(t, "myNewName.myValidation", vv.Name)
198 assert.EqualValues(t, "myNewName.myMessage", vv.message)
199
200 v.Name = ""
201 v.message = "myMessage"
202
203
204 vv = v.ValidateName("")
205 assert.EqualValues(t, "", vv.Name)
206 assert.EqualValues(t, "myMessage", vv.message)
207
208
209 vv = v.ValidateName("myNewName")
210 assert.EqualValues(t, "myNewName", vv.Name)
211 assert.EqualValues(t, "myNewNamemyMessage", vv.message)
212 }
213
214 func TestMarshalJSON(t *testing.T) {
215 const (
216 expectedCode = http.StatusUnsupportedMediaType
217 value = "myValue"
218 )
219 list := []string{"a", "b"}
220
221 e := InvalidContentType(value, list)
222
223 jazon, err := e.MarshalJSON()
224 require.NoError(t, err)
225
226 expectedMessage := strings.ReplaceAll(fmt.Sprintf(contentTypeFail, value, list), `"`, `\"`)
227
228 expectedJSON := fmt.Sprintf(
229 `{"code":%d,"message":"%s","name":"Content-Type","in":"header","value":"%s","values":["a","b"]}`,
230 expectedCode, expectedMessage, value,
231 )
232 assert.JSONEq(t, expectedJSON, string(jazon))
233
234 a := apiError{code: 1, message: "a"}
235 jazon, err = a.MarshalJSON()
236 require.NoError(t, err)
237 assert.JSONEq(t, `{"code":1,"message":"a"}`, string(jazon))
238
239 m := MethodNotAllowedError{code: 1, message: "a", Allowed: []string{"POST"}}
240 jazon, err = m.MarshalJSON()
241 require.NoError(t, err)
242 assert.JSONEq(t, `{"code":1,"message":"a","allowed":["POST"]}`, string(jazon))
243
244 c := CompositeError{Errors: []error{e}, code: 1, message: "a"}
245 jazon, err = c.MarshalJSON()
246 require.NoError(t, err)
247 assert.JSONEq(t, fmt.Sprintf(`{"code":1,"message":"a","errors":[%s]}`, expectedJSON), string(jazon))
248
249 p := ParseError{code: 1, message: "x", Name: "a", In: "b", Value: "c", Reason: errors.New("d")}
250 jazon, err = p.MarshalJSON()
251 require.NoError(t, err)
252 assert.JSONEq(t, `{"code":1,"message":"x","name":"a","in":"b","value":"c","reason":"d"}`, string(jazon))
253 }
254
View as plain text