| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package epfrontend | |
| 6 | |
| 7 import ( | |
| 8 "bytes" | |
| 9 "errors" | |
| 10 "net/http" | |
| 11 "strings" | |
| 12 "testing" | |
| 13 | |
| 14 . "github.com/smartystreets/goconvey/convey" | |
| 15 ) | |
| 16 | |
| 17 type testResponseWriter struct { | |
| 18 status int | |
| 19 data bytes.Buffer | |
| 20 err error | |
| 21 header http.Header | |
| 22 } | |
| 23 | |
| 24 func (w *testResponseWriter) Header() http.Header { | |
| 25 return w.header | |
| 26 } | |
| 27 | |
| 28 func (w *testResponseWriter) WriteHeader(status int) { | |
| 29 w.status = status | |
| 30 } | |
| 31 | |
| 32 func (w *testResponseWriter) Write(d []byte) (int, error) { | |
| 33 if w.err != nil { | |
| 34 return 0, w.err | |
| 35 } | |
| 36 return w.data.Write(d) | |
| 37 } | |
| 38 | |
| 39 func TestErrorResponseWriter(t *testing.T) { | |
| 40 Convey(`An errorResponseWriter bound to a testing ResponseWriter`, t, fu
nc() { | |
| 41 rw := &testResponseWriter{} | |
| 42 erw := &errorResponseWriter{ | |
| 43 ResponseWriter: rw, | |
| 44 } | |
| 45 | |
| 46 Convey(`When no error is encountered, data is written directly.`
, func() { | |
| 47 erw.WriteHeader(http.StatusOK) | |
| 48 c, err := erw.Write([]byte("test")) | |
| 49 So(err, ShouldBeNil) | |
| 50 So(c, ShouldEqual, 4) | |
| 51 | |
| 52 So(rw.status, ShouldEqual, http.StatusOK) | |
| 53 So(rw.data.String(), ShouldResemble, "test") | |
| 54 So(erw.forwardError(), ShouldBeFalse) | |
| 55 }) | |
| 56 | |
| 57 Convey(`When an error is encountered, status is translated and d
ata is buffered.`, func() { | |
| 58 erw.WriteHeader(http.StatusNotAcceptable) // 406 => 404 | |
| 59 c, err := erw.Write([]byte("{}")) | |
| 60 So(err, ShouldBeNil) | |
| 61 So(c, ShouldEqual, 2) | |
| 62 | |
| 63 So(rw.status, ShouldEqual, http.StatusNotFound) // (404) | |
| 64 So(rw.data.String(), ShouldEqual, "") | |
| 65 }) | |
| 66 | |
| 67 Convey(`All HTTP error codes translate to error codes.`, func()
{ | |
| 68 for _, r := range []struct { | |
| 69 lb int | |
| 70 ub int | |
| 71 }{ | |
| 72 // 400s | |
| 73 {http.StatusBadRequest, http.StatusTeapot}, | |
| 74 | |
| 75 // 500s | |
| 76 {http.StatusInternalServerError, http.StatusHTTP
VersionNotSupported}, | |
| 77 | |
| 78 // Not real error code. | |
| 79 {1024, 1024}, | |
| 80 } { | |
| 81 for i := r.lb; i <= r.ub; i++ { | |
| 82 r, inst := erw.translateReason(i) | |
| 83 So(r, ShouldBeGreaterThanOrEqualTo, http
.StatusBadRequest) | |
| 84 So(inst, ShouldNotBeNil) | |
| 85 | |
| 86 So(inst.Domain, ShouldEqual, "global") | |
| 87 So(inst.Reason, ShouldNotEqual, "") | |
| 88 } | |
| 89 } | |
| 90 }) | |
| 91 | |
| 92 Convey(`An error set by the frontend is forwarded.`, func() { | |
| 93 erw.setError(errors.New("test error")) | |
| 94 So(erw.forwardError(), ShouldBeTrue) | |
| 95 | |
| 96 So(rw.status, ShouldEqual, http.StatusServiceUnavailable
) | |
| 97 So(rw.data.String(), ShouldEqual, strings.Join([]string{ | |
| 98 `{`, | |
| 99 ` "error": {`, | |
| 100 ` "code": 503,`, | |
| 101 ` "errors": [`, | |
| 102 ` {`, | |
| 103 ` "domain": "global",`, | |
| 104 ` "message": "test error",`, | |
| 105 ` "reason": "backendError"`, | |
| 106 ` }`, | |
| 107 ` ],`, | |
| 108 ` "message": "unspecified error"`, | |
| 109 ` }`, | |
| 110 `}`, | |
| 111 }, "\n")) | |
| 112 }) | |
| 113 | |
| 114 Convey(`A valid error set by the backend is forwarded.`, func()
{ | |
| 115 erw.WriteHeader(http.StatusNotFound) | |
| 116 _, err := erw.Write([]byte(`{"state": "APPLICATION_ERROR
", "error_message": "test error"}`)) | |
| 117 So(err, ShouldBeNil) | |
| 118 So(erw.forwardError(), ShouldBeTrue) | |
| 119 | |
| 120 So(rw.status, ShouldEqual, http.StatusNotFound) | |
| 121 So(rw.data.String(), ShouldEqual, strings.Join([]string{ | |
| 122 `{`, | |
| 123 ` "error": {`, | |
| 124 ` "code": 404,`, | |
| 125 ` "errors": [`, | |
| 126 ` {`, | |
| 127 ` "domain": "global",`, | |
| 128 ` "message": "test error",`, | |
| 129 ` "reason": "notFound"`, | |
| 130 ` }`, | |
| 131 ` ],`, | |
| 132 ` "message": "test error"`, | |
| 133 ` }`, | |
| 134 `}`, | |
| 135 }, "\n")) | |
| 136 }) | |
| 137 | |
| 138 Convey(`An invalid error set by the backend is forwarded.`, func
() { | |
| 139 erw.WriteHeader(http.StatusNotFound) | |
| 140 _, err := erw.Write([]byte(`DEFINITELY NOT JSON`)) | |
| 141 So(err, ShouldBeNil) | |
| 142 So(erw.forwardError(), ShouldBeTrue) | |
| 143 | |
| 144 So(rw.status, ShouldEqual, http.StatusNotFound) | |
| 145 So(rw.data.String(), ShouldEqual, strings.Join([]string{ | |
| 146 `{`, | |
| 147 ` "error": {`, | |
| 148 ` "code": 404,`, | |
| 149 ` "errors": [`, | |
| 150 ` {`, | |
| 151 ` "domain": "global",`, | |
| 152 ` "message": "Failed to decode error JSON (in
valid character 'D' looking for beginning of value): ",`, | |
| 153 ` "reason": "notFound"`, | |
| 154 ` }`, | |
| 155 ` ],`, | |
| 156 ` "message": "unspecified error"`, | |
| 157 ` }`, | |
| 158 `}`, | |
| 159 }, "\n")) | |
| 160 }) | |
| 161 }) | |
| 162 } | |
| OLD | NEW |