1use std::fmt::{Debug, Display, Formatter};
2
3use serde::{Deserialize, Serialize};
4
5use crate::core::{error::LarkAPIError, error_codes::LarkErrorCode, SDKResult};
6
7#[derive(Debug, Serialize, Deserialize)]
9pub struct BaseResponse<T> {
10 #[serde(flatten)]
12 pub raw_response: RawResponse,
13 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 pub fn error_code(&self) -> Option<LarkErrorCode> {
36 LarkErrorCode::from_code(self.code())
37 }
38
39 pub fn is_error_code(&self, code: LarkErrorCode) -> bool {
41 self.code() == code as i32
42 }
43
44 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 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 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 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 pub fn is_retryable(&self) -> bool {
74 self.error_code().map(|c| c.is_retryable()).unwrap_or(false)
75 }
76
77 pub fn suggested_retry_delay(&self) -> Option<u64> {
79 self.error_code().and_then(|c| c.suggested_retry_delay())
80 }
81
82 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 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, ))
107 }
108 }
109
110 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 Ok(self)
136 }
137 }
138 }
139
140 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 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 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 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
260pub trait ApiResponseTrait: for<'a> Deserialize<'a> + Send + Sync + 'static + Debug {
262 fn data_format() -> ResponseFormat;
264
265 fn from_binary(_file_name: String, _body: Vec<u8>) -> Option<Self> {
266 None
267 }
268}
269
270#[derive(Debug, PartialEq)]
274pub enum ResponseFormat {
275 Data,
277 Flatten,
279 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#[derive(Debug, Serialize, Deserialize)]
305pub struct EmptyResponse {}
306
307impl ApiResponseTrait for EmptyResponse {
308 fn data_format() -> ResponseFormat {
309 ResponseFormat::Data
310 }
311}
312
313pub type JsonResponse = serde_json::Value;
315
316impl ApiResponseTrait for JsonResponse {
317 fn data_format() -> ResponseFormat {
318 ResponseFormat::Data
319 }
320}
321
322#[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 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 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 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; }
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], };
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 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 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 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 for (i, response) in responses.iter().enumerate() {
957 assert!(response.success());
958 assert_eq!(response.data, Some(i as i32));
959 }
960 }
961}