@@ -153,6 +153,164 @@ impl IntoHttpResponse for TrustedServerError {
153153mod tests {
154154 use super :: * ;
155155
156+ #[ test]
157+ fn status_code_returns_expected_http_status_for_each_variant ( ) {
158+ let cases = [
159+ (
160+ TrustedServerError :: BadRequest {
161+ message : String :: from ( "missing field" ) ,
162+ } ,
163+ StatusCode :: BAD_REQUEST ,
164+ ) ,
165+ (
166+ TrustedServerError :: Configuration {
167+ message : String :: from ( "missing setting" ) ,
168+ } ,
169+ StatusCode :: INTERNAL_SERVER_ERROR ,
170+ ) ,
171+ (
172+ TrustedServerError :: Auction {
173+ message : String :: from ( "bid timeout" ) ,
174+ } ,
175+ StatusCode :: BAD_GATEWAY ,
176+ ) ,
177+ (
178+ TrustedServerError :: Gam {
179+ message : String :: from ( "request failed" ) ,
180+ } ,
181+ StatusCode :: BAD_GATEWAY ,
182+ ) ,
183+ (
184+ TrustedServerError :: GdprConsent {
185+ message : String :: from ( "missing consent string" ) ,
186+ } ,
187+ StatusCode :: BAD_REQUEST ,
188+ ) ,
189+ (
190+ TrustedServerError :: InvalidUtf8 {
191+ message : String :: from ( "invalid byte sequence" ) ,
192+ } ,
193+ StatusCode :: INTERNAL_SERVER_ERROR ,
194+ ) ,
195+ (
196+ TrustedServerError :: RequestTooLarge {
197+ message : String :: from ( "body too large" ) ,
198+ } ,
199+ StatusCode :: PAYLOAD_TOO_LARGE ,
200+ ) ,
201+ (
202+ TrustedServerError :: InvalidHeaderValue {
203+ message : String :: from ( "non-ascii header" ) ,
204+ } ,
205+ StatusCode :: BAD_REQUEST ,
206+ ) ,
207+ (
208+ TrustedServerError :: KvStore {
209+ store_name : String :: from ( "sessions" ) ,
210+ message : String :: from ( "timeout" ) ,
211+ } ,
212+ StatusCode :: SERVICE_UNAVAILABLE ,
213+ ) ,
214+ (
215+ TrustedServerError :: Prebid {
216+ message : String :: from ( "adapter error" ) ,
217+ } ,
218+ StatusCode :: BAD_GATEWAY ,
219+ ) ,
220+ (
221+ TrustedServerError :: Integration {
222+ integration : String :: from ( "example-integration" ) ,
223+ message : String :: from ( "request failed" ) ,
224+ } ,
225+ StatusCode :: BAD_GATEWAY ,
226+ ) ,
227+ (
228+ TrustedServerError :: Proxy {
229+ message : String :: from ( "upstream failed" ) ,
230+ } ,
231+ StatusCode :: BAD_GATEWAY ,
232+ ) ,
233+ (
234+ TrustedServerError :: Forbidden {
235+ message : String :: from ( "missing permission" ) ,
236+ } ,
237+ StatusCode :: FORBIDDEN ,
238+ ) ,
239+ (
240+ TrustedServerError :: AllowlistViolation {
241+ host : String :: from ( "example.com" ) ,
242+ } ,
243+ StatusCode :: FORBIDDEN ,
244+ ) ,
245+ (
246+ TrustedServerError :: Settings {
247+ message : String :: from ( "parse failed" ) ,
248+ } ,
249+ StatusCode :: INTERNAL_SERVER_ERROR ,
250+ ) ,
251+ (
252+ TrustedServerError :: EdgeCookie {
253+ message : String :: from ( "generation failed" ) ,
254+ } ,
255+ StatusCode :: INTERNAL_SERVER_ERROR ,
256+ ) ,
257+ (
258+ TrustedServerError :: PartnerNotFound {
259+ partner_id : String :: from ( "example-partner" ) ,
260+ } ,
261+ StatusCode :: NOT_FOUND ,
262+ ) ,
263+ (
264+ TrustedServerError :: InsecureDefault {
265+ field : String :: from ( "example.secret" ) ,
266+ } ,
267+ StatusCode :: INTERNAL_SERVER_ERROR ,
268+ ) ,
269+ ] ;
270+
271+ // `mapped_status` is an exhaustive match with no `_` arm, so adding a
272+ // new `TrustedServerError` variant fails to compile here until its
273+ // status is declared — the per-variant coverage can't silently go
274+ // stale. Cross-checking it against the independent `cases` literals
275+ // above guards both encodings against drift.
276+ fn mapped_status ( error : & TrustedServerError ) -> StatusCode {
277+ match error {
278+ TrustedServerError :: BadRequest { .. } => StatusCode :: BAD_REQUEST ,
279+ TrustedServerError :: Configuration { .. } | TrustedServerError :: Settings { .. } => {
280+ StatusCode :: INTERNAL_SERVER_ERROR
281+ }
282+ TrustedServerError :: Auction { .. } => StatusCode :: BAD_GATEWAY ,
283+ TrustedServerError :: Gam { .. } => StatusCode :: BAD_GATEWAY ,
284+ TrustedServerError :: GdprConsent { .. } => StatusCode :: BAD_REQUEST ,
285+ TrustedServerError :: InvalidUtf8 { .. } => StatusCode :: INTERNAL_SERVER_ERROR ,
286+ TrustedServerError :: RequestTooLarge { .. } => StatusCode :: PAYLOAD_TOO_LARGE ,
287+ TrustedServerError :: InvalidHeaderValue { .. } => StatusCode :: BAD_REQUEST ,
288+ TrustedServerError :: KvStore { .. } => StatusCode :: SERVICE_UNAVAILABLE ,
289+ TrustedServerError :: Prebid { .. } => StatusCode :: BAD_GATEWAY ,
290+ TrustedServerError :: Integration { .. } => StatusCode :: BAD_GATEWAY ,
291+ TrustedServerError :: Proxy { .. } => StatusCode :: BAD_GATEWAY ,
292+ TrustedServerError :: Forbidden { .. } => StatusCode :: FORBIDDEN ,
293+ TrustedServerError :: AllowlistViolation { .. } => StatusCode :: FORBIDDEN ,
294+ TrustedServerError :: EdgeCookie { .. } => StatusCode :: INTERNAL_SERVER_ERROR ,
295+ TrustedServerError :: PartnerNotFound { .. } => StatusCode :: NOT_FOUND ,
296+ TrustedServerError :: InsecureDefault { .. } => StatusCode :: INTERNAL_SERVER_ERROR ,
297+ }
298+ }
299+
300+ for ( error, expected_status) in cases {
301+ assert_eq ! (
302+ error. status_code( ) ,
303+ expected_status,
304+ "should map {error:?} to {expected_status}" ,
305+ ) ;
306+ assert_eq ! (
307+ mapped_status( & error) ,
308+ expected_status,
309+ "exhaustive mapping should agree with the table for {error:?}" ,
310+ ) ;
311+ }
312+ }
313+
156314 #[ test]
157315 fn server_errors_return_generic_message ( ) {
158316 let cases = [
0 commit comments