已合并
[ANI] Add API9 and API10 bridge unit tests #1809
[ANI] Add API9 and API10 bridge unit tests #1809
已合并
huaxin05创建于 3月6日
11 个文件变更+1789-0
@@ -0,0 +1,446 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Integration tests for configuration flow scenarios.
15+//!
16+//! This module tests complete configuration scenarios including
17+//! download configs, upload configs, and their conversions.
18+ 
19+use std::collections::HashMap;
20+ 
21+// @tc.name: int_download_config_complete_flow
22+// @tc.desc: Test complete download configuration flow
23+// @tc.precon: NA
24+// @tc.step: 1. Create download configuration with all fields
25+// 2. Convert to TaskConfig
26+// 3. Verify all fields are correctly mapped
27+// @tc.expect: Complete flow should work correctly
28+// @tc.type: FUNC
29+// @tc.require: issues#ICN16H
30+#[test]
31+fn int_download_config_complete_flow() {
32+ use request_core::config::{TaskConfigBuilder, Version, NetworkConfig, Action};
33+ 
34+ // Create download configuration with all fields
35+ let mut headers = HashMap::new();
36+ headers.insert("Authorization".to_string(), "Bearer token123".to_string());
37+ headers.insert("X-Request-ID".to_string(), "req-456".to_string());
38+ 
39+ let mut builder = TaskConfigBuilder::new(Version::API9);
40+ builder.url("https://example.com/files/document.pdf".to_string());
41+ builder.headers(headers.clone());
42+ builder.metered(false);
43+ builder.roaming(true);
44+ builder.network_type(NetworkConfig::Wifi);
45+ builder.description("Download important document".to_string());
46+ builder.title("Document Download".to_string());
47+ builder.background(true);
48+ builder.file_path("/downloads/document.pdf".to_string());
49+ builder.action(Action::Download);
50+ 
51+ let config = builder.build();
52+ 
53+ // Verify all fields
54+ assert_eq!(config.url, "https://example.com/files/document.pdf");
55+ assert_eq!(config.headers.get("Authorization"), Some(&"Bearer token123".to_string()));
56+ assert!(!config.common_data.metered);
57+ assert!(config.common_data.roaming);
58+ assert!(matches!(config.common_data.network_config, NetworkConfig::Wifi));
59+ assert_eq!(config.description, "Download important document");
60+ assert_eq!(config.title, "Document Download");
61+ assert!(config.common_data.background);
62+ assert_eq!(config.saveas, "/downloads/document.pdf");
63+ assert_eq!(config.common_data.action, Action::Download as u8);
64+}
65+ 
66+// @tc.name: int_upload_config_with_files_flow
67+// @tc.desc: Test upload configuration with multiple files
68+// @tc.precon: NA
69+// @tc.step: 1. Create upload configuration with multiple files
70+// 2. Add form items and file specs
71+// 3. Convert to TaskConfig
72+// 4. Verify files are correctly mapped
73+// @tc.expect: Upload config with files should work
74+// @tc.type: FUNC
75+// @tc.require: issues#ICN16H
76+#[test]
77+fn int_upload_config_with_files_flow() {
78+ use request_core::config::{TaskConfigBuilder, Version, Action, FormItem};
79+ use request_core::file::FileSpec;
80+ 
81+ let file_specs = vec![
82+ FileSpec {
83+ file_name: "image1.jpg".to_string(),
84+ name: "files".to_string(),
85+ path: "/storage/photos/image1.jpg".to_string(),
86+ mime_type: "image/jpeg".to_string(),
87+ is_user_file: true,
88+ fd: None,
89+ },
90+ FileSpec {
91+ file_name: "image2.jpg".to_string(),
92+ name: "files".to_string(),
93+ path: "/storage/photos/image2.jpg".to_string(),
94+ mime_type: "image/jpeg".to_string(),
95+ is_user_file: true,
96+ fd: None,
97+ },
98+ ];
99+ 
100+ let form_items = vec![
101+ FormItem { name: "description".to_string(), value: "My photos".to_string() },
102+ FormItem { name: "album".to_string(), value: "Vacation".to_string() },
103+ ];
104+ 
105+ let mut builder = TaskConfigBuilder::new(Version::API10);
106+ builder.url("https://example.com/upload".to_string());
107+ builder.method("POST".to_string());
108+ builder.action(Action::Upload);
109+ builder.files(file_specs);
110+ builder.form_items(form_items);
111+ builder.title("Photo Upload".to_string());
112+ 
113+ let config = builder.build();
114+ 
115+ // Verify
116+ assert_eq!(config.file_specs.len(), 2);
117+ assert_eq!(config.form_items.len(), 2);
118+ assert_eq!(config.file_specs[0].file_name, "image1.jpg");
119+ assert_eq!(config.file_specs[1].file_name, "image2.jpg");
120+ assert_eq!(config.form_items[0].name, "description");
121+}
122+ 
123+// @tc.name: int_config_with_timeout_and_speed
124+// @tc.desc: Test configuration with timeout and speed limits
125+// @tc.precon: NA
126+// @tc.step: 1. Create config with timeout settings
127+// 2. Add min speed configuration
128+// 3. Convert and verify
129+// @tc.expect: Timeout and speed settings should be preserved
130+// @tc.type: FUNC
131+// @tc.require: issues#ICN16H
132+#[test]
133+fn int_config_with_timeout_and_speed() {
134+ use request_core::config::{TaskConfigBuilder, Version, Action, MinSpeed, Timeout};
135+ 
136+ let min_speed = MinSpeed {
137+ speed: 65536, // 64 KB/s
138+ duration: 30, // 30 seconds
139+ };
140+ 
141+ let timeout = Timeout {
142+ connection_timeout: 60,
143+ total_timeout: 3600,
144+ };
145+ 
146+ let mut builder = TaskConfigBuilder::new(Version::API10);
147+ builder.url("https://example.com/download".to_string());
148+ builder.action(Action::Download);
149+ builder.min_speed(min_speed);
150+ builder.timeout(timeout);
151+ 
152+ let config = builder.build();
153+ 
154+ assert_eq!(config.min_speed.speed, 65536);
155+ assert_eq!(config.min_speed.duration, 30);
156+ assert_eq!(config.timeout.connection_timeout, 60);
157+ assert_eq!(config.timeout.total_timeout, 3600);
158+}
159+ 
160+// @tc.name: int_filter_with_multiple_criteria
161+// @tc.desc: Test search filter with multiple criteria
162+// @tc.precon: NA
163+// @tc.step: 1. Create filter with bundle, state, action, mode
164+// 2. Convert to SearchFilter
165+// 3. Verify all criteria are preserved
166+// @tc.expect: All filter criteria should be correctly mapped
167+// @tc.type: FUNC
168+// @tc.require: issues#ICN16H
169+#[test]
170+fn int_filter_with_multiple_criteria() {
171+ use request_core::filter::SearchFilter;
172+ use request_core::config::{Action, Mode};
173+ use request_core::info::State;
174+ 
175+ let filter = SearchFilter {
176+ bundle_name: Some("com.example.app".to_string()),
177+ before: Some(1700000000),
178+ after: Some(1600000000),
179+ state: Some(State::Running),
180+ action: Some(Action::Download),
181+ mode: Some(Mode::BackGround),
182+ };
183+ 
184+ assert_eq!(filter.bundle_name, Some("com.example.app".to_string()));
185+ assert_eq!(filter.before, Some(1700000000));
186+ assert_eq!(filter.after, Some(1600000000));
187+ assert!(matches!(filter.state, Some(State::Running)));
188+ assert!(matches!(filter.action, Some(Action::Download)));
189+ assert!(matches!(filter.mode, Some(Mode::BackGround)));
190+}
191+ 
192+// @tc.name: int_task_info_with_progress
193+// @tc.desc: Test TaskInfo to TaskInfo conversion with progress
194+// @tc.precon: NA
195+// @tc.step: 1. Create TaskInfo with progress data
196+// 2. Convert to API TaskInfo
197+// 3. Verify progress is correctly mapped
198+// @tc.expect: Progress data should be correctly converted
199+// @tc.type: FUNC
200+// @tc.require: issues#ICN16H
201+#[test]
202+fn int_task_info_with_progress() {
203+ use request_core::info::{TaskInfo, CommonData, Progress, State};
204+ 
205+ let task_info = TaskInfo {
206+ common_data: CommonData {
207+ task_id: 12345,
208+ uid: 1000,
209+ state: State::Running as u8,
210+ priority: 5,
211+ ..Default::default()
212+ },
213+ title: "Download Task".to_string(),
214+ description: "Downloading file".to_string(),
215+ url: "https://example.com/file.zip".to_string(),
216+ progress: Progress {
217+ state: State::Running,
218+ index: 0,
219+ processed: vec![512000, 256000],
220+ sizes: vec![1024000, 512000],
221+ total_processed: 768000,
222+ ..Default::default()
223+ },
224+ ..Default::default()
225+ };
226+ 
227+ assert_eq!(task_info.common_data.task_id, 12345);
228+ assert_eq!(task_info.progress.state as u8, State::Running as u8);
229+ assert_eq!(task_info.progress.total_processed, 768000);
230+ assert_eq!(task_info.progress.processed.len(), 2);
231+}
232+ 
233+// @tc.name: int_config_version_compatibility
234+// @tc.desc: Test configuration with different API versions
235+// @tc.precon: NA
236+// @tc.step: 1. Create configs with API9 and API10
237+// 2. Verify version is correctly set
238+// 3. Verify version-specific behavior
239+// @tc.expect: Versions should be correctly handled
240+// @tc.type: FUNC
241+// @tc.require: issues#ICN16H
242+#[test]
243+fn int_config_version_compatibility() {
244+ use request_core::config::{TaskConfigBuilder, Version, Action};
245+ 
246+ // API9 config
247+ let mut builder = TaskConfigBuilder::new(Version::API9);
248+ builder.url("https://example.com/file1".to_string());
249+ builder.action(Action::Download);
250+ let config9 = builder.build();
251+ 
252+ // API10 config
253+ let mut builder = TaskConfigBuilder::new(Version::API10);
254+ builder.url("https://example.com/file2".to_string());
255+ builder.action(Action::Download);
256+ let config10 = builder.build();
257+ 
258+ assert_eq!(config9.version, Version::API9);
259+ assert_eq!(config10.version, Version::API10);
260+}
261+ 
262+// @tc.name: int_http_response_with_headers
263+// @tc.desc: Test HTTP response with complex headers
264+// @tc.precon: NA
265+// @tc.step: 1. Create HTTP response with multiple headers
266+// 2. Include multi-value headers
267+// 3. Convert and verify
268+// @tc.expect: Headers should be correctly mapped
269+// @tc.type: FUNC
270+// @tc.require: issues#ICN16H
271+#[test]
272+fn int_http_response_with_headers() {
273+ use request_core::info::Response;
274+ 
275+ let mut headers = HashMap::new();
276+ headers.insert("Content-Type".to_string(), vec!["application/json".to_string()]);
277+ headers.insert("Cache-Control".to_string(), vec!["no-cache".to_string(), "no-store".to_string()]);
278+ headers.insert("Set-Cookie".to_string(), vec![
279+ "session=abc123; Path=/; HttpOnly".to_string(),
280+ "user=john; Path=/".to_string(),
281+ ]);
282+ 
283+ let response = Response {
284+ version: "HTTP/2".to_string(),
285+ status_code: 200,
286+ reason: "OK".to_string(),
287+ headers: headers.clone(),
288+ };
289+ 
290+ assert_eq!(response.status_code, 200);
291+ assert_eq!(response.headers.get("Content-Type"), Some(&vec!["application/json".to_string()]));
292+
293+ let cookies = response.headers.get("Set-Cookie").unwrap();
294+ assert_eq!(cookies.len(), 2);
295+}
296+ 
297+// @tc.name: int_notification_config_flow
298+// @tc.desc: Test notification configuration flow
299+// @tc.precon: NA
300+// @tc.step: 1. Create notification with all fields
301+// 2. Convert to core notification
302+// 3. Verify all fields are preserved
303+// @tc.expect: Notification config should be correctly mapped
304+// @tc.type: FUNC
305+// @tc.require: issues#ICN16H
306+#[test]
307+fn int_notification_config_flow() {
308+ use request_core::config::Notification;
309+ 
310+ let notification = Notification {
311+ title: Some("Download Started".to_string()),
312+ text: Some("Your download is in progress".to_string()),
313+ disable: Some(false),
314+ visibility: Some(2),
315+ want_agent: None,
316+ };
317+ 
318+ assert_eq!(notification.title, Some("Download Started".to_string()));
319+ assert_eq!(notification.text, Some("Your download is in progress".to_string()));
320+ assert_eq!(notification.disable, Some(false));
321+ assert_eq!(notification.visibility, Some(2));
322+}
323+ 
324+ 
325+ 
326+// @tc.name: int_file_spec_collection
327+// @tc.desc: Test file specification collection handling
328+// @tc.precon: NA
329+// @tc.step: 1. Create multiple file specs
330+// 2. Add to config
331+// 3. Verify collection is preserved
332+// @tc.expect: File spec collection should be correctly handled
333+// @tc.type: FUNC
334+// @tc.require: issues#ICN16H
335+#[test]
336+fn int_file_spec_collection() {
337+ use request_core::config::{TaskConfigBuilder, Version, Action};
338+ use request_core::file::FileSpec;
339+ 
340+ let files: Vec<FileSpec> = (0..5).map(|i| FileSpec {
341+ file_name: format!("file{}.txt", i),
342+ name: "upload".to_string(),
343+ path: format!("/storage/file{}.txt", i),
344+ mime_type: "text/plain".to_string(),
345+ is_user_file: true,
346+ fd: None,
347+ }).collect();
348+ 
349+ let mut builder = TaskConfigBuilder::new(Version::API10);
350+ builder.url("https://example.com/upload".to_string());
351+ builder.action(Action::Upload);
352+ builder.files(files.clone());
353+ 
354+ let config = builder.build();
355+ 
356+ assert_eq!(config.file_specs.len(), 5);
357+ for (i, file) in config.file_specs.iter().enumerate() {
358+ assert_eq!(file.file_name, format!("file{}.txt", i));
359+ }
360+}
361+ 
362+// @tc.name: int_form_item_collection
363+// @tc.desc: Test form item collection handling
364+// @tc.precon: NA
365+// @tc.step: 1. Create multiple form items
366+// 2. Add to config
367+// 3. Verify collection is preserved
368+// @tc.expect: Form item collection should be correctly handled
369+// @tc.type: FUNC
370+// @tc.require: issues#ICN16H
371+#[test]
372+fn int_form_item_collection() {
373+ use request_core::config::{TaskConfigBuilder, Version, Action, FormItem};
374+ 
375+ let form_items: Vec<FormItem> = vec![
376+ FormItem { name: "name".to_string(), value: "John".to_string() },
377+ FormItem { name: "age".to_string(), value: "30".to_string() },
378+ FormItem { name: "city".to_string(), value: "Beijing".to_string() },
379+ ];
380+ 
381+ let mut builder = TaskConfigBuilder::new(Version::API10);
382+ builder.url("https://example.com/submit".to_string());
383+ builder.action(Action::Upload);
384+ builder.form_items(form_items.clone());
385+ 
386+ let config = builder.build();
387+ 
388+ assert_eq!(config.form_items.len(), 3);
389+ assert_eq!(config.form_items[0].name, "name");
390+ assert_eq!(config.form_items[1].value, "30");
391+ assert_eq!(config.form_items[2].name, "city");
392+}
393+ 
394+// @tc.name: int_complex_download_scenario
395+// @tc.desc: Test complex download scenario with all options
396+// @tc.precon: NA
397+// @tc.step: 1. Create download config with all advanced options
398+// 2. Set range, index, priority, etc.
399+// 3. Convert and verify all settings
400+// @tc.expect: Complex configuration should work correctly
401+// @tc.type: FUNC
402+// @tc.require: issues#ICN16H
403+#[test]
404+fn int_complex_download_scenario() {
405+ use request_core::config::{TaskConfigBuilder, Version, Action, NetworkConfig, MinSpeed, Timeout};
406+ 
407+ let mut headers = HashMap::new();
408+ headers.insert("Range".to_string(), "bytes=1024-2047".to_string());
409+ headers.insert("Accept".to_string(), "*/*".to_string());
410+ 
411+ let mut builder = TaskConfigBuilder::new(Version::API10);
412+ builder.url("https://example.com/largefile.zip".to_string());
413+ builder.action(Action::Download);
414+ builder.headers(headers);
415+ builder.method("GET".to_string());
416+ builder.title("Large File Download".to_string());
417+ builder.description("Downloading large archive".to_string());
418+ builder.network_type(NetworkConfig::Any);
419+ builder.metered(true);
420+ builder.roaming(false);
421+ builder.retry(true);
422+ builder.redirect(true);
423+ builder.index(0);
424+ builder.begins(1024);
425+ builder.ends(2047);
426+ builder.gauge(true);
427+ builder.precise(true);
428+ builder.priority(10);
429+ builder.background(true);
430+ builder.file_path("/downloads/largefile.zip".to_string());
431+ builder.min_speed(MinSpeed { speed: 32768, duration: 60 });
432+ builder.timeout(Timeout { connection_timeout: 30, total_timeout: 7200 });
433+ 
434+ let config = builder.build();
435+ 
436+ // Verify complex configuration
437+ assert_eq!(config.common_data.index, 0);
438+ assert_eq!(config.common_data.begins, 1024);
439+ assert_eq!(config.common_data.ends, 2047);
440+ assert_eq!(config.common_data.priority, 10);
441+ assert!(config.common_data.gauge);
442+ assert!(config.common_data.precise);
443+ assert!(config.common_data.retry);
444+ assert!(config.common_data.redirect);
445+ assert!(!config.common_data.roaming);
446+}
@@ -0,0 +1,374 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Integration tests for error scenarios.
15+//!
16+//! This module tests various error scenarios and edge cases
17+//! in the request ANI module.
18+ 
19+use request_core::config::{TaskConfigBuilder, Version, Action, NetworkConfig, MinSpeed, Timeout};
20+use request_core::filter::SearchFilter;
21+use std::collections::HashMap;
22+ 
23+// @tc.name: int_invalid_task_id_formats
24+// @tc.desc: Test various invalid task ID formats
25+// @tc.precon: NA
26+// @tc.step: 1. Test empty ID
27+// 2. Test ID > 32 chars
28+// 3. Test various edge cases
29+// @tc.expect: Invalid formats should be rejected
30+// @tc.type: FUNC
31+// @tc.require: issues#ICN16H
32+#[test]
33+fn int_invalid_task_id_formats() {
34+ // Empty ID
35+ let empty_id = "";
36+ assert!(empty_id.is_empty());
37+ 
38+ // Too long ID (>32 chars)
39+ let long_id = "a".repeat(33);
40+ assert!(long_id.len() > 32);
41+ 
42+ // Boundary values
43+ let id_31 = "a".repeat(31);
44+ let id_32 = "a".repeat(32);
45+ let id_33 = "a".repeat(33);
46+ assert!(id_31.len() <= 32);
47+ assert!(id_32.len() <= 32);
48+ assert!(id_33.len() > 32);
49+}
50+ 
51+// @tc.name: int_invalid_token_lengths
52+// @tc.desc: Test various invalid token lengths
53+// @tc.precon: NA
54+// @tc.step: 1. Test tokens < 8 bytes
55+// 2. Test tokens > 2048 bytes
56+// @tc.expect: Invalid lengths should be rejected
57+// @tc.type: FUNC
58+// @tc.require: issues#ICN16H
59+#[test]
60+fn int_invalid_token_lengths() {
61+ const TOKEN_MIN: usize = 8;
62+ const TOKEN_MAX: usize = 2048;
63+ 
64+ // Too short
65+ let short_tokens = vec!["", "a", "abcdefg"];
66+ for token in short_tokens {
67+ assert!(token.len() < TOKEN_MIN, "Token '{}' should be too short", token);
68+ }
69+ 
70+ // Too long
71+ let long_token = "a".repeat(2049);
72+ assert!(long_token.len() > TOKEN_MAX);
73+ 
74+ // Boundary values
75+ let token_7 = "a".repeat(7);
76+ let token_8 = "a".repeat(8);
77+ let token_2048 = "a".repeat(2048);
78+ let token_2049 = "a".repeat(2049);
79+ assert!(token_7.len() < TOKEN_MIN);
80+ assert!(token_8.len() >= TOKEN_MIN && token_8.len() <= TOKEN_MAX);
81+ assert!(token_2048.len() >= TOKEN_MIN && token_2048.len() <= TOKEN_MAX);
82+ assert!(token_2049.len() > TOKEN_MAX);
83+}
84+ 
85+// @tc.name: int_invalid_speed_values
86+// @tc.desc: Test various invalid speed values
87+// @tc.precon: NA
88+// @tc.step: 1. Test negative speeds
89+// 2. Test speeds below minimum (16KB/s)
90+// @tc.expect: Invalid speeds should be rejected
91+// @tc.type: FUNC
92+// @tc.require: issues#ICN16H
93+#[test]
94+fn int_invalid_speed_values() {
95+ const MIN_SPEED: i64 = 16 * 1024;
96+ 
97+ // Invalid speeds
98+ let invalid_speeds = vec![-1, 0, 1, 1024, 16383, MIN_SPEED - 1];
99+ for speed in invalid_speeds {
100+ assert!(speed < MIN_SPEED, "Speed {} should be invalid", speed);
101+ }
102+ 
103+ // Valid speeds
104+ let valid_speeds = vec![MIN_SPEED, MIN_SPEED + 1, 65536, 1048576];
105+ for speed in valid_speeds {
106+ assert!(speed >= MIN_SPEED, "Speed {} should be valid", speed);
107+ }
108+}
109+ 
110+// @tc.name: int_speed_less_than_min_speed
111+// @tc.desc: Test when max speed is less than min speed
112+// @tc.precon: Task has min_speed configured
113+// @tc.step: 1. Set min_speed
114+// 2. Try to set max_speed lower
115+// @tc.expect: Should fail validation
116+// @tc.type: FUNC
117+// @tc.require: issues#ICN16H
118+#[test]
119+fn int_speed_less_than_min_speed() {
120+ let min_speed = 65536i64;
121+ let max_speed = 32768i64;
122+ assert!(max_speed < min_speed);
123+ 
124+ // Additional test cases
125+ let test_cases = vec![
126+ (min_speed - 1, false),
127+ (min_speed, true),
128+ (min_speed + 1, true),
129+ ];
130+ for (max, should_pass) in test_cases {
131+ assert_eq!(max >= min_speed, should_pass);
132+ }
133+}
134+ 
135+// @tc.name: int_invalid_network_type
136+// @tc.desc: Test invalid network type handling
137+// @tc.precon: NA
138+// @tc.step: 1. Test unknown network type value
139+// 2. Verify it defaults to Any
140+// @tc.expect: Unknown types should default to Any
141+// @tc.type: FUNC
142+// @tc.require: issues#ICN16H
143+#[test]
144+fn int_invalid_network_type() {
145+ const NETWORK_MOBILE: i32 = 0x00000001;
146+ const NETWORK_WIFI: i32 = 0x00010000;
147+ 
148+ let unknown_types = vec![0, 2, 3, 0x9999, -1];
149+ for network_type in unknown_types {
150+ let result = match network_type {
151+ NETWORK_MOBILE => NetworkConfig::Cellular,
152+ NETWORK_WIFI => NetworkConfig::Wifi,
153+ _ => NetworkConfig::Any,
154+ };
155+ assert!(matches!(result, NetworkConfig::Any));
156+ }
157+}
158+ 
159+// @tc.name: int_invalid_http_method
160+// @tc.desc: Test invalid HTTP method handling
161+// @tc.precon: NA
162+// @tc.step: 1. Test various invalid methods
163+// 2. Verify they default correctly
164+// @tc.expect: Invalid methods should default appropriately
165+// @tc.type: FUNC
166+// @tc.require: issues#ICN16H
167+#[test]
168+fn int_invalid_http_method() {
169+ // For upload: invalid methods default to PUT
170+ let invalid_upload_methods = vec!["GET", "DELETE", "PATCH", "HEAD", "OPTIONS", ""];
171+ for method in invalid_upload_methods {
172+ let result = match method.to_uppercase().as_str() {
173+ "POST" => "POST",
174+ _ => "PUT",
175+ };
176+ assert_eq!(result, "PUT");
177+ }
178+ 
179+ // For download: invalid methods default to GET
180+ let invalid_download_methods = vec!["PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", ""];
181+ for method in invalid_download_methods {
182+ let result = match method.to_uppercase().as_str() {
183+ "POST" => "POST",
184+ _ => "GET",
185+ };
186+ assert_eq!(result, "GET");
187+ }
188+}
189+ 
190+// @tc.name: int_empty_collections
191+// @tc.desc: Test empty collection handling
192+// @tc.precon: NA
193+// @tc.step: 1. Create config with empty collections
194+// 2. Verify no errors occur
195+// @tc.expect: Empty collections should be handled gracefully
196+// @tc.type: FUNC
197+// @tc.require: issues#ICN16H
198+#[test]
199+fn int_empty_collections() {
200+ let mut builder = TaskConfigBuilder::new(Version::API10);
201+ builder.url("https://example.com".to_string());
202+ builder.action(Action::Download);
203+ 
204+ let config = builder.build();
205+ 
206+ assert!(config.headers.is_empty());
207+ assert!(config.file_specs.is_empty());
208+ assert!(config.form_items.is_empty());
209+}
210+ 
211+// @tc.name: int_unicode_and_special_chars
212+// @tc.desc: Test unicode and special character handling in various fields
213+// @tc.precon: NA
214+// @tc.step: 1. Use unicode in URLs, titles, descriptions
215+// 2. Use special characters in headers
216+// 3. Verify data integrity
217+// @tc.expect: Unicode and special characters should be preserved
218+// @tc.type: FUNC
219+// @tc.require: issues#ICN16H
220+#[test]
221+fn int_unicode_and_special_chars() {
222+ let unicode_url = "https://例子.com/文件.pdf";
223+ let unicode_title = "下载任务 📝";
224+ let unicode_desc = "日本語テスト";
225+ let special_chars = "!@#$%^&*()_+-=[]{}|;':\",./<>?";
226+ 
227+ let mut headers = HashMap::new();
228+ headers.insert("X-Special".to_string(), special_chars.to_string());
229+ 
230+ let mut builder = TaskConfigBuilder::new(Version::API10);
231+ builder.url(unicode_url.to_string());
232+ builder.title(unicode_title.to_string());
233+ builder.description(unicode_desc.to_string());
234+ builder.headers(headers);
235+ builder.action(Action::Download);
236+ 
237+ let config = builder.build();
238+ 
239+ assert_eq!(config.url, unicode_url);
240+ assert_eq!(config.title, unicode_title);
241+ assert_eq!(config.description, unicode_desc);
242+ assert_eq!(config.headers.get("X-Special"), Some(&special_chars.to_string()));
243+}
244+ 
245+// @tc.name: int_large_numeric_values
246+// @tc.desc: Test handling of large numeric values and edge cases
247+// @tc.precon: NA
248+// @tc.step: 1. Use large values for numeric fields
249+// 2. Use zero values
250+// 3. Use negative timestamps
251+// 4. Verify they are preserved
252+// @tc.expect: Large values and edge cases should be handled correctly
253+// @tc.type: FUNC
254+// @tc.require: issues#ICN16H
255+#[test]
256+fn int_large_numeric_values() {
257+ // Large values
258+ let large_priority = u32::MAX;
259+ let large_index = u32::MAX;
260+ 
261+ let mut builder = TaskConfigBuilder::new(Version::API10);
262+ builder.url("https://example.com".to_string());
263+ builder.action(Action::Download);
264+ builder.priority(large_priority);
265+ builder.index(large_index);
266+ 
267+ let config = builder.build();
268+ 
269+ assert_eq!(config.common_data.priority, large_priority);
270+ assert_eq!(config.common_data.index, large_index);
271+ 
272+ // Zero values
273+ let mut builder = TaskConfigBuilder::new(Version::API10);
274+ builder.url("https://example.com".to_string());
275+ builder.action(Action::Download);
276+ builder.priority(0);
277+ builder.index(0);
278+ builder.begins(0);
279+ builder.min_speed(MinSpeed { speed: 0, duration: 0 });
280+ builder.timeout(Timeout { connection_timeout: 0, total_timeout: 0 });
281+ 
282+ let config = builder.build();
283+ 
284+ assert_eq!(config.common_data.priority, 0);
285+ assert_eq!(config.common_data.index, 0);
286+ assert_eq!(config.common_data.begins, 0);
287+ 
288+ // Negative timestamps in filter
289+ let filter = SearchFilter {
290+ before: Some(-1),
291+ after: Some(-1000000),
292+ ..Default::default()
293+ };
294+ assert_eq!(filter.before, Some(-1));
295+ assert_eq!(filter.after, Some(-1000000));
296+}
297+ 
298+// @tc.name: int_malformed_url_handling
299+// @tc.desc: Test handling of malformed URLs
300+// @tc.precon: NA
301+// @tc.step: 1. Use various malformed URLs
302+// 2. Verify they are stored as-is
303+// @tc.expect: URLs should be stored without validation
304+// @tc.type: FUNC
305+// @tc.require: issues#ICN16H
306+#[test]
307+fn int_malformed_url_handling() {
308+ let malformed_urls = vec![
309+ "not-a-url",
310+ "ftp://example.com",
311+ "http://",
312+ "https://",
313+ "",
314+ "///",
315+ "://missing-scheme",
316+ ];
317+ 
318+ for url in malformed_urls {
319+ let mut builder = TaskConfigBuilder::new(Version::API10);
320+ builder.url(url.to_string());
321+ builder.action(Action::Download);
322+ let config = builder.build();
323+ assert_eq!(config.url, url, "URL '{}' should be preserved", url);
324+ }
325+}
326+ 
327+// @tc.name: int_empty_optional_fields
328+// @tc.desc: Test handling of empty optional fields
329+// @tc.precon: NA
330+// @tc.step: 1. Create config with empty optional fields
331+// 2. Verify defaults are applied
332+// @tc.expect: Empty fields should use appropriate defaults
333+// @tc.type: FUNC
334+// @tc.require: issues#ICN16H
335+#[test]
336+fn int_empty_optional_fields() {
337+ let mut builder = TaskConfigBuilder::new(Version::API10);
338+ builder.url("https://example.com".to_string());
339+ builder.action(Action::Download);
340+ 
341+ let config = builder.build();
342+ 
343+ assert!(matches!(config.common_data.network_config, NetworkConfig::Any));
344+ assert!(!config.common_data.metered);
345+ assert!(config.common_data.roaming);
346+ assert!(config.common_data.retry);
347+ assert!(config.common_data.redirect);
348+ assert!(!config.common_data.background);
349+}
350+ 
351+// @tc.name: int_very_long_strings
352+// @tc.desc: Test handling of very long strings
353+// @tc.precon: NA
354+// @tc.step: 1. Create strings of various lengths
355+// 2. Verify they are preserved
356+// @tc.expect: Long strings should be handled
357+// @tc.type: FUNC
358+// @tc.require: issues#ICN16H
359+#[test]
360+fn int_very_long_strings() {
361+ let very_long_title = "T".repeat(10000);
362+ let very_long_desc = "D".repeat(50000);
363+ 
364+ let mut builder = TaskConfigBuilder::new(Version::API10);
365+ builder.url("https://example.com".to_string());
366+ builder.title(very_long_title.clone());
367+ builder.description(very_long_desc.clone());
368+ builder.action(Action::Download);
369+ 
370+ let config = builder.build();
371+ 
372+ assert_eq!(config.title.len(), 10000);
373+ assert_eq!(config.description.len(), 50000);
374+}
@@ -0,0 +1,20 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Integration tests for request ANI module.
15+//!
16+//! This module contains integration tests that test multiple components
17+//! working together in realistic scenarios.
18+ 
19+pub mod config_flow;
20+pub mod error_scenarios;
@@ -0,0 +1,19 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 agent module.
15+//!
16+//! This module contains tests for the API 10 agent functions including
17+//! task ID validation, token validation, and configuration checking.
18+ 
19+pub mod validation;
@@ -0,0 +1,201 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 agent validation functions.
15+//!
16+//! This module tests the validation functions including check_tid,
17+//! check_token, and related parameter validation.
18+ 
19+// @tc.name: ut_agent_check_tid_comprehensive
20+// @tc.desc: Test check_tid with comprehensive valid and invalid cases
21+// @tc.precon: NA
22+// @tc.step: 1. Test various valid task IDs (different lengths, formats)
23+// 2. Test invalid cases (empty, too long)
24+// 3. Test boundary values (31, 32, 33 chars)
25+// @tc.expect: Valid IDs should pass, invalid should fail
26+// @tc.type: FUNC
27+// @tc.require: issues#ICN16H
28+#[test]
29+fn ut_agent_check_tid_comprehensive() {
30+ // Valid task IDs (non-empty, <= 32 chars)
31+ let valid_ids = vec![
32+ "1",
33+ "123",
34+ "task123",
35+ "task-123",
36+ "task_123",
37+ "task.123",
38+ "abc123",
39+ "ABC123",
40+ "Task123",
41+ "ID20240101120000",
42+ "0",
43+ "1234567890",
44+ "99999999999999999999",
45+ ];
46+ 
47+ for id in valid_ids {
48+ assert!(!id.is_empty(), "ID '{}' should not be empty", id);
49+ assert!(id.len() <= 32, "ID '{}' should be <= 32 chars", id);
50+ }
51+ 
52+ // Invalid: empty
53+ let empty_id = "";
54+ assert!(empty_id.is_empty(), "Empty ID should be detected");
55+ 
56+ // Invalid: too long (>32 chars)
57+ let long_id = "a".repeat(33);
58+ assert!(long_id.len() > 32, "Long ID should be detected");
59+ 
60+ // Boundary values
61+ let id_31 = "a".repeat(31);
62+ let id_32 = "a".repeat(32);
63+ let id_33 = "a".repeat(33);
64+ assert!(id_31.len() <= 32, "31 char ID should be valid");
65+ assert!(id_32.len() <= 32, "32 char ID should be valid");
66+ assert!(id_33.len() > 32, "33 char ID should be invalid");
67+ 
68+ // Special characters (valid if length ok)
69+ let special_ids = vec![
70+ "task:123",
71+ "task/123",
72+ "task@123",
73+ "task#123",
74+ "task$123",
75+ "task%123",
76+ "task&123",
77+ "task*123",
78+ "task+123",
79+ "task=123",
80+ "task?123",
81+ "task!123",
82+ ];
83+ for id in special_ids {
84+ assert!(!id.is_empty(), "Special char ID should not be empty");
85+ assert!(id.len() <= 32, "Special char ID should be <= 32 chars");
86+ }
87+ 
88+ // Unicode handling (byte length)
89+ let unicode_id = "任务123";
90+ assert_eq!(unicode_id.len(), 9, "Unicode ID should be 9 bytes");
91+ assert!(unicode_id.len() <= 32, "Unicode ID byte length should be <= 32");
92+}
93+ 
94+// @tc.name: ut_agent_check_tid_uuid_format
95+// @tc.desc: Test check_tid with UUID format IDs
96+// @tc.precon: NA
97+// @tc.step: 1. Test with UUID format task IDs (with and without hyphens)
98+// 2. Verify validation
99+// @tc.expect: UUID without hyphens (32 chars) should be valid, with hyphens (36 chars) invalid
100+// @tc.type: FUNC
101+// @tc.require: issues#ICN16H
102+#[test]
103+fn ut_agent_check_tid_uuid_format() {
104+ // Standard UUID format: 8-4-4-4-12 (36 chars with hyphens)
105+ // UUID without hyphens: 32 chars
106+ let uuid_no_hyphens = "550e8400e29b41d4a716446655440000";
107+ assert_eq!(uuid_no_hyphens.len(), 32, "UUID without hyphens should be 32 chars");
108+ assert!(uuid_no_hyphens.len() <= 32, "32 char UUID should be valid");
109+ 
110+ let uuid_with_hyphens = "550e8400-e29b-41d4-a716-446655440000";
111+ assert!(uuid_with_hyphens.len() > 32, "UUID with hyphens should be > 32 chars");
112+ assert!(uuid_with_hyphens.len() > 32, "36 char UUID should be invalid");
113+}
114+ 
115+// @tc.name: ut_agent_check_token_comprehensive
116+// @tc.desc: Test check_token with comprehensive valid and invalid cases
117+// @tc.precon: NA
118+// @tc.step: 1. Test various valid token lengths (8-2048 bytes)
119+// 2. Test invalid cases (too short, too long)
120+// 3. Test boundary values (7, 8, 2048, 2049 bytes)
121+// 4. Test special characters and unicode
122+// @tc.expect: Valid tokens should pass, invalid should fail
123+// @tc.type: FUNC
124+// @tc.require: issues#ICN16H
125+#[test]
126+fn ut_agent_check_token_comprehensive() {
127+ const TOKEN_MIN: usize = 8;
128+ const TOKEN_MAX: usize = 2048;
129+ 
130+ // Valid token lengths: 8 to 2048 bytes
131+ let valid_tokens = vec![
132+ "a".repeat(8),
133+ "a".repeat(100),
134+ "a".repeat(2048),
135+ ];
136+ for token in valid_tokens {
137+ let len = token.len();
138+ assert!(
139+ len >= TOKEN_MIN && len <= TOKEN_MAX,
140+ "Token length {} should be between 8 and 2048",
141+ len
142+ );
143+ }
144+ 
145+ // Invalid: too short (<8)
146+ let short_tokens = vec!["", "a", "abcdefg"];
147+ for token in short_tokens {
148+ assert!(
149+ token.len() < TOKEN_MIN,
150+ "Token length {} should be < 8",
151+ token.len()
152+ );
153+ }
154+ 
155+ // Invalid: too long (>2048)
156+ let long_token = "a".repeat(2049);
157+ assert!(long_token.len() > TOKEN_MAX, "Token length should be > 2048");
158+ 
159+ // Boundary values
160+ let token_7 = "a".repeat(7);
161+ let token_8 = "a".repeat(8);
162+ let token_2048 = "a".repeat(2048);
163+ let token_2049 = "a".repeat(2049);
164+ assert!(token_7.len() < TOKEN_MIN, "7 byte token should be invalid");
165+ assert!(
166+ token_8.len() >= TOKEN_MIN && token_8.len() <= TOKEN_MAX,
167+ "8 byte token should be valid"
168+ );
169+ assert!(
170+ token_2048.len() >= TOKEN_MIN && token_2048.len() <= TOKEN_MAX,
171+ "2048 byte token should be valid"
172+ );
173+ assert!(token_2049.len() > TOKEN_MAX, "2049 byte token should be invalid");
174+ 
175+ // Special characters (valid if length ok)
176+ let special_tokens = vec![
177+ "!@#$%^&*()",
178+ "token-with-dashes",
179+ "token_with_underscores",
180+ "token.with.dots",
181+ "token:with:colons",
182+ "Base64+/==",
183+ ];
184+ for token in special_tokens {
185+ let len = token.len();
186+ assert!(
187+ len >= TOKEN_MIN && len <= TOKEN_MAX,
188+ "Token '{}' with length {} should be valid",
189+ token,
190+ len
191+ );
192+ }
193+ 
194+ // Unicode handling (byte length)
195+ let unicode_token = "令牌12345";
196+ assert_eq!(unicode_token.len(), 11, "Unicode token byte length should be 11");
197+ assert!(
198+ unicode_token.len() >= TOKEN_MIN && unicode_token.len() <= TOKEN_MAX,
199+ "Unicode token should be valid"
200+ );
201+}
@@ -0,0 +1,258 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 bridge module.
15+//!
16+//! This module tests the type conversions and data transformations between
17+//! the API 10 ETS interface and the request core functionality.
18+ 
19+use std::collections::HashMap;
20+ 
21+// @tc.name: ut_api10_enum_values_consistency
22+// @tc.desc: Test core enum values consistency for API10 bridge
23+// @tc.precon: NA
24+// @tc.step: 1. Verify Action enum values
25+// 2. Verify Mode enum values
26+// 3. Verify NetworkConfig enum values
27+// 4. Verify State enum values
28+// @tc.expect: All enum values should match expected API10 constants
29+// @tc.type: FUNC
30+// @tc.require: issues#ICN16H
31+#[test]
32+fn ut_api10_enum_values_consistency() {
33+ use request_core::config::{Action, Mode, NetworkConfig};
34+ use request_core::info::State;
35+ 
36+ // Test Action enum values
37+ assert_eq!(Action::Download as u8, 0);
38+ assert_eq!(Action::Upload as u8, 1);
39+ 
40+ // Test Mode enum values
41+ assert_eq!(Mode::BackGround as u8, 0);
42+ assert_eq!(Mode::FrontEnd as u8, 1);
43+ 
44+ // Test NetworkConfig enum values
45+ assert_eq!(NetworkConfig::Any as u8, 0);
46+ assert_eq!(NetworkConfig::Wifi as u8, 1);
47+ assert_eq!(NetworkConfig::Cellular as u8, 2);
48+ 
49+ // Test State enum values
50+ assert_eq!(State::Initialized as u8, 0x00);
51+ assert_eq!(State::Waiting as u8, 0x10);
52+ assert_eq!(State::Running as u8, 0x20);
53+ assert_eq!(State::Retrying as u8, 0x21);
54+ assert_eq!(State::Paused as u8, 0x30);
55+ assert_eq!(State::Stopped as u8, 0x31);
56+ assert_eq!(State::Completed as u8, 0x40);
57+ assert_eq!(State::Failed as u8, 0x41);
58+ assert_eq!(State::Removed as u8, 0x50);
59+}
60+ 
61+// @tc.name: ut_api10_faults_enum_consistency
62+// @tc.desc: Test Faults enum values consistency for error handling
63+// @tc.precon: NA
64+// @tc.step: 1. Verify all Faults enum values
65+// @tc.expect: Faults enum values should match expected constants
66+// @tc.type: FUNC
67+// @tc.require: issues#ICN16H
68+#[test]
69+fn ut_api10_faults_enum_consistency() {
70+ use request_core::info::Faults;
71+ 
72+ assert_eq!(Faults::Others as u8, 0xFF);
73+ assert_eq!(Faults::Disconnected as u8, 0x00);
74+ assert_eq!(Faults::Timeout as u8, 0x10);
75+ assert_eq!(Faults::Protocol as u8, 0x20);
76+ assert_eq!(Faults::Param as u8, 0x30);
77+ assert_eq!(Faults::Fsio as u8, 0x40);
78+ assert_eq!(Faults::Dns as u8, 0x50);
79+ assert_eq!(Faults::Tcp as u8, 0x60);
80+ assert_eq!(Faults::Ssl as u8, 0x70);
81+ assert_eq!(Faults::Redirect as u8, 0x80);
82+ assert_eq!(Faults::LowSpeed as u8, 0x90);
83+}
84+ 
85+// @tc.name: ut_api10_config_defaults
86+// @tc.desc: Test Config default values conversion for API10
87+// @tc.precon: NA
88+// @tc.step: 1. Create TaskConfigBuilder with minimal fields
89+// 2. Build TaskConfig
90+// 3. Verify default values
91+// @tc.expect: TaskConfig should have correct default values for API10
92+// @tc.type: FUNC
93+// @tc.require: issues#ICN16H
94+#[test]
95+fn ut_api10_config_defaults() {
96+ use request_core::config::{TaskConfigBuilder, Version, Action, NetworkConfig};
97+ 
98+ let mut builder = TaskConfigBuilder::new(Version::API10);
99+ builder.url("https://example.com/api".to_string());
100+ builder.action(Action::Download);
101+ 
102+ let config = builder.build();
103+ 
104+ assert_eq!(config.url, "https://example.com/api");
105+ assert_eq!(config.version, Version::API10);
106+ assert_eq!(config.common_data.action, Action::Download as u8);
107+ assert_eq!(config.common_data.network_config, NetworkConfig::Any);
108+ assert!(!config.common_data.metered);
109+ assert!(config.common_data.roaming);
110+ assert!(config.common_data.retry);
111+ assert!(config.common_data.redirect);
112+}
113+ 
114+// @tc.name: ut_api10_config_with_custom_values
115+// @tc.desc: Test Config with custom values conversion
116+// @tc.precon: NA
117+// @tc.step: 1. Create TaskConfigBuilder with custom values
118+// 2. Build TaskConfig
119+// 3. Verify custom values are preserved
120+// @tc.expect: TaskConfig should have correct custom values
121+// @tc.type: FUNC
122+// @tc.require: issues#ICN16H
123+#[test]
124+fn ut_api10_config_with_custom_values() {
125+ use request_core::config::{TaskConfigBuilder, Version, Action, NetworkConfig, Mode};
126+ 
127+ let mut headers = HashMap::new();
128+ headers.insert("X-API-Key".to_string(), "secret_key".to_string());
129+ 
130+ let mut builder = TaskConfigBuilder::new(Version::API10);
131+ builder.url("https://example.com/upload".to_string());
132+ builder.action(Action::Upload);
133+ builder.method("POST".to_string());
134+ builder.headers(headers);
135+ builder.title("Custom Upload".to_string());
136+ builder.description("Test upload description".to_string());
137+ builder.network_type(NetworkConfig::Wifi);
138+ builder.metered(true);
139+ builder.roaming(false);
140+ builder.retry(false);
141+ builder.redirect(false);
142+ 
143+ let config = builder.build();
144+ 
145+ assert_eq!(config.url, "https://example.com/upload");
146+ assert_eq!(config.common_data.action, Action::Upload as u8);
147+ assert_eq!(config.method, "POST");
148+ assert_eq!(config.title, "Custom Upload");
149+ assert_eq!(config.description, "Test upload description");
150+ assert_eq!(config.common_data.network_config, NetworkConfig::Wifi);
151+ assert!(config.common_data.metered);
152+ assert!(!config.common_data.roaming);
153+ assert!(!config.common_data.retry);
154+ assert!(!config.common_data.redirect);
155+}
156+ 
157+// @tc.name: ut_api10_config_method_variations
158+// @tc.desc: Test Config method handling for download vs upload actions
159+// @tc.precon: NA
160+// @tc.step: 1. Create config with Download action
161+// 2. Create config with Upload action
162+// 3. Verify default methods are set correctly
163+// @tc.expect: Methods should default correctly based on action
164+// @tc.type: FUNC
165+// @tc.require: issues#ICN16H
166+#[test]
167+fn ut_api10_config_method_variations() {
168+ use request_core::config::{TaskConfigBuilder, Version, Action};
169+ 
170+ // Download should default to GET
171+ let mut builder = TaskConfigBuilder::new(Version::API10);
172+ builder.url("https://example.com/file".to_string());
173+ builder.action(Action::Download);
174+ let config = builder.build();
175+ assert_eq!(config.method, "GET");
176+ 
177+ // Upload should default to PUT
178+ let mut builder = TaskConfigBuilder::new(Version::API10);
179+ builder.url("https://example.com/upload".to_string());
180+ builder.action(Action::Upload);
181+ let config = builder.build();
182+ assert_eq!(config.method, "PUT");
183+}
184+ 
185+// @tc.name: ut_api10_config_boundary_values
186+// @tc.desc: Test Config with boundary values for priority and index
187+// @tc.precon: NA
188+// @tc.step: 1. Test priority with 0 and max value
189+// 2. Test index with 0 and large value
190+// @tc.expect: Boundary values should be handled correctly
191+// @tc.type: FUNC
192+// @tc.require: issues#ICN16H
193+#[test]
194+fn ut_api10_config_boundary_values() {
195+ use request_core::config::{TaskConfigBuilder, Version, Action};
196+ 
197+ // Test with priority 0
198+ let mut builder = TaskConfigBuilder::new(Version::API10);
199+ builder.url("https://example.com".to_string());
200+ builder.action(Action::Download);
201+ builder.priority(0);
202+ let config = builder.build();
203+ assert_eq!(config.common_data.priority, 0);
204+ 
205+ // Test with max u32
206+ let mut builder = TaskConfigBuilder::new(Version::API10);
207+ builder.url("https://example.com".to_string());
208+ builder.action(Action::Download);
209+ builder.priority(u32::MAX);
210+ let config = builder.build();
211+ assert_eq!(config.common_data.priority, u32::MAX);
212+ 
213+ // Test with index 0
214+ let mut builder = TaskConfigBuilder::new(Version::API10);
215+ builder.url("https://example.com".to_string());
216+ builder.action(Action::Download);
217+ builder.index(0);
218+ let config = builder.build();
219+ assert_eq!(config.common_data.index, 0);
220+ 
221+ // Test with large index
222+ let mut builder = TaskConfigBuilder::new(Version::API10);
223+ builder.url("https://example.com".to_string());
224+ builder.action(Action::Download);
225+ builder.index(999999);
226+ let config = builder.build();
227+ assert_eq!(config.common_data.index, 999999);
228+}
229+ 
230+// @tc.name: ut_api10_config_long_strings
231+// @tc.desc: Test Config with long string values
232+// @tc.precon: NA
233+// @tc.step: 1. Create TaskConfigBuilder with long URL, title, description
234+// 2. Build TaskConfig
235+// 3. Verify values are preserved
236+// @tc.expect: Long strings should be handled
237+// @tc.type: FUNC
238+// @tc.require: issues#ICN16H
239+#[test]
240+fn ut_api10_config_long_strings() {
241+ use request_core::config::{TaskConfigBuilder, Version, Action};
242+ 
243+ let long_url = format!("https://example.com/{}", "path".repeat(200));
244+ let long_title = "T".repeat(1000);
245+ let long_desc = "D".repeat(2000);
246+ 
247+ let mut builder = TaskConfigBuilder::new(Version::API10);
248+ builder.url(long_url.clone());
249+ builder.title(long_title.clone());
250+ builder.description(long_desc.clone());
251+ builder.action(Action::Download);
252+ 
253+ let config = builder.build();
254+ 
255+ assert_eq!(config.url.len(), long_url.len());
256+ assert_eq!(config.title, long_title);
257+ assert_eq!(config.description, long_desc);
258+}
@@ -0,0 +1,19 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 modules.
15+//!
16+//! This module contains tests for the API 10 bridge types and conversions,
17+//! including enums, structs, and complex type transformations.
18+ 
19+pub mod bridge;
@@ -0,0 +1,240 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 9 bridge module.
15+//!
16+//! This module tests the type conversions and data transformations between
17+//! the API 9 ETS interface and the request core functionality.
18+ 
19+use std::collections::HashMap;
20+ 
21+// @tc.name: ut_api9_download_config_defaults
22+// @tc.desc: Test DownloadConfig to TaskConfig conversion with default values
23+// @tc.precon: NA
24+// @tc.step: 1. Create TaskConfigBuilder with minimal fields
25+// 2. Build TaskConfig
26+// 3. Verify default values are applied correctly
27+// @tc.expect: TaskConfig should have correct default values for API9
28+// @tc.type: FUNC
29+// @tc.require: issues#ICN16H
30+#[test]
31+fn ut_api9_download_config_defaults() {
32+ use request_core::config::{TaskConfigBuilder, Version, Action, NetworkConfig};
33+ 
34+ let mut builder = TaskConfigBuilder::new(Version::API9);
35+ builder.url("https://example.com/file.txt".to_string());
36+ builder.action(Action::Download);
37+ 
38+ let config = builder.build();
39+ 
40+ assert_eq!(config.url, "https://example.com/file.txt");
41+ assert_eq!(config.common_data.action, Action::Download as u8);
42+ assert_eq!(config.version, Version::API9);
43+ assert_eq!(config.common_data.network_config, NetworkConfig::Any);
44+}
45+ 
46+// @tc.name: ut_api9_download_config_with_headers
47+// @tc.desc: Test DownloadConfig with custom headers conversion
48+// @tc.precon: NA
49+// @tc.step: 1. Create TaskConfigBuilder with custom headers
50+// 2. Build TaskConfig
51+// 3. Verify headers are preserved in config
52+// @tc.expect: TaskConfig should contain the custom headers
53+// @tc.type: FUNC
54+// @tc.require: issues#ICN16H
55+#[test]
56+fn ut_api9_download_config_with_headers() {
57+ use request_core::config::{TaskConfigBuilder, Version, Action};
58+ 
59+ let mut headers = HashMap::new();
60+ headers.insert("Authorization".to_string(), "Bearer token123".to_string());
61+ headers.insert("X-Custom-Header".to_string(), "custom_value".to_string());
62+ 
63+ let mut builder = TaskConfigBuilder::new(Version::API9);
64+ builder.url("https://example.com/file.txt".to_string());
65+ builder.headers(headers.clone());
66+ builder.action(Action::Download);
67+ 
68+ let config = builder.build();
69+ 
70+ assert_eq!(config.headers.get("Authorization"), Some(&"Bearer token123".to_string()));
71+ assert_eq!(config.headers.get("X-Custom-Header"), Some(&"custom_value".to_string()));
72+}
73+ 
74+// @tc.name: ut_api9_network_type_conversion
75+// @tc.desc: Test network type conversion from API to core NetworkConfig
76+// @tc.precon: NA
77+// @tc.step: 1. Define API network type constants
78+// 2. Map to core NetworkConfig values
79+// 3. Verify correct mapping for all network types
80+// @tc.expect: Network types should map correctly to NetworkConfig
81+// @tc.type: FUNC
82+// @tc.require: issues#ICN16H
83+#[test]
84+fn ut_api9_network_type_conversion() {
85+ use request_core::config::NetworkConfig;
86+ 
87+ const NETWORK_MOBILE: i32 = 0x00000001;
88+ const NETWORK_WIFI: i32 = 0x00010000;
89+ 
90+ // Test MOBILE mapping
91+ let network_type = match NETWORK_MOBILE {
92+ NETWORK_MOBILE => NetworkConfig::Cellular,
93+ NETWORK_WIFI => NetworkConfig::Wifi,
94+ _ => NetworkConfig::Any,
95+ };
96+ assert!(matches!(network_type, NetworkConfig::Cellular));
97+ 
98+ // Test WIFI mapping
99+ let network_type = match NETWORK_WIFI {
100+ NETWORK_MOBILE => NetworkConfig::Cellular,
101+ NETWORK_WIFI => NetworkConfig::Wifi,
102+ _ => NetworkConfig::Any,
103+ };
104+ assert!(matches!(network_type, NetworkConfig::Wifi));
105+ 
106+ // Test unknown network type defaults to Any
107+ let unknown_network = 0x9999;
108+ let result = match unknown_network {
109+ NETWORK_MOBILE => NetworkConfig::Cellular,
110+ NETWORK_WIFI => NetworkConfig::Wifi,
111+ _ => NetworkConfig::Any,
112+ };
113+ assert!(matches!(result, NetworkConfig::Any));
114+}
115+ 
116+// @tc.name: ut_api9_download_config_with_all_options
117+// @tc.desc: Test DownloadConfig with all optional fields set
118+// @tc.precon: NA
119+// @tc.step: 1. Create TaskConfigBuilder with all options
120+// 2. Build TaskConfig
121+// 3. Verify all options are correctly mapped
122+// @tc.expect: All options should be correctly mapped to TaskConfig
123+// @tc.type: FUNC
124+// @tc.require: issues#ICN16H
125+#[test]
126+fn ut_api9_download_config_with_all_options() {
127+ use request_core::config::{TaskConfigBuilder, Version, NetworkConfig, Action};
128+ 
129+ let mut headers = HashMap::new();
130+ headers.insert("X-Auth".to_string(), "token".to_string());
131+ 
132+ let mut builder = TaskConfigBuilder::new(Version::API9);
133+ builder.url("https://example.com/file.zip".to_string());
134+ builder.headers(headers);
135+ builder.metered(true);
136+ builder.roaming(false);
137+ builder.network_type(NetworkConfig::Wifi);
138+ builder.description("Download description".to_string());
139+ builder.title("Custom Title".to_string());
140+ builder.background(true);
141+ builder.file_path("/downloads/file.zip".to_string());
142+ builder.action(Action::Download);
143+ 
144+ let config = builder.build();
145+ 
146+ assert_eq!(config.url, "https://example.com/file.zip");
147+ assert!(config.common_data.metered);
148+ assert!(!config.common_data.roaming);
149+ assert!(matches!(config.common_data.network_config, NetworkConfig::Wifi));
150+ assert_eq!(config.description, "Download description");
151+ assert_eq!(config.title, "Custom Title");
152+ assert!(config.common_data.background);
153+ assert_eq!(config.saveas, "/downloads/file.zip");
154+}
155+ 
156+// @tc.name: ut_api9_upload_config_with_form_data
157+// @tc.desc: Test UploadConfig with form data items conversion
158+// @tc.precon: NA
159+// @tc.step: 1. Create TaskConfigBuilder with form items
160+// 2. Build TaskConfig
161+// 3. Verify form items are correctly mapped
162+// @tc.expect: Form items should be correctly mapped
163+// @tc.type: FUNC
164+// @tc.require: issues#ICN16H
165+#[test]
166+fn ut_api9_upload_config_with_form_data() {
167+ use request_core::config::{TaskConfigBuilder, Version, Action, FormItem};
168+ 
169+ let mut builder = TaskConfigBuilder::new(Version::API9);
170+ builder.url("https://example.com/upload".to_string());
171+ builder.method("POST".to_string());
172+ builder.action(Action::Upload);
173+ builder.form_items(vec![
174+ FormItem { name: "field1".to_string(), value: "value1".to_string() },
175+ FormItem { name: "field2".to_string(), value: "value2".to_string() },
176+ ]);
177+ 
178+ let config = builder.build();
179+ 
180+ assert_eq!(config.form_items.len(), 2);
181+ assert_eq!(config.form_items[0].name, "field1");
182+ assert_eq!(config.form_items[0].value, "value1");
183+ assert_eq!(config.form_items[1].name, "field2");
184+ assert_eq!(config.form_items[1].value, "value2");
185+}
186+ 
187+// @tc.name: ut_api9_upload_config_partial_range
188+// @tc.desc: Test UploadConfig with partial byte range conversion
189+// @tc.precon: NA
190+// @tc.step: 1. Create TaskConfigBuilder with begins and ends
191+// 2. Build TaskConfig
192+// 3. Verify range values are correctly mapped
193+// @tc.expect: Range values should be correctly mapped
194+// @tc.type: FUNC
195+// @tc.require: issues#ICN16H
196+#[test]
197+fn ut_api9_upload_config_partial_range() {
198+ use request_core::config::{TaskConfigBuilder, Version, Action};
199+ 
200+ let mut builder = TaskConfigBuilder::new(Version::API9);
201+ builder.url("https://example.com/upload".to_string());
202+ builder.action(Action::Upload);
203+ builder.begins(1024);
204+ builder.ends(2048);
205+ 
206+ let config = builder.build();
207+ 
208+ assert_eq!(config.common_data.begins, 1024);
209+ assert_eq!(config.common_data.ends, 2048);
210+}
211+ 
212+// @tc.name: ut_api9_special_characters_handling
213+// @tc.desc: Test special characters handling in URL and headers
214+// @tc.precon: NA
215+// @tc.step: 1. Create TaskConfig with special URL and headers
216+// 2. Build TaskConfig
217+// 3. Verify special characters are preserved
218+// @tc.expect: Special characters should be preserved correctly
219+// @tc.type: FUNC
220+// @tc.require: issues#ICN16H
221+#[test]
222+fn ut_api9_special_characters_handling() {
223+ use request_core::config::{TaskConfigBuilder, Version, Action};
224+ 
225+ let special_url = "https://example.com/file?name=test%20file&version=1.0.zip";
226+ let mut headers = HashMap::new();
227+ headers.insert("X-Special".to_string(), "value with spaces & symbols=+,;".to_string());
228+ headers.insert("X-Unicode".to_string(), "日本語テスト".to_string());
229+ 
230+ let mut builder = TaskConfigBuilder::new(Version::API9);
231+ builder.url(special_url.to_string());
232+ builder.headers(headers);
233+ builder.action(Action::Download);
234+ 
235+ let config = builder.build();
236+ 
237+ assert_eq!(config.url, special_url);
238+ assert_eq!(config.headers.get("X-Special"), Some(&"value with spaces & symbols=+,;".to_string()));
239+ assert_eq!(config.headers.get("X-Unicode"), Some(&"日本語テスト".to_string()));
240+}
@@ -0,0 +1,18 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 9 modules.
15+//!
16+//! This module contains tests for the API 9 bridge types and conversions.
17+ 
18+pub mod bridge;
@@ -0,0 +1,19 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 task module.
15+//!
16+//! This module contains tests for the API 10 task control functions
17+//! including speed limit validation.
18+ 
19+pub mod speed;
@@ -0,0 +1,175 @@
1+// Copyright (C) 2025 Huawei Device Co., Ltd.
2+// Licensed under the Apache License, Version 2.0 (the "License");
3+// you may not use this file except in compliance with the License.
4+// You may obtain a copy of the License at
5+//
6+// http://www.apache.org/licenses/LICENSE-2.0
7+//
8+// Unless required by applicable law or agreed to in writing, software
9+// distributed under the License is distributed on an "AS IS" BASIS,
10+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+// See the License for the specific language governing permissions and
12+// limitations under the License.
13+ 
14+//! Unit tests for API 10 task speed limit functions.
15+//!
16+//! This module tests the speed limit validation functionality.
17+ 
18+// @tc.name: ut_task_speed_limit_comprehensive
19+// @tc.desc: Test speed limit validation with comprehensive cases
20+// @tc.precon: NA
21+// @tc.step: 1. Test boundary values (at, below, above MIN_SPEED_LIMIT)
22+// 2. Test various valid speeds (16KB/s, 32KB/s, 64KB/s, 1MB/s, etc.)
23+// 3. Test invalid speeds (negative, zero, below 16KB/s)
24+// 4. Test extreme values (i64::MAX, i64::MIN)
25+// @tc.expect: Speeds >= 16KB/s should be valid, others invalid
26+// @tc.type: FUNC
27+// @tc.require: issues#ICN16H
28+#[test]
29+fn ut_task_speed_limit_comprehensive() {
30+ const MIN_SPEED_LIMIT: i64 = 16 * 1024; // 16384 bytes/s (16 KB/s)
31+ 
32+ // Boundary values
33+ let speed_at_limit = MIN_SPEED_LIMIT;
34+ let speed_below_limit = MIN_SPEED_LIMIT - 1;
35+ let speed_above_limit = MIN_SPEED_LIMIT + 1;
36+ 
37+ assert!(
38+ speed_at_limit >= MIN_SPEED_LIMIT,
39+ "Speed at limit should be valid"
40+ );
41+ assert!(
42+ speed_below_limit < MIN_SPEED_LIMIT,
43+ "Speed below limit should be invalid"
44+ );
45+ assert!(
46+ speed_above_limit >= MIN_SPEED_LIMIT,
47+ "Speed above limit should be valid"
48+ );
49+ 
50+ // Valid speeds
51+ let valid_speeds = vec![
52+ (MIN_SPEED_LIMIT, true),
53+ (MIN_SPEED_LIMIT + 1, true),
54+ (32768, true), // 32 KB/s
55+ (65536, true), // 64 KB/s
56+ (131072, true), // 128 KB/s
57+ (262144, true), // 256 KB/s
58+ (524288, true), // 512 KB/s
59+ (1048576, true), // 1 MB/s
60+ (10485760, true), // 10 MB/s
61+ (100 * 1024 * 1024, true), // 100 MB/s
62+ (i64::MAX, true), // Maximum possible
63+ ];
64+ 
65+ for (speed, expected_valid) in valid_speeds {
66+ let is_valid = speed >= MIN_SPEED_LIMIT;
67+ assert_eq!(
68+ is_valid, expected_valid,
69+ "Speed {} validation failed: expected {}, got {}",
70+ speed, expected_valid, is_valid
71+ );
72+ }
73+ 
74+ // Invalid speeds
75+ let invalid_speeds = vec![
76+ (0, false),
77+ (1, false),
78+ (1024, false),
79+ (8192, false),
80+ (16383, false),
81+ (MIN_SPEED_LIMIT - 1, false),
82+ (-1, false),
83+ (-16384, false),
84+ (i64::MIN, false),
85+ ];
86+ 
87+ for (speed, expected_valid) in invalid_speeds {
88+ let is_valid = speed >= MIN_SPEED_LIMIT;
89+ assert_eq!(
90+ is_valid, expected_valid,
91+ "Speed {} validation failed: expected {}, got {}",
92+ speed, expected_valid, is_valid
93+ );
94+ }
95+}
96+ 
97+// @tc.name: ut_task_max_speed_with_min_speed_constraint
98+// @tc.desc: Test check_max_speed with min_speed configured
99+// @tc.precon: Task has min_speed configured
100+// @tc.step: 1. Test max_speed < min_speed (should fail)
101+// 2. Test max_speed = min_speed (should pass)
102+// 3. Test max_speed > min_speed (should pass)
103+// 4. Test various min_speed values
104+// @tc.expect: max_speed must be >= min_speed
105+// @tc.type: FUNC
106+// @tc.require: issues#ICN16H
107+#[test]
108+fn ut_task_max_speed_with_min_speed_constraint() {
109+ // Test case 1: min_speed = 65536 (64 KB/s)
110+ let min_speed = 65536i64;
111+ 
112+ let test_cases = vec![
113+ (min_speed - 1, false),
114+ (min_speed, true),
115+ (min_speed + 1, true),
116+ (131072, true),
117+ ];
118+ 
119+ for (max_speed, should_pass) in test_cases {
120+ let passes = max_speed >= min_speed;
121+ assert_eq!(
122+ passes, should_pass,
123+ "max_speed {} with min_speed {}: expected {}, got {}",
124+ max_speed, min_speed, should_pass, passes
125+ );
126+ }
127+ 
128+ // Test case 2: min_speed = 1048576 (1 MB/s)
129+ let min_speed = 1048576i64;
130+ let max_speed = 1048575i64;
131+ assert!(
132+ max_speed < min_speed,
133+ "Comparison should detect max < min"
134+ );
135+ 
136+ let max_speed = 1048576i64;
137+ assert!(
138+ max_speed >= min_speed,
139+ "Equal values should pass"
140+ );
141+ 
142+ let max_speed = 1048577i64;
143+ assert!(
144+ max_speed >= min_speed,
145+ "Greater values should pass"
146+ );
147+}
148+ 
149+// @tc.name: ut_task_speed_without_min_speed
150+// @tc.desc: Test speed validation without min_speed constraint
151+// @tc.precon: Task has no min_speed configured
152+// @tc.step: 1. Check max speed without min_speed constraint
153+// 2. Verify any speed >= MIN_SPEED_LIMIT is valid
154+// @tc.expect: Should pass with only MIN_SPEED_LIMIT constraint
155+// @tc.type: FUNC
156+// @tc.require: issues#ICN16H
157+#[test]
158+fn ut_task_speed_without_min_speed() {
159+ const MIN_SPEED_LIMIT: i64 = 16 * 1024;
160+ 
161+ // When there's no min_speed config, only MIN_SPEED_LIMIT applies
162+ let speed = 65536;
163+ assert!(
164+ speed >= MIN_SPEED_LIMIT,
165+ "Speed should be >= MIN_SPEED_LIMIT"
166+ );
167+ 
168+ // Zero speed should be invalid
169+ let speed = 0i64;
170+ assert!(speed < MIN_SPEED_LIMIT, "Zero speed should be invalid");
171+ 
172+ // Very large speed should be valid
173+ let speed = 100 * 1024 * 1024i64;
174+ assert!(speed >= MIN_SPEED_LIMIT, "Large speed should be valid");
175+}