Skip to main content

openlark_core/error/
mod.rs

1//! 现代化错误处理系统
2//!
3//! 基于thiserror的完整错误处理解决方案,提供类型安全和开发者友好的API
4
5use uuid::Uuid;
6
7// 暴露错误体系(CoreError 为主要错误类型)
8pub use self::codes::{ErrorCategory, ErrorCode};
9pub use self::context::{ErrorContext, ErrorContextBuilder};
10pub use self::core::{
11    api_error, authentication_error, business_error, configuration_error, network_error,
12    network_error_with_details, permission_missing_error, rate_limit_error, serialization_error,
13    service_unavailable_error, sso_token_invalid_error, timeout_error, token_expired_error,
14    token_invalid_error, user_identity_invalid_error, validation_error,
15};
16pub use self::core::{ApiError, BuilderKind, CoreError, ErrorBuilder, ErrorRecord};
17pub use self::core::{RecoveryStrategy, RetryPolicy};
18pub use self::traits::{ErrorContextTrait, ErrorFormatTrait, ErrorTrait, FullErrorTrait};
19pub use self::traits::{ErrorSeverity, ErrorType};
20
21// 主要类型别名(推荐使用)
22/// SDK 操作结果类型别名
23pub type SDKResult<T> = Result<T, CoreError>;
24/// 错误唯一标识符类型别名
25pub type ErrorId = Uuid;
26
27// 核心模块
28pub mod codes;
29pub mod context;
30pub mod core; // 主实现(含重试策略与错误定义)
31pub mod traits;
32
33// 预设导入
34pub mod prelude;
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use std::time::Duration;
40
41    #[test]
42    fn test_modern_error_creation() {
43        let error = api_error(
44            404,
45            "/api/users/123",
46            "用户不存在",
47            Some("req-123".to_string()),
48        );
49
50        assert_eq!(error.error_type(), ErrorType::Api);
51        assert_eq!(error.severity(), ErrorSeverity::Warning);
52        assert!(!error.is_retryable());
53        assert!(!error.is_user_error());
54        assert_eq!(error.context().request_id(), Some("req-123"));
55    }
56
57    #[test]
58    fn test_detailed_error_creation() {
59        let error = network_error_with_details(
60            "连接超时",
61            Some("https://api.example.com".to_string()), // endpoint
62            Some("req-456".to_string()),                 // request_id
63        );
64
65        assert!(error.is_network_error());
66        assert_eq!(error.context().request_id(), Some("req-456"));
67    }
68
69    // ========== 新增测试: 错误类型创建测试 ==========
70
71    /// 测试 network_error 创建
72    #[test]
73    fn test_network_error_creation() {
74        let error = network_error("网络连接失败");
75
76        assert!(error.is_network_error());
77        assert!(error.is_retryable());
78        assert_eq!(error.error_type(), ErrorType::Network);
79        assert!(matches!(error.code(), ErrorCode::NetworkConnectionFailed));
80    }
81
82    /// 测试 authentication_error 创建
83    #[test]
84    fn test_authentication_error_creation() {
85        let error = authentication_error("令牌无效");
86
87        assert!(error.is_auth_error());
88        assert!(!error.is_retryable());
89        assert_eq!(error.error_type(), ErrorType::Authentication);
90        assert!(error.is_user_error());
91    }
92
93    /// 测试 validation_error 创建
94    #[test]
95    fn test_validation_error_creation() {
96        let error = validation_error("username", "用户名不能为空");
97
98        assert!(error.is_validation_error());
99        assert!(!error.is_retryable());
100        assert_eq!(error.error_type(), ErrorType::Validation);
101        assert!(error.context().has_context("field"));
102        assert_eq!(error.context().get_context("field"), Some("username"));
103    }
104
105    /// 测试 business_error 创建
106    #[test]
107    fn test_business_error_creation() {
108        let error = business_error("库存不足");
109
110        assert!(error.is_business_error());
111        assert!(!error.is_retryable());
112        assert_eq!(error.error_type(), ErrorType::Business);
113        assert!(matches!(error.code(), ErrorCode::BusinessError));
114    }
115
116    /// 测试 configuration_error 创建
117    #[test]
118    fn test_configuration_error_creation() {
119        let error = configuration_error("缺少必要配置项");
120
121        assert!(error.is_config_error());
122        assert!(!error.is_retryable());
123        assert_eq!(error.error_type(), ErrorType::Configuration);
124        assert!(matches!(error.code(), ErrorCode::ConfigurationError));
125    }
126
127    /// 测试 timeout_error 创建
128    #[test]
129    fn test_timeout_error_creation() {
130        let error = timeout_error(Duration::from_secs(30), Some("api_call".to_string()));
131
132        assert!(error.is_timeout_error());
133        assert!(error.is_retryable());
134        assert_eq!(error.error_type(), ErrorType::Timeout);
135    }
136
137    /// 测试 rate_limit_error 创建
138    #[test]
139    fn test_rate_limit_error_creation() {
140        let error = rate_limit_error(100, Duration::from_secs(60), Some(Duration::from_secs(30)));
141
142        assert!(error.is_rate_limited());
143        assert!(error.is_retryable());
144        assert_eq!(error.error_type(), ErrorType::RateLimit);
145        assert_eq!(error.retry_delay(0), Some(Duration::from_secs(60)));
146    }
147
148    /// 测试 service_unavailable_error 创建
149    #[test]
150    fn test_service_unavailable_error_creation() {
151        let error = service_unavailable_error("飞书API", Some(Duration::from_secs(120)));
152
153        assert!(error.is_service_unavailable_error());
154        assert!(error.is_retryable());
155        assert_eq!(error.error_type(), ErrorType::ServiceUnavailable);
156    }
157
158    /// 测试 permission_missing_error 创建
159    #[test]
160    fn test_permission_missing_error_creation() {
161        let error = permission_missing_error(&["contact:user:read", "contact:user:write"]);
162
163        assert!(error.is_auth_error());
164        assert!(error.context().has_context("required_scopes"));
165        assert!(error
166            .context()
167            .get_context("required_scopes")
168            .unwrap()
169            .contains("contact:user:read"));
170    }
171
172    /// 测试 sso_token_invalid_error 创建
173    #[test]
174    fn test_sso_token_invalid_error_creation() {
175        let error = sso_token_invalid_error("SSO令牌已过期");
176
177        assert!(error.is_auth_error());
178        assert!(error.context().has_context("detail"));
179        assert!(matches!(error.code(), ErrorCode::SsoTokenInvalid));
180    }
181
182    /// 测试 user_identity_invalid_error 创建
183    #[test]
184    fn test_user_identity_invalid_error_creation() {
185        let error = user_identity_invalid_error("用户身份无法解析");
186
187        assert!(error.is_auth_error());
188        assert!(error.context().has_context("description"));
189        assert!(matches!(error.code(), ErrorCode::UserIdentityInvalid));
190    }
191
192    /// 测试 token_invalid_error 创建
193    #[test]
194    fn test_token_invalid_error_creation() {
195        let error = token_invalid_error("访问令牌格式错误");
196
197        assert!(error.is_auth_error());
198        assert!(error.context().has_context("detail"));
199        assert!(matches!(error.code(), ErrorCode::AccessTokenInvalid));
200    }
201
202    /// 测试 token_expired_error 创建
203    #[test]
204    fn test_token_expired_error_creation() {
205        let error = token_expired_error("访问令牌已过期");
206
207        assert!(error.is_auth_error());
208        assert!(error.context().has_context("detail"));
209        assert!(matches!(error.code(), ErrorCode::AccessTokenExpiredV2));
210    }
211
212    /// 测试 serialization_error 创建
213    #[test]
214    fn test_serialization_error_creation() {
215        let error: CoreError = serialization_error("JSON解析失败", None::<serde_json::Error>);
216
217        assert!(error.is_serialization_error());
218        assert!(!error.is_retryable());
219        assert_eq!(error.error_type(), ErrorType::Serialization);
220    }
221
222    // ========== ErrorContextBuilder 测试 ==========
223
224    /// 测试 ErrorContextBuilder 完整功能
225    #[test]
226    fn test_error_context_builder_full() {
227        let context = ErrorContextBuilder::new()
228            .user_message("操作失败")
229            .context("endpoint", "/api/v1/users")
230            .context("method", "POST")
231            .request_id("req-test-001")
232            .operation("create_user")
233            .component("user_service")
234            .build();
235
236        assert_eq!(context.user_message(), Some("操作失败"));
237        assert_eq!(context.get_context("endpoint"), Some("/api/v1/users"));
238        assert_eq!(context.get_context("method"), Some("POST"));
239        assert_eq!(context.request_id(), Some("req-test-001"));
240        assert_eq!(context.operation(), Some("create_user"));
241        assert_eq!(context.component(), Some("user_service"));
242    }
243
244    /// 测试 ErrorContext 批量添加上下文
245    #[test]
246    fn test_error_context_extend() {
247        let mut context = ErrorContext::new();
248        context.extend_context(vec![
249            ("key1", "value1"),
250            ("key2", "value2"),
251            ("key3", "value3"),
252        ]);
253
254        assert_eq!(context.context_len(), 3);
255        assert_eq!(context.get_context("key1"), Some("value1"));
256        assert_eq!(context.get_context("key2"), Some("value2"));
257        assert_eq!(context.get_context("key3"), Some("value3"));
258    }
259
260    // ========== RetryPolicy 测试 ==========
261
262    /// 测试 RetryPolicy::no_retry
263    #[test]
264    fn test_retry_policy_no_retry() {
265        let policy = RetryPolicy::no_retry();
266
267        assert!(!policy.is_retryable());
268        assert_eq!(policy.max_retries(), 0);
269        assert!(policy.retry_delay(0).is_none());
270    }
271
272    /// 测试 RetryPolicy::fixed
273    #[test]
274    fn test_retry_policy_fixed() {
275        let policy = RetryPolicy::fixed(3, Duration::from_secs(5));
276
277        assert!(policy.is_retryable());
278        assert_eq!(policy.max_retries(), 3);
279        assert_eq!(policy.retry_delay(0), Some(Duration::from_secs(5)));
280        assert_eq!(policy.retry_delay(1), Some(Duration::from_secs(5)));
281        assert!(!policy.use_exponential_backoff());
282    }
283
284    /// 测试 RetryPolicy::exponential
285    #[test]
286    fn test_retry_policy_exponential() {
287        let policy = RetryPolicy::exponential(4, Duration::from_secs(1));
288
289        assert!(policy.is_retryable());
290        assert_eq!(policy.max_retries(), 4);
291        assert!(policy.use_exponential_backoff());
292
293        // 验证指数退避
294        let delay0 = policy.retry_delay(0).unwrap();
295        let delay1 = policy.retry_delay(1).unwrap();
296        let delay2 = policy.retry_delay(2).unwrap();
297
298        assert!(delay1 > delay0);
299        assert!(delay2 > delay1);
300    }
301
302    /// 测试 RetryPolicy::delay 方法
303    #[test]
304    fn test_retry_policy_delay() {
305        let policy = RetryPolicy::fixed(2, Duration::from_secs(10));
306
307        assert_eq!(policy.delay(0), Duration::from_secs(10));
308        assert_eq!(policy.delay(1), Duration::from_secs(10));
309        // 超过最大重试次数返回 0
310        assert_eq!(policy.delay(2), Duration::ZERO);
311    }
312
313    /// 测试 RetryPolicy default
314    #[test]
315    fn test_retry_policy_default() {
316        let policy = RetryPolicy::default();
317
318        assert!(policy.is_retryable());
319        assert_eq!(policy.max_retries(), 3);
320        assert!(policy.use_exponential_backoff());
321    }
322
323    // ========== ErrorRecord 序列化测试 ==========
324
325    /// 测试 ErrorRecord 序列化
326    #[test]
327    fn test_error_record_serialization() {
328        let error = api_error(404, "/api/test", "资源不存在", Some("req-123".to_string()));
329        let record = error.record();
330
331        // 验证序列化成功
332        let json = serde_json::to_string(&record).expect("序列化失败");
333        assert!(json.contains("NotFound"));
334        assert!(json.contains("req-123"));
335        assert!(json.contains("资源不存在"));
336    }
337
338    /// 测试 ErrorRecord 反序列化
339    #[test]
340    fn test_error_record_json_roundtrip() {
341        let error = api_error(
342            500,
343            "/api/internal",
344            "内部错误",
345            Some("req-456".to_string()),
346        );
347        let record = error.record();
348
349        // 序列化
350        let json = serde_json::to_string(&record).expect("序列化失败");
351
352        // 验证关键字段存在
353        assert!(json.contains("InternalServerError"));
354        assert!(json.contains("req-456"));
355        assert!(json.contains("retryable"));
356    }
357
358    // ========== ErrorBuilder 测试 ==========
359
360    /// 测试 ErrorBuilder 创建 API 错误
361    #[test]
362    fn test_error_builder_api_error() {
363        let error = CoreError::api_builder()
364            .status(429)
365            .endpoint("/api/rate-limited")
366            .message("请求过于频繁")
367            .request_id("req-rate-001")
368            .build();
369
370        assert!(error.is_api_error());
371        assert!(error.is_retryable());
372        assert_eq!(error.context().request_id(), Some("req-rate-001"));
373    }
374
375    /// 测试 ErrorBuilder 创建验证错误
376    #[test]
377    fn test_error_builder_validation_error() {
378        let error = CoreError::validation_builder()
379            .field("email")
380            .message("邮箱格式不正确")
381            .context("input", "invalid-email")
382            .build();
383
384        assert!(error.is_validation_error());
385        assert!(!error.is_retryable());
386    }
387
388    /// 测试 ErrorBuilder 创建网络错误
389    #[test]
390    fn test_error_builder_network_error() {
391        let error = CoreError::network_builder()
392            .message("连接超时")
393            .endpoint("https://api.feishu.cn")
394            .operation("fetch_user")
395            .build();
396
397        assert!(error.is_network_error());
398        assert!(error.is_retryable());
399    }
400
401    /// 测试 ErrorBuilder 创建业务错误
402    #[test]
403    fn test_error_builder_business_error() {
404        let error = CoreError::business_builder()
405            .message("订单已取消")
406            .context("order_id", "ORDER-123")
407            .build();
408
409        assert!(error.is_business_error());
410        assert!(!error.is_retryable());
411    }
412
413    /// 测试 ErrorBuilder 创建认证错误
414    #[test]
415    fn test_error_builder_authentication_error() {
416        let error = CoreError::authentication_builder()
417            .message("令牌已过期")
418            .request_id("req-auth-001")
419            .build();
420
421        assert!(error.is_auth_error());
422        assert!(!error.is_retryable());
423        assert_eq!(error.context().request_id(), Some("req-auth-001"));
424    }
425
426    // ========== ErrorCode 测试 ==========
427
428    /// 测试 ErrorCode HTTP 状态码映射
429    #[test]
430    fn test_error_code_from_http_status() {
431        assert_eq!(ErrorCode::from_http_status(400), ErrorCode::BadRequest);
432        assert_eq!(ErrorCode::from_http_status(401), ErrorCode::Unauthorized);
433        assert_eq!(ErrorCode::from_http_status(403), ErrorCode::Forbidden);
434        assert_eq!(ErrorCode::from_http_status(404), ErrorCode::NotFound);
435        assert_eq!(ErrorCode::from_http_status(429), ErrorCode::TooManyRequests);
436        assert_eq!(
437            ErrorCode::from_http_status(500),
438            ErrorCode::InternalServerError
439        );
440        assert_eq!(
441            ErrorCode::from_http_status(503),
442            ErrorCode::ServiceUnavailable
443        );
444    }
445
446    /// 测试 ErrorCode severity
447    #[test]
448    fn test_error_code_severity() {
449        assert_eq!(ErrorCode::Success.severity(), ErrorSeverity::Info);
450        assert_eq!(ErrorCode::NotFound.severity(), ErrorSeverity::Warning);
451        assert_eq!(
452            ErrorCode::InternalServerError.severity(),
453            ErrorSeverity::Critical
454        );
455        assert_eq!(
456            ErrorCode::NetworkTimeout.severity(),
457            ErrorSeverity::Critical
458        );
459    }
460
461    // ========== 错误类型判断测试 ==========
462
463    /// 测试 ErrorTrait is_user_error 和 is_system_error
464    #[test]
465    fn test_error_trait_user_system_errors() {
466        let validation = validation_error("field", "无效");
467        assert!(validation.is_user_error());
468        assert!(!validation.is_system_error());
469
470        let network = network_error("连接失败");
471        assert!(!network.is_user_error());
472        assert!(network.is_system_error());
473
474        let auth = authentication_error("认证失败");
475        assert!(auth.is_user_error());
476        assert!(!auth.is_system_error());
477    }
478
479    /// 测试 CoreError Clone
480    #[test]
481    fn test_core_error_clone() {
482        let error = api_error(404, "/api/test", "资源不存在", Some("req-123".to_string()));
483        let cloned = error.clone();
484
485        assert_eq!(error.error_type(), cloned.error_type());
486        assert_eq!(error.code(), cloned.code());
487        assert_eq!(error.context().request_id(), cloned.context().request_id());
488    }
489
490    /// 测试 CoreError Display
491    #[test]
492    fn test_core_error_display() {
493        let error = network_error("连接失败");
494        let display = format!("{}", error);
495        assert!(display.contains("网络错误"));
496
497        let error = validation_error("field", "无效值");
498        let display = format!("{}", error);
499        assert!(display.contains("验证错误"));
500    }
501
502    /// 测试 CoreError::message() 和 kind() 兼容方法
503    #[test]
504    fn test_core_error_compatibility_methods() {
505        let error = api_error(500, "/api/test", "服务器错误", None);
506
507        // message() 方法
508        let msg = error.message();
509        assert!(msg.contains("API错误"));
510
511        // kind() 方法 (返回 ErrorType)
512        assert_eq!(error.kind(), ErrorType::Api);
513    }
514
515    /// 测试 CoreError::validation_msg 便捷方法
516    #[test]
517    fn test_core_error_validation_msg() {
518        let error = CoreError::validation_msg("参数验证失败");
519
520        assert!(error.is_validation_error());
521    }
522
523    /// 测试 CoreError::api_error 兼容方法
524    #[test]
525    fn test_core_error_api_error_compatibility() {
526        let error = CoreError::api_error(404, "/api/users", "用户不存在", Some("req-001"));
527
528        assert!(error.is_api_error());
529        assert_eq!(error.context().request_id(), Some("req-001"));
530    }
531
532    /// 测试 CoreError::api_data_error
533    #[test]
534    fn test_core_error_api_data_error() {
535        let error = CoreError::api_data_error("数据为空");
536
537        assert!(error.is_api_error());
538        assert!(error.message().contains("no data"));
539    }
540
541    /// 测试 SDKResult 类型别名
542    #[test]
543    fn test_sdk_result_type_alias() {
544        fn returns_sdk_result() -> SDKResult<String> {
545            Ok("success".to_string())
546        }
547
548        let result = returns_sdk_result();
549        assert!(result.is_ok());
550        assert_eq!(result.unwrap(), "success");
551    }
552
553    // ========== RecoveryStrategy 测试 ==========
554
555    /// 测试 RecoveryStrategy 枚举变体
556    #[test]
557    fn test_recovery_strategy_variants() {
558        let strategies = vec![
559            RecoveryStrategy::RetryWithBackoff,
560            RecoveryStrategy::ValidateAndRetry,
561            RecoveryStrategy::Reauthenticate,
562            RecoveryStrategy::RequestPermission,
563            RecoveryStrategy::ManualIntervention,
564            RecoveryStrategy::RetryWithDelay,
565        ];
566
567        // 验证每个变体都可以被创建和匹配
568        for strategy in strategies {
569            match strategy {
570                RecoveryStrategy::RetryWithBackoff => {}
571                RecoveryStrategy::ValidateAndRetry => {}
572                RecoveryStrategy::Reauthenticate => {}
573                RecoveryStrategy::RequestPermission => {}
574                RecoveryStrategy::ManualIntervention => {}
575                RecoveryStrategy::RetryWithDelay => {}
576            }
577        }
578    }
579
580    /// 测试 RecoveryStrategy Clone
581    #[test]
582    fn test_recovery_strategy_clone() {
583        let strategy = RecoveryStrategy::RetryWithBackoff;
584        let cloned = strategy.clone();
585
586        match (strategy, cloned) {
587            (RecoveryStrategy::RetryWithBackoff, RecoveryStrategy::RetryWithBackoff) => {}
588            _ => panic!("RecoveryStrategy clone 失败"),
589        }
590    }
591
592    /// 测试 RecoveryStrategy Debug
593    #[test]
594    fn test_recovery_strategy_debug() {
595        let strategy = RecoveryStrategy::Reauthenticate;
596        let debug_str = format!("{:?}", strategy);
597        assert!(debug_str.contains("Reauthenticate"));
598    }
599
600    // ========== ErrorContext 扩展测试 ==========
601
602    /// 测试 ErrorContext 所有 getter 方法
603    #[test]
604    fn test_error_context_all_getters() {
605        let mut context = ErrorContext::new();
606        context.set_user_message("测试消息");
607        context.set_request_id("req-123");
608        context.set_operation("test_op");
609        context.set_component("test_component");
610        context.add_context("key1", "value1");
611
612        assert_eq!(context.user_message(), Some("测试消息"));
613        assert_eq!(context.request_id(), Some("req-123"));
614        assert_eq!(context.operation(), Some("test_op"));
615        assert_eq!(context.component(), Some("test_component"));
616        assert_eq!(context.get_context("key1"), Some("value1"));
617        assert!(context.timestamp().is_some());
618    }
619
620    /// 测试 ErrorContext is_empty 和 context_len
621    #[test]
622    fn test_error_context_empty_and_len() {
623        let empty_context = ErrorContext::new();
624        assert!(empty_context.is_empty());
625        assert_eq!(empty_context.context_len(), 0);
626
627        let mut context = ErrorContext::new();
628        context.add_context("key", "value");
629        assert!(!context.is_empty());
630        assert_eq!(context.context_len(), 1);
631    }
632
633    /// 测试 ErrorContext all_context
634    #[test]
635    fn test_error_context_all_context() {
636        let mut context = ErrorContext::new();
637        context.add_context("k1", "v1");
638        context.add_context("k2", "v2");
639
640        let all = context.all_context();
641        assert_eq!(all.len(), 2);
642        assert_eq!(all.get("k1"), Some(&"v1".to_string()));
643        assert_eq!(all.get("k2"), Some(&"v2".to_string()));
644    }
645
646    /// 测试 ErrorContextBuilder 链式调用完整流程
647    #[test]
648    fn test_error_context_builder_chaining() {
649        let context = ErrorContextBuilder::new()
650            .user_message("链式消息")
651            .request_id("chain-req-001")
652            .operation("chain_op")
653            .component("chain_comp")
654            .context("extra", "data")
655            .build();
656
657        assert_eq!(context.user_message(), Some("链式消息"));
658        assert_eq!(context.request_id(), Some("chain-req-001"));
659        assert_eq!(context.operation(), Some("chain_op"));
660        assert_eq!(context.component(), Some("chain_comp"));
661        assert_eq!(context.get_context("extra"), Some("data"));
662    }
663
664    // ========== 错误序列化/反序列化扩展测试 ==========
665
666    /// 测试各种错误类型的序列化
667    #[test]
668    fn test_error_record_serialization_various_types() {
669        // 网络错误
670        let network = network_error("连接超时");
671        let record = network.record();
672        let json = serde_json::to_string(&record).expect("序列化失败");
673        assert!(json.contains("NetworkConnectionFailed") || json.contains("retryable"));
674
675        // 认证错误
676        let auth = authentication_error("令牌无效");
677        let record = auth.record();
678        let json = serde_json::to_string(&record).expect("序列化失败");
679        assert!(json.contains("AuthenticationFailed"));
680
681        // 业务错误
682        let business = business_error("库存不足");
683        let record = business.record();
684        let json = serde_json::to_string(&record).expect("序列化失败");
685        assert!(json.contains("BusinessError"));
686    }
687
688    /// 测试 ErrorRecord 序列化包含所有字段
689    #[test]
690    fn test_error_record_full_serialization() {
691        let error = api_error(
692            404,
693            "/api/resource",
694            "资源不存在",
695            Some("req-xyz".to_string()),
696        );
697        let record = error.record();
698        let json = serde_json::to_string(&record).expect("序列化失败");
699
700        // 验证 JSON 包含所有关键字段
701        assert!(json.contains("NotFound"));
702        assert!(json.contains("req-xyz"));
703        assert!(json.contains("retryable"));
704        assert!(json.contains("severity"));
705        assert!(json.contains("message"));
706    }
707
708    /// 测试不同 severity 的序列化
709    #[test]
710    fn test_error_record_severity_serialization() {
711        let info_error = api_error(200, "/api", "成功", None::<String>);
712        let warning_error = api_error(404, "/api", "未找到", None::<String>);
713        let critical_error = api_error(500, "/api", "服务器错误", None::<String>);
714
715        let info_record = info_error.record();
716        let warning_record = warning_error.record();
717        let critical_record = critical_error.record();
718
719        assert_eq!(info_record.severity, ErrorSeverity::Info);
720        assert_eq!(warning_record.severity, ErrorSeverity::Warning);
721        assert_eq!(critical_record.severity, ErrorSeverity::Critical);
722    }
723
724    // ========== CoreError 方法全面测试 ==========
725
726    /// 测试 CoreError 所有判断方法
727    #[test]
728    fn test_core_error_all_predicates() {
729        assert!(network_error("test").is_network_error());
730        assert!(authentication_error("test").is_auth_error());
731        assert!(validation_error("f", "m").is_validation_error());
732        assert!(business_error("test").is_business_error());
733        assert!(timeout_error(Duration::from_secs(1), None).is_timeout_error());
734        assert!(rate_limit_error(1, Duration::from_secs(1), None).is_rate_limited());
735        assert!(service_unavailable_error("svc", None).is_service_unavailable_error());
736        assert!(serialization_error("test", None::<serde_json::Error>).is_serialization_error());
737    }
738
739    /// 测试 CoreError user_message 方法
740    #[test]
741    fn test_core_error_user_message() {
742        let network = network_error("连接失败");
743        assert_eq!(network.user_message(), Some("网络连接异常,请稍后重试"));
744
745        let auth = authentication_error("认证失败");
746        assert_eq!(auth.user_message(), Some("认证失败,请重新登录"));
747
748        let timeout = timeout_error(Duration::from_secs(30), Some("api_call".to_string()));
749        assert_eq!(timeout.user_message(), Some("请求超时,请稍后重试"));
750
751        let rate_limit = rate_limit_error(100, Duration::from_secs(60), None);
752        assert_eq!(rate_limit.user_message(), Some("请求过于频繁,请稍候"));
753
754        let service = service_unavailable_error("api", None);
755        assert_eq!(service.user_message(), Some("服务暂不可用,请稍后重试"));
756    }
757
758    /// 测试 CoreError retry_delay 对不同错误类型
759    #[test]
760    fn test_core_error_retry_delay_various() {
761        // API 错误 500 系列应该有退避延迟
762        let api500 = api_error(500, "/api", "error", None::<String>);
763        let delay0 = api500.retry_delay(0);
764        let delay1 = api500.retry_delay(1);
765        assert!(delay0.is_some());
766        assert!(delay1.is_some());
767        assert!(delay1.unwrap() > delay0.unwrap());
768
769        // API 错误 429 应该有延迟
770        let api429 = api_error(429, "/api", "too many requests", None::<String>);
771        assert!(api429.retry_delay(0).is_some());
772
773        // API 错误 400 不应该重试
774        let api400 = api_error(400, "/api", "bad request", None::<String>);
775        assert!(!api400.is_retryable());
776    }
777
778    /// 测试 CoreError error_code 方法
779    #[test]
780    fn test_core_error_error_code() {
781        let api = api_error(404, "/api", "not found", None::<String>);
782        assert_eq!(api.error_code(), None); // CoreError 的 error_code 返回 None
783    }
784
785    /// 测试 CoreError 各种构建器方法
786    #[test]
787    fn test_core_error_builder_methods() {
788        let network_builder = CoreError::network_builder();
789        let api_builder = CoreError::api_builder();
790        let validation_builder = CoreError::validation_builder();
791        let auth_builder = CoreError::authentication_builder();
792        let business_builder = CoreError::business_builder();
793
794        // 验证构建器可以被创建(不需要进一步构建)
795        let _ = network_builder;
796        let _ = api_builder;
797        let _ = validation_builder;
798        let _ = auth_builder;
799        let _ = business_builder;
800    }
801
802    /// 测试 CoreError 便捷构造方法
803    #[test]
804    fn test_core_error_convenience_methods() {
805        let network_msg = CoreError::network_msg("网络消息");
806        assert!(network_msg.is_network_error());
807
808        let auth = CoreError::authentication("认证消息");
809        assert!(auth.is_auth_error());
810
811        let api_err = CoreError::api_error(500, "/api", "api消息", Some("req-id"));
812        assert!(api_err.is_api_error());
813
814        let validation_msg = CoreError::validation_msg("验证消息");
815        assert!(validation_msg.is_validation_error());
816    }
817
818    /// 测试 ErrorId 类型别名
819    #[test]
820    fn test_error_id_type_alias() {
821        let id: ErrorId = Uuid::new_v4();
822        assert!(!id.to_string().is_empty());
823    }
824
825    #[test]
826    fn test_lark_api_error_type_alias() {
827        fn use_lark_api_error() -> CoreError {
828            api_error(500, "/api", "test", None::<String>)
829        }
830
831        let error = use_lark_api_error();
832        assert!(error.is_api_error());
833    }
834
835    /// 测试错误类型转换边界情况
836    #[test]
837    fn test_error_type_conversions() {
838        // 从 reqwest::Error 转换(模拟)
839        // 由于无法轻易创建 reqwest::Error,我们测试序列化错误转换
840        let json_err = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
841        let core_err: CoreError = json_err.into();
842        assert!(core_err.is_serialization_error());
843    }
844
845    // ========== BuilderKind 测试 ==========
846
847    /// 测试 BuilderKind 枚举
848    #[test]
849    fn test_builder_kind_variants() {
850        let kinds = vec![
851            BuilderKind::Network,
852            BuilderKind::Authentication,
853            BuilderKind::Api,
854            BuilderKind::Validation,
855            BuilderKind::Configuration,
856            BuilderKind::Serialization,
857            BuilderKind::Business,
858            BuilderKind::Timeout,
859            BuilderKind::RateLimit,
860            BuilderKind::ServiceUnavailable,
861            BuilderKind::Internal,
862        ];
863
864        for kind in kinds {
865            match kind {
866                BuilderKind::Network => {}
867                BuilderKind::Authentication => {}
868                BuilderKind::Api => {}
869                BuilderKind::Validation => {}
870                BuilderKind::Configuration => {}
871                BuilderKind::Serialization => {}
872                BuilderKind::Business => {}
873                BuilderKind::Timeout => {}
874                BuilderKind::RateLimit => {}
875                BuilderKind::ServiceUnavailable => {}
876                BuilderKind::Internal => {}
877            }
878        }
879    }
880
881    /// 测试 BuilderKind Debug
882    #[test]
883    fn test_builder_kind_debug() {
884        let kind = BuilderKind::Api;
885        let debug = format!("{:?}", kind);
886        assert!(debug.contains("Api"));
887    }
888}