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