(t *testing.T)
| 1173 | } |
| 1174 | |
| 1175 | func TestWriteUpstreamError(t *testing.T) { |
| 1176 | t.Parallel() |
| 1177 | |
| 1178 | tests := []struct { |
| 1179 | name string |
| 1180 | respErr *ResponseError |
| 1181 | expectStatus int |
| 1182 | // Empty string means the header should be absent. |
| 1183 | expectRetryAfter string |
| 1184 | // Substring expected in the marshaled body. Empty means no body check. |
| 1185 | expectBodyContains string |
| 1186 | }{ |
| 1187 | { |
| 1188 | // Standard error: status and JSON body written. |
| 1189 | name: "writes_status_and_body", |
| 1190 | respErr: newResponseError("upstream failed", "api_error", http.StatusBadGateway, 0), |
| 1191 | expectStatus: http.StatusBadGateway, |
| 1192 | expectBodyContains: `"upstream failed"`, |
| 1193 | }, |
| 1194 | { |
| 1195 | // Whole-second retryAfter: emitted as integer seconds. |
| 1196 | name: "retry_after_in_seconds", |
| 1197 | respErr: newResponseError("rate limited", "rate_limit_error", http.StatusTooManyRequests, 60*time.Second), |
| 1198 | expectStatus: http.StatusTooManyRequests, |
| 1199 | expectRetryAfter: "60", |
| 1200 | }, |
| 1201 | { |
| 1202 | // 500ms rounds up to Retry-After: 1. |
| 1203 | name: "retry_after_500ms_rounds_up_to_one", |
| 1204 | respErr: newResponseError("rate limited", "rate_limit_error", http.StatusTooManyRequests, 500*time.Millisecond), |
| 1205 | expectStatus: http.StatusTooManyRequests, |
| 1206 | expectRetryAfter: "1", |
| 1207 | }, |
| 1208 | { |
| 1209 | // 200ms rounds up to Retry-After: 1. |
| 1210 | name: "retry_after_200ms_rounds_up_to_one", |
| 1211 | respErr: newResponseError("rate limited", "rate_limit_error", http.StatusTooManyRequests, 200*time.Millisecond), |
| 1212 | expectStatus: http.StatusTooManyRequests, |
| 1213 | expectRetryAfter: "1", |
| 1214 | }, |
| 1215 | { |
| 1216 | // Negative retryAfter: header omitted. |
| 1217 | name: "negative_retry_after_omits_header", |
| 1218 | respErr: newResponseError("rate limited", "rate_limit_error", http.StatusTooManyRequests, -1*time.Second), |
| 1219 | expectStatus: http.StatusTooManyRequests, |
| 1220 | expectRetryAfter: "", |
| 1221 | }, |
| 1222 | } |
| 1223 | |
| 1224 | for _, tc := range tests { |
| 1225 | t.Run(tc.name, func(t *testing.T) { |
| 1226 | t.Parallel() |
| 1227 | base := &interceptionBase{logger: slog.Make()} |
| 1228 | |
| 1229 | w := httptest.NewRecorder() |
| 1230 | base.writeUpstreamError(w, tc.respErr) |
| 1231 | |
| 1232 | assert.Equal(t, tc.expectStatus, w.Code, "status code") |
nothing calls this directly
no test coverage detected