open_lark/core/
api_resp.rs

1use std::fmt::{Debug, Display, Formatter};
2
3use serde::{Deserialize, Serialize};
4
5use crate::core::{error::LarkAPIError, error_codes::LarkErrorCode, SDKResult};
6
7/// 业务返回值
8#[derive(Debug, Serialize, Deserialize)]
9pub struct BaseResponse<T> {
10    /// 响应头
11    #[serde(flatten)]
12    pub raw_response: RawResponse,
13    /// 具体数据
14    pub data: Option<T>,
15}
16
17impl<T> BaseResponse<T> {
18    pub fn success(&self) -> bool {
19        self.raw_response.code == 0
20    }
21
22    pub fn code(&self) -> i32 {
23        self.raw_response.code
24    }
25
26    pub fn msg(&self) -> &str {
27        &self.raw_response.msg
28    }
29
30    pub fn err(&self) -> Option<&ErrorInfo> {
31        self.raw_response.err.as_ref()
32    }
33
34    /// 获取语义化的错误码
35    pub fn error_code(&self) -> Option<LarkErrorCode> {
36        LarkErrorCode::from_code(self.code())
37    }
38
39    /// 检查是否为特定错误码
40    pub fn is_error_code(&self, code: LarkErrorCode) -> bool {
41        self.code() == code as i32
42    }
43
44    /// 检查是否为权限相关错误
45    pub fn is_permission_error(&self) -> bool {
46        self.error_code()
47            .map(|c| c.is_permission_error())
48            .unwrap_or(false)
49    }
50
51    /// 检查是否为认证相关错误
52    pub fn is_auth_error(&self) -> bool {
53        self.error_code()
54            .map(|c| c.is_auth_error())
55            .unwrap_or(false)
56    }
57
58    /// 检查是否为服务器错误
59    pub fn is_server_error(&self) -> bool {
60        self.error_code()
61            .map(|c| c.is_server_error())
62            .unwrap_or(false)
63    }
64
65    /// 检查是否为客户端错误
66    pub fn is_client_error(&self) -> bool {
67        self.error_code()
68            .map(|c| c.is_client_error())
69            .unwrap_or(false)
70    }
71
72    /// 检查是否可以重试
73    pub fn is_retryable(&self) -> bool {
74        self.error_code().map(|c| c.is_retryable()).unwrap_or(false)
75    }
76
77    /// 获取建议的重试延迟时间
78    pub fn suggested_retry_delay(&self) -> Option<u64> {
79        self.error_code().and_then(|c| c.suggested_retry_delay())
80    }
81
82    /// 获取数据或返回友好错误
83    pub fn data_or_error(self) -> Result<T, String> {
84        if self.success() {
85            self.data.ok_or_else(|| "响应成功但数据为空".to_string())
86        } else {
87            let error_msg = if let Some(code) = self.error_code() {
88                code.detailed_description().to_string()
89            } else {
90                format!("{} (错误码: {})", self.msg(), self.code())
91            };
92            Err(error_msg)
93        }
94    }
95
96    /// 获取数据或转换为LarkAPIError
97    pub fn data_or_api_error(self) -> SDKResult<T> {
98        if self.success() {
99            self.data
100                .ok_or_else(|| LarkAPIError::api_error(0, "响应成功但数据为空", None))
101        } else {
102            Err(LarkAPIError::api_error(
103                self.code(),
104                self.msg(),
105                None, // FUTURE: 可从响应头中提取request_id以增强调试支持
106            ))
107        }
108    }
109
110    /// 处理通用错误,返回处理后的响应或错误
111    pub fn handle_common_errors(self) -> SDKResult<Self> {
112        if self.success() {
113            return Ok(self);
114        }
115
116        match self.error_code() {
117            Some(LarkErrorCode::AccessTokenInvalid) => Err(LarkAPIError::illegal_param(
118                "访问令牌已过期,请重新获取用户授权",
119            )),
120            Some(LarkErrorCode::AppAccessTokenInvalid) => Err(LarkAPIError::illegal_param(
121                "应用访问令牌无效,请检查应用配置",
122            )),
123            Some(LarkErrorCode::TenantAccessTokenInvalid) => Err(LarkAPIError::illegal_param(
124                "租户访问令牌无效,请检查应用权限",
125            )),
126            Some(LarkErrorCode::Forbidden) => Err(LarkAPIError::illegal_param(
127                "权限不足,请检查应用权限配置或用户权限",
128            )),
129            Some(LarkErrorCode::TooManyRequests) => {
130                Err(LarkAPIError::illegal_param("请求过于频繁,请稍后重试"))
131            }
132            Some(LarkErrorCode::NotFound) => Err(LarkAPIError::illegal_param("请求的资源不存在")),
133            _ => {
134                // 对于其他错误,返回原始响应让调用者处理
135                Ok(self)
136            }
137        }
138    }
139
140    /// 获取用户友好的错误描述
141    pub fn user_friendly_error(&self) -> Option<String> {
142        if self.success() {
143            return None;
144        }
145
146        Some(
147            self.error_code()
148                .map(|c| c.detailed_description().to_string())
149                .unwrap_or_else(|| format!("{} (错误码: {})", self.msg(), self.code())),
150        )
151    }
152
153    /// 获取错误的建议解决方案
154    pub fn error_solutions(&self) -> Vec<String> {
155        if self.success() {
156            return vec![];
157        }
158
159        match self.error_code() {
160            Some(LarkErrorCode::AccessTokenInvalid) => vec![
161                "重新获取用户访问令牌".to_string(),
162                "检查令牌是否在有效期内".to_string(),
163            ],
164            Some(LarkErrorCode::AppAccessTokenInvalid) => vec![
165                "检查应用ID和应用密钥".to_string(),
166                "确认应用类型配置正确".to_string(),
167            ],
168            Some(LarkErrorCode::TenantAccessTokenInvalid) => vec![
169                "检查租户权限配置".to_string(),
170                "确认应用已正确安装到企业".to_string(),
171            ],
172            Some(LarkErrorCode::Forbidden) => vec![
173                "检查应用权限范围设置".to_string(),
174                "确认用户具有相应的操作权限".to_string(),
175                "联系管理员添加必要权限".to_string(),
176            ],
177            Some(LarkErrorCode::TooManyRequests) => vec![
178                "降低请求频率".to_string(),
179                "实现请求重试机制".to_string(),
180                "考虑使用请求缓存".to_string(),
181            ],
182            Some(LarkErrorCode::NotFound) => vec![
183                "检查资源ID是否正确".to_string(),
184                "确认资源是否存在".to_string(),
185            ],
186            _ => vec![
187                "检查请求参数是否正确".to_string(),
188                "参考API文档确认调用方式".to_string(),
189            ],
190        }
191    }
192
193    /// 获取相关的帮助链接
194    pub fn help_links(&self) -> Vec<(&'static str, &'static str)> {
195        if self.success() {
196            return vec![];
197        }
198
199        match self.error_code() {
200            Some(code) => vec![
201                (
202                    "官方文档",
203                    code.help_url()
204                        .unwrap_or("https://open.feishu.cn/document/"),
205                ),
206                (
207                    "开发者社区",
208                    "https://getfeishu.cn/hc/zh-cn/categories/360000150856",
209                ),
210            ],
211            None => vec![
212                ("API文档", "https://open.feishu.cn/document/"),
213                (
214                    "开发者社区",
215                    "https://getfeishu.cn/hc/zh-cn/categories/360000150856",
216                ),
217            ],
218        }
219    }
220
221    /// 打印详细的错误信息(用于调试)
222    pub fn print_error_details(&self) {
223        if self.success() {
224            println!("✅ 请求成功");
225            return;
226        }
227
228        println!("❌ 请求失败");
229        println!("错误码: {}", self.code());
230
231        if let Some(error_code) = self.error_code() {
232            println!("错误类型: {}", error_code.description());
233            println!("详细说明: {}", error_code.detailed_description());
234        }
235
236        println!("错误消息: {}", self.msg());
237
238        let solutions = self.error_solutions();
239        if !solutions.is_empty() {
240            println!("\n💡 建议解决方案:");
241            for (i, solution) in solutions.iter().enumerate() {
242                println!("   {}. {}", i + 1, solution);
243            }
244        }
245
246        let help_links = self.help_links();
247        if !help_links.is_empty() {
248            println!("\n🔗 相关链接:");
249            for (name, url) in help_links {
250                println!("   {name}: {url}");
251            }
252        }
253
254        if let Some(delay) = self.suggested_retry_delay() {
255            println!("\n⏱️ 建议重试延迟: {delay}秒");
256        }
257    }
258}
259
260/// 业务返回值格式
261pub trait ApiResponseTrait: for<'a> Deserialize<'a> + Send + Sync + 'static + Debug {
262    /// 是否是标准数据格式, 既是用data包裹数据
263    fn data_format() -> ResponseFormat;
264
265    fn from_binary(_file_name: String, _body: Vec<u8>) -> Option<Self> {
266        None
267    }
268}
269
270/// 响应格式类型
271///
272/// 定义API响应的不同格式类型
273#[derive(Debug, PartialEq)]
274pub enum ResponseFormat {
275    /// 标准数据格式, 既是用data包裹数据
276    Data,
277    /// 扁平数据格式, 既是直接返回数据
278    Flatten,
279    /// 二进制数据格式
280    Binary,
281}
282
283#[derive(Serialize, Deserialize, Debug, Clone, Default)]
284pub struct RawResponse {
285    pub code: i32,
286    pub msg: String,
287    #[serde(rename = "error", default, skip_serializing_if = "Option::is_none")]
288    pub err: Option<ErrorInfo>,
289}
290
291impl ApiResponseTrait for RawResponse {
292    fn data_format() -> ResponseFormat {
293        ResponseFormat::Flatten
294    }
295}
296
297impl Display for RawResponse {
298    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
299        write!(f, "code: {}, msg: {}", self.code, self.msg)
300    }
301}
302
303/// 空响应体
304#[derive(Debug, Serialize, Deserialize)]
305pub struct EmptyResponse {}
306
307impl ApiResponseTrait for EmptyResponse {
308    fn data_format() -> ResponseFormat {
309        ResponseFormat::Data
310    }
311}
312
313/// JSON响应体
314pub type JsonResponse = serde_json::Value;
315
316impl ApiResponseTrait for JsonResponse {
317    fn data_format() -> ResponseFormat {
318        ResponseFormat::Data
319    }
320}
321
322/// 二进制数据响应体
323#[derive(Debug, Serialize, Deserialize)]
324pub struct BinaryResponse {
325    pub file_name: String,
326    pub body: Vec<u8>,
327}
328
329impl ApiResponseTrait for BinaryResponse {
330    fn data_format() -> ResponseFormat {
331        ResponseFormat::Binary
332    }
333
334    fn from_binary(file_name: String, body: Vec<u8>) -> Option<Self> {
335        Some(BinaryResponse { file_name, body })
336    }
337}
338
339#[derive(Serialize, Deserialize, Debug, Clone)]
340pub struct ErrorInfo {
341    #[serde(rename = "key", default, skip_serializing_if = "Option::is_none")]
342    pub log_id: Option<String>,
343    #[serde(rename = "details", default, skip_serializing_if = "Vec::is_empty")]
344    pub details: Vec<CodeErrorDetail>,
345    #[serde(
346        rename = "permission_violations",
347        default,
348        skip_serializing_if = "Vec::is_empty"
349    )]
350    pub permission_violations: Vec<CodeErrorPermissionViolation>,
351    #[serde(
352        rename = "field_violations",
353        default,
354        skip_serializing_if = "Vec::is_empty"
355    )]
356    pub field_violations: Vec<CodeErrorFieldViolation>,
357}
358
359#[derive(Serialize, Deserialize, Debug, Clone)]
360pub struct CodeErrorDetail {
361    #[serde(rename = "key", default, skip_serializing_if = "Option::is_none")]
362    pub key: Option<String>,
363    #[serde(rename = "value", default, skip_serializing_if = "Option::is_none")]
364    pub value: Option<String>,
365}
366
367#[derive(Serialize, Deserialize, Debug, Clone)]
368pub struct CodeErrorPermissionViolation {
369    #[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
370    pub type_: Option<String>,
371    #[serde(rename = "subject", default, skip_serializing_if = "Option::is_none")]
372    pub subject: Option<String>,
373    #[serde(
374        rename = "description",
375        default,
376        skip_serializing_if = "Option::is_none"
377    )]
378    pub description: Option<String>,
379}
380
381#[derive(Serialize, Deserialize, Debug, Clone)]
382pub struct CodeErrorFieldViolation {
383    #[serde(rename = "field", default, skip_serializing_if = "Option::is_none")]
384    pub field: Option<String>,
385    #[serde(rename = "value", default, skip_serializing_if = "Option::is_none")]
386    pub value: Option<String>,
387    #[serde(
388        rename = "description",
389        default,
390        skip_serializing_if = "Option::is_none"
391    )]
392    pub description: Option<String>,
393}
394
395#[cfg(test)]
396mod tests {
397    use super::*;
398    use serde_json;
399
400    // Helper function to create a test RawResponse
401    fn create_test_raw_response(code: i32, msg: &str) -> RawResponse {
402        RawResponse {
403            code,
404            msg: msg.to_string(),
405            err: None,
406        }
407    }
408
409    // Helper function to create a test BaseResponse
410    fn create_test_response<T>(code: i32, msg: &str, data: Option<T>) -> BaseResponse<T> {
411        BaseResponse {
412            raw_response: create_test_raw_response(code, msg),
413            data,
414        }
415    }
416
417    #[test]
418    fn test_base_response_success() {
419        let response: BaseResponse<String> =
420            create_test_response(0, "success", Some("test_data".to_string()));
421        assert!(response.success());
422
423        let error_response: BaseResponse<String> = create_test_response(1000, "error", None);
424        assert!(!error_response.success());
425    }
426
427    #[test]
428    fn test_base_response_code_and_msg() {
429        let response: BaseResponse<String> = create_test_response(1234, "test message", None);
430        assert_eq!(response.code(), 1234);
431        assert_eq!(response.msg(), "test message");
432    }
433
434    #[test]
435    fn test_base_response_data_or_error_success() {
436        let response: BaseResponse<String> =
437            create_test_response(0, "success", Some("test_data".to_string()));
438        let result = response.data_or_error();
439        assert!(result.is_ok());
440        assert_eq!(result.unwrap(), "test_data");
441    }
442
443    #[test]
444    fn test_base_response_data_or_error_success_but_no_data() {
445        let response: BaseResponse<String> = create_test_response(0, "success", None);
446        let result = response.data_or_error();
447        assert!(result.is_err());
448        assert_eq!(result.unwrap_err(), "响应成功但数据为空");
449    }
450
451    #[test]
452    fn test_base_response_data_or_error_failure() {
453        let response: BaseResponse<String> = create_test_response(1000, "API error", None);
454        let result = response.data_or_error();
455        assert!(result.is_err());
456        let error_msg = result.unwrap_err();
457        assert!(error_msg.contains("API error"));
458        assert!(error_msg.contains("1000"));
459    }
460
461    #[test]
462    fn test_base_response_data_or_api_error_success() {
463        let response: BaseResponse<String> =
464            create_test_response(0, "success", Some("test_data".to_string()));
465        let result = response.data_or_api_error();
466        assert!(result.is_ok());
467        assert_eq!(result.unwrap(), "test_data");
468    }
469
470    #[test]
471    fn test_base_response_data_or_api_error_failure() {
472        let response: BaseResponse<String> = create_test_response(1000, "API error", None);
473        let result = response.data_or_api_error();
474        assert!(result.is_err());
475
476        match result.unwrap_err() {
477            LarkAPIError::ApiError { code, message, .. } => {
478                assert_eq!(code, 1000);
479                assert_eq!(message, "API error");
480            }
481            _ => panic!("Expected ApiError"),
482        }
483    }
484
485    #[test]
486    fn test_base_response_handle_common_errors_success() {
487        let response: BaseResponse<String> =
488            create_test_response(0, "success", Some("test_data".to_string()));
489        let result = response.handle_common_errors();
490        assert!(result.is_ok());
491    }
492
493    #[test]
494    fn test_base_response_user_friendly_error_success() {
495        let response: BaseResponse<String> =
496            create_test_response(0, "success", Some("test_data".to_string()));
497        assert!(response.user_friendly_error().is_none());
498    }
499
500    #[test]
501    fn test_base_response_user_friendly_error_failure() {
502        let response: BaseResponse<String> = create_test_response(1000, "API error", None);
503        let error = response.user_friendly_error();
504        assert!(error.is_some());
505        assert!(error.unwrap().contains("API error"));
506    }
507
508    #[test]
509    fn test_base_response_error_solutions_success() {
510        let response: BaseResponse<String> =
511            create_test_response(0, "success", Some("test_data".to_string()));
512        assert!(response.error_solutions().is_empty());
513    }
514
515    #[test]
516    fn test_base_response_error_solutions_failure() {
517        let response: BaseResponse<String> = create_test_response(1000, "API error", None);
518        let solutions = response.error_solutions();
519        assert!(!solutions.is_empty());
520        assert!(solutions.contains(&"检查请求参数是否正确".to_string()));
521    }
522
523    #[test]
524    fn test_base_response_help_links_success() {
525        let response: BaseResponse<String> =
526            create_test_response(0, "success", Some("test_data".to_string()));
527        assert!(response.help_links().is_empty());
528    }
529
530    #[test]
531    fn test_base_response_help_links_failure() {
532        let response: BaseResponse<String> = create_test_response(1000, "API error", None);
533        let links = response.help_links();
534        assert!(!links.is_empty());
535        assert!(links.iter().any(|(name, _)| name.contains("API文档")));
536    }
537
538    #[test]
539    fn test_base_response_print_error_details() {
540        let response: BaseResponse<String> =
541            create_test_response(0, "success", Some("test_data".to_string()));
542        // Test that print_error_details doesn't panic
543        response.print_error_details();
544
545        let error_response: BaseResponse<String> = create_test_response(1000, "API error", None);
546        error_response.print_error_details();
547    }
548
549    #[test]
550    fn test_raw_response_serialization() {
551        let raw_resp = RawResponse {
552            code: 1000,
553            msg: "test error".to_string(),
554            err: None,
555        };
556
557        let json = serde_json::to_string(&raw_resp).unwrap();
558        assert!(json.contains("1000"));
559        assert!(json.contains("test error"));
560
561        let deserialized: RawResponse = serde_json::from_str(&json).unwrap();
562        assert_eq!(deserialized.code, 1000);
563        assert_eq!(deserialized.msg, "test error");
564    }
565
566    #[test]
567    fn test_raw_response_display() {
568        let raw_resp = RawResponse {
569            code: 1234,
570            msg: "display test".to_string(),
571            err: None,
572        };
573
574        let display_str = format!("{}", raw_resp);
575        assert!(display_str.contains("1234"));
576        assert!(display_str.contains("display test"));
577    }
578
579    #[test]
580    fn test_raw_response_data_format() {
581        assert!(matches!(
582            RawResponse::data_format(),
583            ResponseFormat::Flatten
584        ));
585    }
586
587    #[test]
588    fn test_raw_response_debug() {
589        let raw_resp = RawResponse {
590            code: 500,
591            msg: "debug test".to_string(),
592            err: None,
593        };
594
595        let debug_str = format!("{:?}", raw_resp);
596        assert!(debug_str.contains("RawResponse"));
597        assert!(debug_str.contains("500"));
598        assert!(debug_str.contains("debug test"));
599    }
600
601    #[test]
602    fn test_raw_response_clone() {
603        let raw_resp = RawResponse {
604            code: 200,
605            msg: "clone test".to_string(),
606            err: None,
607        };
608
609        let cloned = raw_resp.clone();
610        assert_eq!(raw_resp.code, cloned.code);
611        assert_eq!(raw_resp.msg, cloned.msg);
612    }
613
614    #[test]
615    fn test_raw_response_default() {
616        let default_resp = RawResponse::default();
617        assert_eq!(default_resp.code, 0);
618        assert!(default_resp.msg.is_empty());
619        assert!(default_resp.err.is_none());
620    }
621
622    #[test]
623    fn test_empty_response_data_format() {
624        assert!(matches!(EmptyResponse::data_format(), ResponseFormat::Data));
625    }
626
627    #[test]
628    fn test_empty_response_serialization() {
629        let empty_resp = EmptyResponse {};
630        let json = serde_json::to_string(&empty_resp).unwrap();
631        assert_eq!(json, "{}");
632
633        let deserialized: EmptyResponse = serde_json::from_str("{}").unwrap();
634        let _ = deserialized; // Just ensure it deserializes without error
635    }
636
637    #[test]
638    fn test_empty_response_debug() {
639        let empty_resp = EmptyResponse {};
640        let debug_str = format!("{:?}", empty_resp);
641        assert!(debug_str.contains("EmptyResponse"));
642    }
643
644    #[test]
645    fn test_json_response_data_format() {
646        assert!(matches!(JsonResponse::data_format(), ResponseFormat::Data));
647    }
648
649    #[test]
650    fn test_binary_response_data_format() {
651        assert!(matches!(
652            BinaryResponse::data_format(),
653            ResponseFormat::Binary
654        ));
655    }
656
657    #[test]
658    fn test_binary_response_from_binary() {
659        let file_name = "test.pdf".to_string();
660        let body = vec![1, 2, 3, 4, 5];
661
662        let binary_resp = BinaryResponse::from_binary(file_name.clone(), body.clone());
663        assert!(binary_resp.is_some());
664
665        let resp = binary_resp.unwrap();
666        assert_eq!(resp.file_name, file_name);
667        assert_eq!(resp.body, body);
668    }
669
670    #[test]
671    fn test_binary_response_serialization() {
672        let binary_resp = BinaryResponse {
673            file_name: "test_file.txt".to_string(),
674            body: vec![72, 101, 108, 108, 111], // "Hello" in bytes
675        };
676
677        let json = serde_json::to_string(&binary_resp).unwrap();
678        assert!(json.contains("test_file.txt"));
679
680        let deserialized: BinaryResponse = serde_json::from_str(&json).unwrap();
681        assert_eq!(deserialized.file_name, "test_file.txt");
682        assert_eq!(deserialized.body, vec![72, 101, 108, 108, 111]);
683    }
684
685    #[test]
686    fn test_binary_response_debug() {
687        let binary_resp = BinaryResponse {
688            file_name: "debug_file.bin".to_string(),
689            body: vec![255, 254, 253],
690        };
691
692        let debug_str = format!("{:?}", binary_resp);
693        assert!(debug_str.contains("BinaryResponse"));
694        assert!(debug_str.contains("debug_file.bin"));
695    }
696
697    #[test]
698    fn test_error_info_serialization() {
699        let error_info = ErrorInfo {
700            log_id: Some("test_log_id".to_string()),
701            details: vec![],
702            permission_violations: vec![],
703            field_violations: vec![],
704        };
705
706        let json = serde_json::to_string(&error_info).unwrap();
707        assert!(json.contains("test_log_id"));
708
709        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
710        assert_eq!(deserialized.log_id, Some("test_log_id".to_string()));
711    }
712
713    #[test]
714    fn test_error_info_with_details() {
715        let error_detail = CodeErrorDetail {
716            key: Some("param_name".to_string()),
717            value: Some("invalid_value".to_string()),
718        };
719
720        let error_info = ErrorInfo {
721            log_id: Some("log_123".to_string()),
722            details: vec![error_detail],
723            permission_violations: vec![],
724            field_violations: vec![],
725        };
726
727        let json = serde_json::to_string(&error_info).unwrap();
728        assert!(json.contains("param_name"));
729        assert!(json.contains("invalid_value"));
730
731        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
732        assert_eq!(deserialized.details.len(), 1);
733        assert_eq!(deserialized.details[0].key, Some("param_name".to_string()));
734    }
735
736    #[test]
737    fn test_error_info_with_permission_violations() {
738        let permission_violation = CodeErrorPermissionViolation {
739            type_: Some("SCOPE_REQUIRED".to_string()),
740            subject: Some("read:user".to_string()),
741            description: Some("Missing required permission".to_string()),
742        };
743
744        let error_info = ErrorInfo {
745            log_id: None,
746            details: vec![],
747            permission_violations: vec![permission_violation],
748            field_violations: vec![],
749        };
750
751        let json = serde_json::to_string(&error_info).unwrap();
752        assert!(json.contains("SCOPE_REQUIRED"));
753        assert!(json.contains("read:user"));
754
755        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
756        assert_eq!(deserialized.permission_violations.len(), 1);
757        assert_eq!(
758            deserialized.permission_violations[0].type_,
759            Some("SCOPE_REQUIRED".to_string())
760        );
761    }
762
763    #[test]
764    fn test_error_info_with_field_violations() {
765        let field_violation = CodeErrorFieldViolation {
766            field: Some("email".to_string()),
767            value: Some("invalid-email".to_string()),
768            description: Some("Invalid email format".to_string()),
769        };
770
771        let error_info = ErrorInfo {
772            log_id: None,
773            details: vec![],
774            permission_violations: vec![],
775            field_violations: vec![field_violation],
776        };
777
778        let json = serde_json::to_string(&error_info).unwrap();
779        assert!(json.contains("email"));
780        assert!(json.contains("Invalid email format"));
781
782        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
783        assert_eq!(deserialized.field_violations.len(), 1);
784        assert_eq!(
785            deserialized.field_violations[0].field,
786            Some("email".to_string())
787        );
788    }
789
790    #[test]
791    fn test_error_info_debug() {
792        let error_info = ErrorInfo {
793            log_id: Some("debug_log".to_string()),
794            details: vec![],
795            permission_violations: vec![],
796            field_violations: vec![],
797        };
798
799        let debug_str = format!("{:?}", error_info);
800        assert!(debug_str.contains("ErrorInfo"));
801        assert!(debug_str.contains("debug_log"));
802    }
803
804    #[test]
805    fn test_error_info_clone() {
806        let error_info = ErrorInfo {
807            log_id: Some("clone_test".to_string()),
808            details: vec![],
809            permission_violations: vec![],
810            field_violations: vec![],
811        };
812
813        let cloned = error_info.clone();
814        assert_eq!(error_info.log_id, cloned.log_id);
815        assert_eq!(error_info.details.len(), cloned.details.len());
816    }
817
818    #[test]
819    fn test_code_error_detail_serialization() {
820        let detail = CodeErrorDetail {
821            key: Some("test_key".to_string()),
822            value: Some("test_value".to_string()),
823        };
824
825        let json = serde_json::to_string(&detail).unwrap();
826        assert!(json.contains("test_key"));
827        assert!(json.contains("test_value"));
828
829        let deserialized: CodeErrorDetail = serde_json::from_str(&json).unwrap();
830        assert_eq!(deserialized.key, Some("test_key".to_string()));
831        assert_eq!(deserialized.value, Some("test_value".to_string()));
832    }
833
834    #[test]
835    fn test_code_error_detail_with_none_values() {
836        let detail = CodeErrorDetail {
837            key: None,
838            value: None,
839        };
840
841        let json = serde_json::to_string(&detail).unwrap();
842        // Should serialize to empty object or minimal JSON
843        assert!(json == "{}" || json.len() < 10);
844
845        let deserialized: CodeErrorDetail = serde_json::from_str(&json).unwrap();
846        assert_eq!(deserialized.key, None);
847        assert_eq!(deserialized.value, None);
848    }
849
850    #[test]
851    fn test_base_response_serialization() {
852        let response = BaseResponse {
853            raw_response: RawResponse {
854                code: 0,
855                msg: "success".to_string(),
856                err: None,
857            },
858            data: Some("test_data".to_string()),
859        };
860
861        let json = serde_json::to_string(&response).unwrap();
862        assert!(json.contains("success"));
863        assert!(json.contains("test_data"));
864
865        let deserialized: BaseResponse<String> = serde_json::from_str(&json).unwrap();
866        assert_eq!(deserialized.raw_response.code, 0);
867        assert_eq!(deserialized.data, Some("test_data".to_string()));
868    }
869
870    #[test]
871    fn test_base_response_debug() {
872        let response: BaseResponse<String> =
873            create_test_response(200, "OK", Some("debug_data".to_string()));
874        let debug_str = format!("{:?}", response);
875        assert!(debug_str.contains("BaseResponse"));
876        assert!(debug_str.contains("debug_data"));
877    }
878
879    #[test]
880    fn test_base_response_with_error_info() {
881        let mut raw_resp = create_test_raw_response(400, "Bad Request");
882        raw_resp.err = Some(ErrorInfo {
883            log_id: Some("error_log_123".to_string()),
884            details: vec![],
885            permission_violations: vec![],
886            field_violations: vec![],
887        });
888
889        let response: BaseResponse<String> = BaseResponse {
890            raw_response: raw_resp,
891            data: None,
892        };
893
894        assert!(!response.success());
895        assert_eq!(response.code(), 400);
896        assert!(response.err().is_some());
897        assert_eq!(
898            response.err().unwrap().log_id,
899            Some("error_log_123".to_string())
900        );
901    }
902
903    #[test]
904    fn test_response_format_enum() {
905        // Test that ResponseFormat variants can be created
906        let _data_format = ResponseFormat::Data;
907        let _flatten_format = ResponseFormat::Flatten;
908        let _binary_format = ResponseFormat::Binary;
909    }
910
911    #[test]
912    fn test_multiple_error_types() {
913        let error_info = ErrorInfo {
914            log_id: Some("multi_error_log".to_string()),
915            details: vec![
916                CodeErrorDetail {
917                    key: Some("detail1".to_string()),
918                    value: Some("value1".to_string()),
919                },
920                CodeErrorDetail {
921                    key: Some("detail2".to_string()),
922                    value: Some("value2".to_string()),
923                },
924            ],
925            permission_violations: vec![CodeErrorPermissionViolation {
926                type_: Some("PERMISSION_DENIED".to_string()),
927                subject: Some("user:123".to_string()),
928                description: Some("User lacks permission".to_string()),
929            }],
930            field_violations: vec![CodeErrorFieldViolation {
931                field: Some("username".to_string()),
932                value: Some("".to_string()),
933                description: Some("Username cannot be empty".to_string()),
934            }],
935        };
936
937        let json = serde_json::to_string(&error_info).unwrap();
938        let deserialized: ErrorInfo = serde_json::from_str(&json).unwrap();
939
940        assert_eq!(deserialized.details.len(), 2);
941        assert_eq!(deserialized.permission_violations.len(), 1);
942        assert_eq!(deserialized.field_violations.len(), 1);
943        assert_eq!(deserialized.log_id, Some("multi_error_log".to_string()));
944    }
945
946    #[test]
947    fn test_base_response_memory_efficiency() {
948        // Test creating many BaseResponse instances doesn't consume excessive memory
949        let responses: Vec<BaseResponse<i32>> = (0..100)
950            .map(|i| create_test_response(0, "success", Some(i)))
951            .collect();
952
953        assert_eq!(responses.len(), 100);
954
955        // Verify each response has correct data
956        for (i, response) in responses.iter().enumerate() {
957            assert!(response.success());
958            assert_eq!(response.data, Some(i as i32));
959        }
960    }
961}