16 "github.com/stretchr/testify/assert"
17 "github.com/stretchr/testify/require"
19 "github.com/tendermint/tmlibs/common"
22 func TestWriteSuccess(t *testing.T) {
23 w := httptest.NewRecorder()
24 common.WriteSuccess(w, "foo")
25 assert.Equal(t, w.Code, 200, "should get a 200")
28 var blankErrResponse = new(common.ErrorResponse)
30 func TestWriteError(t *testing.T) {
31 tests := [...]struct {
36 msg: "this is a message",
41 for i, tt := range tests {
42 w := httptest.NewRecorder()
45 // First check without a defined code, should send back a 400
46 common.WriteError(w, errors.New(msg))
47 assert.Equal(t, w.Code, http.StatusBadRequest, "#%d: should get a 400", i)
48 blob, err := ioutil.ReadAll(w.Body)
50 assert.Fail(t, "expecting a successful ioutil.ReadAll", "#%d", i)
54 recv := new(common.ErrorResponse)
55 if err := json.Unmarshal(blob, recv); err != nil {
56 assert.Fail(t, "expecting a successful json.Unmarshal", "#%d", i)
60 assert.Equal(t, reflect.DeepEqual(recv, blankErrResponse), false, "expecting a non-blank error response")
62 // Now test with an error that's .HTTPCode() int conforming
65 w = httptest.NewRecorder()
67 common.WriteError(w, common.ErrorWithCode(errors.New("foo"), tt.code))
68 assert.Equal(t, w.Code, tt.code, "case #%d", i)
72 type marshalFailer struct{}
74 var errFooFailed = errors.New("foo failed here")
76 func (mf *marshalFailer) MarshalJSON() ([]byte, error) {
77 return nil, errFooFailed
80 func TestWriteCode(t *testing.T) {
83 1: http.StatusBadRequest,
84 2: http.StatusUnauthorized,
85 3: http.StatusInternalServerError,
88 for i, code := range codes {
89 w := httptest.NewRecorder()
90 common.WriteCode(w, "foo", code)
91 assert.Equal(t, w.Code, code, "#%d", i)
93 // Then for the failed JSON marshaling
94 w = httptest.NewRecorder()
95 common.WriteCode(w, &marshalFailer{}, code)
96 wantCode := http.StatusBadRequest
97 assert.Equal(t, w.Code, wantCode, "#%d", i)
98 assert.True(t, strings.Contains(w.Body.String(), errFooFailed.Error()),
99 "#%d: expected %q in the error message", i, errFooFailed)
104 Foo int `json:"foo" validate:"min=10"`
105 Bar string `json:"bar"`
108 type rcloser struct {
114 var errAlreadyClosed = errors.New("already closed")
116 func (rc *rcloser) Close() error {
117 var err = errAlreadyClosed
118 rc.closeOnce.Do(func() {
126 func (rc *rcloser) Read(b []byte) (int, error) {
127 return rc.body.Read(b)
130 var _ io.ReadCloser = (*rcloser)(nil)
132 func makeReq(strBody string) (*http.Request, <-chan bool) {
133 closeChan := make(chan bool, 1)
134 buf := new(bytes.Buffer)
135 buf.Write([]byte(strBody))
136 req := &http.Request{
137 Header: make(http.Header),
138 Body: &rcloser{body: buf, closeChan: closeChan},
140 return req, closeChan
143 func TestParseRequestJSON(t *testing.T) {
144 tests := [...]struct {
149 0: {wantErr: true, body: ``},
151 2: {body: `{"foo": 2}`}, // Not that the validate tags don't matter here since we are just parsing
152 3: {body: `{"foo": "abcd"}`, wantErr: true},
153 4: {useNil: true, wantErr: true},
156 for i, tt := range tests {
157 req, closeChan := makeReq(tt.body)
162 err := common.ParseRequestJSON(req, sav)
164 assert.NotEqual(t, err, nil, "#%d: want non-nil error", i)
167 assert.Equal(t, err, nil, "#%d: want nil error", i)
168 wasClosed := <-closeChan
169 assert.Equal(t, wasClosed, true, "#%d: should have invoked close", i)
173 func TestFparseJSON(t *testing.T) {
174 r1 := strings.NewReader(`{"foo": 1}`)
176 require.Equal(t, common.FparseJSON(r1, sav), nil, "expecting successful parsing")
177 r2 := strings.NewReader(`{"bar": "blockchain"}`)
178 require.Equal(t, common.FparseJSON(r2, sav), nil, "expecting successful parsing")
179 require.Equal(t, reflect.DeepEqual(sav, &saver{Foo: 1, Bar: "blockchain"}), true, "should have parsed both")
181 // Now with a nil body
182 require.NotEqual(t, nil, common.FparseJSON(nil, sav), "expecting a nil error report")
185 func TestFparseAndValidateJSON(t *testing.T) {
186 r1 := strings.NewReader(`{"foo": 1}`)
188 require.NotEqual(t, common.FparseAndValidateJSON(r1, sav), nil, "expecting validation to fail")
189 r1 = strings.NewReader(`{"foo": 100}`)
190 require.Equal(t, common.FparseJSON(r1, sav), nil, "expecting successful parsing")
191 r2 := strings.NewReader(`{"bar": "blockchain"}`)
192 require.Equal(t, common.FparseAndValidateJSON(r2, sav), nil, "expecting successful parsing")
193 require.Equal(t, reflect.DeepEqual(sav, &saver{Foo: 100, Bar: "blockchain"}), true, "should have parsed both")
195 // Now with a nil body
196 require.NotEqual(t, nil, common.FparseJSON(nil, sav), "expecting a nil error report")
199 var blankSaver = new(saver)
201 func TestParseAndValidateRequestJSON(t *testing.T) {
202 tests := [...]struct {
207 0: {wantErr: true, body: ``},
208 1: {body: `{}`, wantErr: true}, // Here it should fail since Foo doesn't meet the minimum value
209 2: {body: `{"foo": 2}`, wantErr: true}, // Here validation should fail
210 3: {body: `{"foo": "abcd"}`, wantErr: true},
211 4: {useNil: true, wantErr: true},
212 5: {body: `{"foo": 100}`}, // Must succeed
215 for i, tt := range tests {
216 req, closeChan := makeReq(tt.body)
221 err := common.ParseRequestAndValidateJSON(req, sav)
223 assert.NotEqual(t, err, nil, "#%d: want non-nil error", i)
227 assert.Equal(t, err, nil, "#%d: want nil error", i)
228 assert.False(t, reflect.DeepEqual(blankSaver, sav), "#%d: expecting a set saver", i)
230 wasClosed := <-closeChan
231 assert.Equal(t, wasClosed, true, "#%d: should have invoked close", i)
235 func TestErrorWithCode(t *testing.T) {
236 tests := [...]struct {
240 0: {code: 500, err: errors.New("funky")},
241 1: {code: 406, err: errors.New("purist")},
244 for i, tt := range tests {
245 errRes := common.ErrorWithCode(tt.err, tt.code)
246 assert.Equal(t, errRes.Error(), tt.err.Error(), "#%d: expecting the error values to be equal", i)
247 assert.Equal(t, errRes.Code, tt.code, "expecting the same status code", i)
248 assert.Equal(t, errRes.HTTPCode(), tt.code, "expecting the same status code", i)