github.com/go-graphite/carbonapi@v0.17.0/zipper/helper/errors_test.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "reflect" 8 "testing" 9 10 "github.com/ansel1/merry" 11 "github.com/go-graphite/carbonapi/zipper/types" 12 ) 13 14 func TestMergeHttpErrors(t *testing.T) { 15 tests := []struct { 16 name string 17 errors []merry.Error 18 wantCode int 19 want []string 20 }{ 21 { 22 name: "NotFound", 23 errors: []merry.Error{}, 24 wantCode: http.StatusNotFound, 25 want: []string{}, 26 }, 27 { 28 name: "NetErr", 29 errors: []merry.Error{ 30 types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")}).WithHTTPCode(http.StatusServiceUnavailable), 31 }, 32 wantCode: http.StatusServiceUnavailable, 33 want: []string{"connect: refused"}, 34 }, 35 { 36 name: "NetErr (incapsulated)", 37 errors: []merry.Error{ 38 types.ErrMaxTriesExceeded.WithCause(types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")})).WithHTTPCode(http.StatusServiceUnavailable), 39 }, 40 wantCode: http.StatusServiceUnavailable, 41 want: []string{"connect: refused"}, 42 }, 43 { 44 name: "ServiceUnavailable", 45 errors: []merry.Error{ 46 merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 47 }, 48 wantCode: http.StatusServiceUnavailable, 49 want: []string{"unavaliable"}, 50 }, 51 { 52 name: "GatewayTimeout and ServiceUnavailable", 53 errors: []merry.Error{ 54 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 55 merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 56 }, 57 wantCode: http.StatusServiceUnavailable, 58 want: []string{"timeout", "unavaliable"}, 59 }, 60 { 61 name: "ServiceUnavailable and GatewayTimeout", 62 errors: []merry.Error{ 63 merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 64 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 65 }, 66 wantCode: http.StatusServiceUnavailable, 67 want: []string{"unavaliable", "timeout"}, 68 }, 69 { 70 name: "Forbidden and GatewayTimeout", 71 errors: []merry.Error{ 72 merry.New("limit").WithHTTPCode(http.StatusForbidden), 73 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 74 }, 75 wantCode: http.StatusForbidden, 76 want: []string{"limit", "timeout"}, 77 }, 78 { 79 name: "GatewayTimeout and Forbidden", 80 errors: []merry.Error{ 81 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 82 merry.New("limit").WithHTTPCode(http.StatusForbidden), 83 }, 84 wantCode: http.StatusForbidden, 85 want: []string{"timeout", "limit"}, 86 }, 87 { 88 name: "InternalServerError and Forbidden", 89 errors: []merry.Error{ 90 merry.New("error").WithHTTPCode(http.StatusInternalServerError), 91 merry.New("limit").WithHTTPCode(http.StatusForbidden), 92 }, 93 wantCode: http.StatusForbidden, 94 want: []string{"error", "limit"}, 95 }, 96 { 97 name: "InternalServerError and GatewayTimeout", 98 errors: []merry.Error{ 99 merry.New("error").WithHTTPCode(http.StatusInternalServerError), 100 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 101 }, 102 wantCode: http.StatusInternalServerError, 103 want: []string{"error", "timeout"}, 104 }, 105 { 106 name: "GatewayTimeout and InternalServerError", 107 errors: []merry.Error{ 108 merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 109 merry.New("error").WithHTTPCode(http.StatusInternalServerError), 110 }, 111 wantCode: http.StatusInternalServerError, 112 want: []string{"timeout", "error"}, 113 }, 114 { 115 name: "BadRequest and Forbidden", 116 errors: []merry.Error{ 117 merry.New("error").WithHTTPCode(http.StatusBadRequest), 118 merry.New("limit").WithHTTPCode(http.StatusForbidden), 119 }, 120 wantCode: http.StatusBadRequest, 121 want: []string{"error", "limit"}, 122 }, 123 { 124 name: "Forbidden and BadRequest", 125 errors: []merry.Error{ 126 merry.New("limit").WithHTTPCode(http.StatusForbidden), 127 merry.New("error").WithHTTPCode(http.StatusBadRequest), 128 }, 129 wantCode: http.StatusBadRequest, 130 want: []string{"limit", "error"}, 131 }, 132 } 133 for _, tt := range tests { 134 t.Run(tt.name, func(t *testing.T) { 135 gotCode, got := MergeHttpErrors(tt.errors) 136 if gotCode != tt.wantCode { 137 t.Errorf("MergeHttpErrors() gotCode = %v, want %v", gotCode, tt.wantCode) 138 } 139 if !reflect.DeepEqual(got, tt.want) { 140 t.Errorf("MergeHttpErrors() got = %v, want %v", got, tt.want) 141 } 142 }) 143 } 144 } 145 146 func TestMergeHttpErrorMap(t *testing.T) { 147 tests := []struct { 148 name string 149 errors map[string]merry.Error 150 wantCode int 151 want map[string]string 152 }{ 153 { 154 name: "NotFound", 155 errors: map[string]merry.Error{}, 156 wantCode: http.StatusNotFound, 157 want: map[string]string{}, 158 }, 159 { 160 name: "NetErr", 161 errors: map[string]merry.Error{ 162 "a": types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")}).WithHTTPCode(http.StatusServiceUnavailable), 163 }, 164 wantCode: http.StatusServiceUnavailable, 165 want: map[string]string{"a": "connect: refused"}, 166 }, 167 { 168 name: "NetErr (incapsulated)", 169 errors: map[string]merry.Error{ 170 "b": types.ErrMaxTriesExceeded.WithCause(types.ErrBackendError.WithValue("server", "test").WithCause(&net.OpError{Op: "connect", Err: fmt.Errorf("refused")})).WithHTTPCode(http.StatusServiceUnavailable), 171 }, 172 wantCode: http.StatusServiceUnavailable, 173 want: map[string]string{"b": "connect: refused"}, 174 }, 175 { 176 name: "ServiceUnavailable", 177 errors: map[string]merry.Error{ 178 "d": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 179 }, 180 wantCode: http.StatusServiceUnavailable, 181 want: map[string]string{"d": "unavaliable"}, 182 }, 183 { 184 name: "GatewayTimeout and ServiceUnavailable", 185 errors: map[string]merry.Error{ 186 "a": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 187 "de": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 188 }, 189 wantCode: http.StatusServiceUnavailable, 190 want: map[string]string{"a": "timeout", "de": "unavaliable"}, 191 }, 192 { 193 name: "ServiceUnavailable and GatewayTimeout", 194 errors: map[string]merry.Error{ 195 "de": merry.New("unavaliable").WithHTTPCode(http.StatusServiceUnavailable), 196 "a": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 197 }, 198 wantCode: http.StatusServiceUnavailable, 199 want: map[string]string{"a": "timeout", "de": "unavaliable"}, 200 }, 201 { 202 name: "Forbidden and GatewayTimeout", 203 errors: map[string]merry.Error{ 204 "de": merry.New("limit").WithHTTPCode(http.StatusForbidden), 205 "c": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 206 }, 207 wantCode: http.StatusForbidden, 208 want: map[string]string{"c": "timeout", "de": "limit"}, 209 }, 210 { 211 name: "GatewayTimeout and Forbidden", 212 errors: map[string]merry.Error{ 213 "a": merry.New("limit").WithHTTPCode(http.StatusForbidden), 214 "c": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 215 }, 216 wantCode: http.StatusForbidden, 217 want: map[string]string{"a": "limit", "c": "timeout"}, 218 }, 219 { 220 name: "InternalServerError and Forbidden", 221 errors: map[string]merry.Error{ 222 "a": merry.New("error").WithHTTPCode(http.StatusInternalServerError), 223 "cd": merry.New("limit").WithHTTPCode(http.StatusForbidden), 224 }, 225 wantCode: http.StatusForbidden, 226 want: map[string]string{"a": "error", "cd": "limit"}, 227 }, 228 { 229 name: "InternalServerError and GatewayTimeout", 230 errors: map[string]merry.Error{ 231 "a": merry.New("error").WithHTTPCode(http.StatusInternalServerError), 232 "b": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 233 }, 234 wantCode: http.StatusInternalServerError, 235 want: map[string]string{"a": "error", "b": "timeout"}, 236 }, 237 { 238 name: "GatewayTimeout and InternalServerError", 239 errors: map[string]merry.Error{ 240 "a": merry.New("timeout").WithHTTPCode(http.StatusGatewayTimeout), 241 "cd": merry.New("error").WithHTTPCode(http.StatusInternalServerError), 242 }, 243 wantCode: http.StatusInternalServerError, 244 want: map[string]string{"a": "timeout", "cd": "error"}, 245 }, 246 { 247 name: "BadRequest and Forbidden", 248 errors: map[string]merry.Error{ 249 "de": merry.New("error").WithHTTPCode(http.StatusBadRequest), 250 "a": merry.New("limit").WithHTTPCode(http.StatusForbidden), 251 }, 252 wantCode: http.StatusBadRequest, 253 want: map[string]string{"a": "limit", "de": "error"}, 254 }, 255 { 256 name: "Forbidden and BadRequest", 257 errors: map[string]merry.Error{ 258 "a": merry.New("limit").WithHTTPCode(http.StatusForbidden), 259 "b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}": merry.New("error").WithHTTPCode(http.StatusBadRequest), 260 }, 261 wantCode: http.StatusBadRequest, 262 want: map[string]string{ 263 "a": "limit", 264 "b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.b{c,de,klmn}.cde.d{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}.e{c,de,klmn}.k{c,de,klmn}": "error", 265 }, 266 }, 267 } 268 for _, tt := range tests { 269 t.Run(tt.name, func(t *testing.T) { 270 gotCode, got := MergeHttpErrorMap(tt.errors) 271 if gotCode != tt.wantCode { 272 t.Errorf("MergeHttpErrors() gotCode = %v, want %v", gotCode, tt.wantCode) 273 } 274 if !reflect.DeepEqual(got, tt.want) { 275 t.Errorf("MergeHttpErrors() got = %v, want %v", got, tt.want) 276 } 277 }) 278 } 279 }