• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 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 #[cfg(test)]
15 mod tests {
16     use super::*;
17     use crate::{error::HttpErrorCode, info::DownloadInfoMgr};
18     use std::sync::{Arc, AtomicBool, Mutex};
19     use std::cell::RefCell;
20     use mockall::mock;
21 
22     mock! {
23         pub RequestCallback {}
24         impl RequestCallback for RequestCallback {
25             fn on_success(&mut self, response: Response);
26             fn on_fail(&mut self, error: HttpClientError);
27             fn on_cancel(&mut self);
28             fn on_data_receive(&mut self, data: &[u8], task: RequestTask);
29             fn on_progress(&mut self, dl_total: u64, dl_now: u64, ul_total: u64, ul_now: u64);
30             fn on_restart(&mut self);
31         }
32     }
33 
34     // @tc.name: ut_callback_wrapper_creation
35     // @tc.desc: Test CallbackWrapper creation with valid parameters
36     // @tc.precon: NA
37     // @tc.step: 1. Create mock RequestCallback
38     // 2. Create required Arc and Weak pointers
39     // 3. Initialize CallbackWrapper with from_callback method
40     // @tc.expect: CallbackWrapper is successfully created with correct initial state
41     // @tc.type: FUNC
42     // @tc.require: issueNumber
43     // @tc.level: Level 0
44     #[test]
ut_callback_wrapper_creation()45     fn ut_callback_wrapper_creation() {
46         let mock_callback = Box::new(MockRequestCallback::new());
47         let reset = Arc::new(AtomicBool::new(false));
48         let task = Arc::new(Mutex::new(SharedPtr::null()));
49         let task_weak = Arc::downgrade(&task);
50         let task_id = TaskId::new();
51         let info_mgr = Arc::new(DownloadInfoMgr::new());
52 
53         let wrapper = CallbackWrapper::from_callback(
54             mock_callback,
55             reset.clone(),
56             task_weak,
57             task_id.clone(),
58             info_mgr.clone(),
59             0
60         );
61 
62         assert!(!wrapper.reset.load(Ordering::SeqCst));
63         assert_eq!(wrapper.task_id, task_id);
64         assert_eq!(wrapper.current, 0);
65         assert_eq!(wrapper.tries, 0);
66         assert!(wrapper.inner.is_some());
67     }
68 
69     // @tc.name: ut_callback_wrapper_on_success_200
70     // @tc.desc: Test on_success callback with 200 status code
71     // @tc.precon: CallbackWrapper initialized with mock callback
72     // @tc.step: 1. Create test response with OK status
73     // 2. Call on_success method
74     // 3. Verify callback was triggered with success
75     // @tc.expect: on_success is called with properly converted Response
76     // @tc.type: FUNC
77     // @tc.require: issueNumber
78     // @tc.level: Level 1
79     #[test]
ut_callback_wrapper_on_success_200()80     fn ut_callback_wrapper_on_success_200() {
81         let mut mock = MockRequestCallback::new();
82         mock.expect_on_success().once().return_const(());
83 
84         let wrapper = create_test_wrapper(Box::new(mock));
85         let mut wrapper = RefCell::new(wrapper);
86 
87         let request = ffi::NewHttpClientRequest();
88         let response = create_mock_response(ffi::ResponseCode::OK);
89 
90         wrapper.borrow_mut().on_success(&request, &response);
91 
92         assert!(wrapper.borrow().inner.is_none());
93     }
94 
95     // @tc.name: ut_callback_wrapper_on_success_error_status
96     // @tc.desc: Test on_success callback with error status code
97     // @tc.precon: CallbackWrapper initialized with mock callback
98     // @tc.step: 1. Create test response with 404 status
99     // 2. Call on_success method
100     // 3. Verify callback was triggered with failure
101     // @tc.expect: on_fail is called with appropriate error
102     // @tc.type: FUNC
103     // @tc.require: issueNumber
104     // @tc.level: Level 2
105     #[test]
ut_callback_wrapper_on_success_error_status()106     fn ut_callback_wrapper_on_success_error_status() {
107         let mut mock = MockRequestCallback::new();
108         mock.expect_on_fail().once().return_const(());
109 
110         let wrapper = create_test_wrapper(Box::new(mock));
111         let mut wrapper = RefCell::new(wrapper);
112 
113         let request = ffi::NewHttpClientRequest();
114         let response = create_mock_response(ffi::ResponseCode::NOT_FOUND);
115 
116         wrapper.borrow_mut().on_success(&request, &response);
117 
118         assert!(wrapper.borrow().inner.is_none());
119     }
120 
121     // @tc.name: ut_task_status_try_from
122     // @tc.desc: Test TryFrom conversion for TaskStatus enum
123     // @tc.precon: NA
124     // @tc.step: 1. Attempt conversion from valid ffi::TaskStatus
125     // 2. Attempt conversion from invalid ffi::TaskStatus
126     // @tc.expect: Valid conversions succeed, invalid returns Err
127     // @tc.type: FUNC
128     // @tc.require: issueNumber
129     // @tc.level: Level 1
130     #[test]
ut_task_status_try_from()131     fn ut_task_status_try_from() {
132         assert!(matches!(TaskStatus::try_from(ffi::TaskStatus::IDLE), Ok(TaskStatus::Idle)));
133         assert!(matches!(TaskStatus::try_from(ffi::TaskStatus::RUNNING), Ok(TaskStatus::Running)));
134 
135         // Test invalid variant (using out-of-range value)
136         let invalid_status = unsafe { std::mem::transmute(999) };
137         assert!(matches!(TaskStatus::try_from(invalid_status), Err(_)));
138     }
139 
140     // @tc.name: ut_response_code_try_from
141     // @tc.desc: Test TryFrom conversion for ResponseCode enum
142     // @tc.precon: NA
143     // @tc.step: 1. Test conversion for multiple valid ResponseCode variants
144     // 2. Test conversion for invalid ResponseCode
145     // @tc.expect: Valid conversions return correct ResponseCode, invalid returns Err
146     // @tc.type: FUNC
147     // @tc.require: issueNumber
148     // @tc.level: Level 1
149     #[test]
ut_response_code_try_from()150     fn ut_response_code_try_from() {
151         assert!(matches!(ResponseCode::try_from(ffi::ResponseCode::OK), Ok(ResponseCode::Ok)));
152         assert!(matches!(ResponseCode::try_from(ffi::ResponseCode::NOT_FOUND), Ok(ResponseCode::NotFound)));
153         assert!(matches!(ResponseCode::try_from(ffi::ResponseCode::INTERNAL_ERROR), Ok(ResponseCode::InternalError)));
154 
155         // Test invalid variant
156         let invalid_code = unsafe { std::mem::transmute(999) };
157         assert!(matches!(ResponseCode::try_from(invalid_code), Err(_)));
158     }
159 
160     // @tc.name: ut_http_error_code_try_from
161     // @tc.desc: Test TryFrom conversion for HttpErrorCode enum
162     // @tc.precon: NA
163     // @tc.step: 1. Test conversion for multiple HttpErrorCode variants
164     // 2. Test edge case with unknown error code
165     // @tc.expect: Valid conversions return correct HttpErrorCode, unknown returns Err
166     // @tc.type: FUNC
167     // @tc.require: issueNumber
168     // @tc.level: Level 2
169     #[test]
ut_http_error_code_try_from()170     fn ut_http_error_code_try_from() {
171         assert!(matches!(HttpErrorCode::try_from(ffi::HttpErrorCode::HTTP_NONE_ERR), Ok(HttpErrorCode::HttpNoneErr)));
172         assert!(matches!(HttpErrorCode::try_from(ffi::HttpErrorCode::HTTP_WRITE_ERROR), Ok(HttpErrorCode::HttpWriteError)));
173         assert!(matches!(HttpErrorCode::try_from(ffi::HttpErrorCode::HTTP_TASK_CANCELED), Ok(HttpErrorCode::HttpTaskCanceled)));
174 
175         // Test edge case with unknown error code
176         let unknown_code = unsafe { std::mem::transmute(ffi::HttpErrorCode::HTTP_UNKNOWN_OTHER_ERROR) };
177         assert!(matches!(HttpErrorCode::try_from(unknown_code), Ok(HttpErrorCode::HttpUnknownOtherError)));
178     }
179 
180     // @tc.name: ut_callback_wrapper_on_progress
181     // @tc.desc: Test progress callback functionality
182     // @tc.precon: CallbackWrapper initialized with mock callback
183     // @tc.step: 1. Set up mock to expect progress call
184     // 2. Call on_progress with test values
185     // 3. Verify mock was called with correct parameters
186     // @tc.expect: on_progress is called with matching parameters
187     // @tc.type: FUNC
188     // @tc.require: issueNumber
189     // @tc.level: Level 1
190     #[test]
ut_callback_wrapper_on_progress()191     fn ut_callback_wrapper_on_progress() {
192         let mut mock = MockRequestCallback::new();
193         mock.expect_on_progress()
194             .withf(|dl_total, dl_now, ul_total, ul_now|
195                 *dl_total == 1000 && *dl_now == 500 && *ul_total == 200 && *ul_now == 100)
196             .once()
197             .return_const(());
198 
199         let wrapper = create_test_wrapper(Box::new(mock));
200         let mut wrapper = RefCell::new(wrapper);
201 
202         wrapper.borrow_mut().on_progress(1000, 500, 200, 100);
203     }
204 
205     // @tc.name: ut_callback_wrapper_on_cancel_reset
206     // @tc.desc: Test cancel behavior when reset flag is set
207     // @tc.precon: CallbackWrapper with reset flag set to true
208     // @tc.step: 1. Configure wrapper with reset=true
209     // 2. Call on_cancel method
210     // 3. Verify new task creation and callback restart
211     // @tc.expect: New task is created and reset flag is cleared
212     // @tc.type: FUNC
213     // @tc.require: issueNumber
214     // @tc.level: Level 3
215     #[test]
ut_callback_wrapper_on_cancel_reset()216     fn ut_callback_wrapper_on_cancel_reset() {
217         let mut mock = MockRequestCallback::new();
218         mock.expect_on_restart().once().return_const(());
219 
220         let reset = Arc::new(AtomicBool::new(true));
221         let wrapper = create_test_wrapper_with_reset(Box::new(mock), reset.clone());
222         let mut wrapper = RefCell::new(wrapper);
223 
224         let request = ffi::NewHttpClientRequest();
225         let response = create_mock_response(ffi::ResponseCode::OK);
226 
227         wrapper.borrow_mut().on_cancel(&request, &response);
228 
229         assert!(!reset.load(Ordering::SeqCst));
230     }
231 
232     // Helper functions for test setup
create_test_wrapper(callback: Box<dyn RequestCallback>) -> CallbackWrapper233     fn create_test_wrapper(callback: Box<dyn RequestCallback>) -> CallbackWrapper {
234         let reset = Arc::new(AtomicBool::new(false));
235         let task = Arc::new(Mutex::new(SharedPtr::null()));
236         let task_weak = Arc::downgrade(&task);
237         let task_id = TaskId::new();
238         let info_mgr = Arc::new(DownloadInfoMgr::new());
239 
240         CallbackWrapper::from_callback(callback, reset, task_weak, task_id, info_mgr, 0)
241     }
242 
create_test_wrapper_with_reset(callback: Box<dyn RequestCallback>, reset: Arc<AtomicBool>) -> CallbackWrapper243     fn create_test_wrapper_with_reset(callback: Box<dyn RequestCallback>, reset: Arc<AtomicBool>) -> CallbackWrapper {
244         let task = Arc::new(Mutex::new(SharedPtr::null()));
245         let task_weak = Arc::downgrade(&task);
246         let task_id = TaskId::new();
247         let info_mgr = Arc::new(DownloadInfoMgr::new());
248 
249         CallbackWrapper::from_callback(callback, reset, task_weak, task_id, info_mgr, 0)
250     }
251 
create_mock_response(code: ffi::ResponseCode) -> ffi::HttpClientResponse252     fn create_mock_response(code: ffi::ResponseCode) -> ffi::HttpClientResponse {
253         // In a real test environment, this would be replaced with actual mock implementation
254         unsafe { std::mem::zeroed() }
255     }
256 }