已合并
[ANI] Add API9 and API10 bridge unit tests #1809
huaxin05创建于 3月6日
[ANI] Add API9 and API10 bridge unit tests #1809
已合并
共 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | + | ||
| 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 | +} | ||