| 1 | use super::*; |
| 2 | |
| 3 | #[test] |
| 4 | fn raw_rate_and_quota_phrases_remain_coarse_rate_limit_diagnostics() { |
| 5 | for message in [ |
| 6 | "Rate limit reached for gpt-4", |
| 7 | "Too Many Requests", |
| 8 | "HTTP 429 from upstream", |
| 9 | "Your quota has been exceeded", |
| 10 | "Authorization failed: You've reached your usage limit for this billing cycle", |
| 11 | ] { |
| 12 | assert_eq!(classify_error_message(message), ErrorCategory::RateLimit); |
| 13 | } |
| 14 | } |
| 15 | |
| 16 | #[test] |
| 17 | fn typed_llm_quota_envelope_is_non_recoverable_and_distinct_from_rate_limit() { |
| 18 | let envelope = ErrorEnvelope::from(LlmError::from_http_response( |
| 19 | 429, |
| 20 | r#"{"error":{"code":"insufficient_quota"}}"#, |
| 21 | )); |
| 22 | assert_eq!(envelope.category, ErrorCategory::RateLimit); |
| 23 | assert_eq!(envelope.severity, ErrorSeverity::Error); |
| 24 | assert!(!envelope.recoverable); |
| 25 | assert_eq!(envelope.code, "llm_quota_exhausted"); |
| 26 | } |
| 27 | |
| 28 | #[test] |
| 29 | fn llm_auth_error_envelope_renders_context_without_secret() { |
| 30 | let api_key = "tp-secret-token-plan-value"; |
| 31 | let envelope = ErrorEnvelope::from(LlmError::from_http_response_with_request_context( |
| 32 | 401, |
| 33 | &format!("Invalid API Key: {api_key}"), |
| 34 | Some("Xiaomi MiMo"), |
| 35 | Some("https://token-plan-sgp.xiaomimimo.com/v1"), |
| 36 | Some("mimo-v2.5"), |
| 37 | Some("env"), |
| 38 | Some(api_key), |
| 39 | )); |
| 40 | assert_eq!(envelope.category, ErrorCategory::Authentication); |
| 41 | assert_eq!(envelope.severity, ErrorSeverity::Critical); |
| 42 | assert!(!envelope.recoverable); |
| 43 | for expected in [ |
| 44 | "provider: Xiaomi MiMo", |
| 45 | "base URL authority: token-plan-sgp.xiaomimimo.com", |
| 46 | "model: mimo-v2.5", |
| 47 | "key source: env", |
| 48 | "key fingerprint: tp-... (len=26)", |
| 49 | "key type: Xiaomi MiMo Token Plan key", |
| 50 | ] { |
| 51 | assert!(envelope.message.contains(expected)); |
| 52 | } |
| 53 | assert!(!envelope.message.contains(api_key)); |
| 54 | assert!(!envelope.message.contains("secret-token-plan-value")); |
| 55 | } |
| 56 |