1 // Copyright (C) 2023 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_oh! {
15     pub(crate) mod config;
16     pub(crate) use config::{SystemConfig, SystemConfigManager};
17 }
18 
19 pub(crate) mod account;
20 pub(crate) mod app_state;
21 pub(crate) mod database;
22 pub(crate) mod events;
23 pub(crate) mod query;
24 pub(crate) use task_manager::TaskManager;
25 pub(crate) mod network;
26 pub(crate) mod network_manager;
27 pub(crate) mod notifier;
28 pub(crate) mod scheduler;
29 pub(crate) mod task_manager;
30 
31 #[cfg(test)]
32 mod test {
33     use std::fs::File;
34     use std::time::Duration;
35 
36     use ylong_runtime::sync::mpsc::unbounded_channel;
37 
38     use super::database::RequestDb;
39     use super::network::{NetworkInfo, NetworkInner, NetworkType};
40     use super::TaskManager;
41     use crate::config::{Action, ConfigBuilder, Mode};
42     use crate::error::ErrorCode;
43     use crate::info::{State, TaskInfo};
44     use crate::manage::events::{TaskEvent, TaskManagerEvent};
45     use crate::manage::task_manager::{TaskManagerRx, TaskManagerTx};
46     use crate::service::client::ClientManagerEntry;
47     use crate::service::run_count::RunCountManagerEntry;
48     use crate::task::reason::Reason;
49     use crate::tests::{lock_database, test_init};
50 
51     const GITEE_FILE_LEN: u64 = 1042003;
52 
task_manager() -> TaskManager53     fn task_manager() -> TaskManager {
54         let (tx, rx) = unbounded_channel();
55         let task_manager_tx = TaskManagerTx::new(tx);
56         let rx = TaskManagerRx::new(rx);
57         let inner = NetworkInner::new();
58         inner.notify_online(NetworkInfo {
59             network_type: NetworkType::Wifi,
60             is_metered: false,
61             is_roaming: false,
62         });
63         let (tx, _rx) = unbounded_channel();
64         let run_count = RunCountManagerEntry::new(tx);
65         let (tx, _rx) = unbounded_channel();
66         let client = ClientManagerEntry::new(tx);
67         TaskManager::new(task_manager_tx, rx, run_count, client)
68     }
69 
task_into(task_id: u32) -> TaskInfo70     fn task_into(task_id: u32) -> TaskInfo {
71         let db = RequestDb::get_instance();
72         db.get_task_info(task_id).unwrap()
73     }
74 
75     #[test]
ut_manager_task_state_and_reason()76     fn ut_manager_task_state_and_reason() {
77         test_init();
78         let _lock = lock_database();
79         let mut manager = task_manager();
80         let file_path = "test_files/ut_manager_task_state_and_reason.txt";
81 
82         let file = File::create(file_path).unwrap();
83         let config = ConfigBuilder::new()
84         .action(Action::Download)
85         .retry(true)
86         .mode(Mode::BackGround)
87         .file_spec(file)
88         .url("https://www.gitee.com/tiga-ultraman/downloadTests/releases/download/v1.01/test.txt")
89         .redirect(true)
90         .build();
91         let uid = config.common_data.uid;
92         let task_id = manager.create(config).unwrap();
93         assert_eq!(
94             task_into(task_id).progress.common_data.state,
95             State::Initialized.repr
96         );
97 
98         assert_eq!(task_into(task_id).common_data.reason, Reason::Default.repr);
99 
100         manager.start(uid, task_id);
101         assert_eq!(
102             task_into(task_id).progress.common_data.state,
103             State::Waiting.repr
104         );
105         assert_eq!(
106             task_into(task_id).common_data.reason,
107             Reason::RunningTaskMeetLimits.repr
108         );
109 
110         manager.pause(uid, task_id);
111         assert_eq!(
112             task_into(task_id).progress.common_data.state,
113             State::Paused.repr
114         );
115         assert_eq!(
116             task_into(task_id).common_data.reason,
117             Reason::UserOperation.repr
118         );
119 
120         manager.resume(uid, task_id);
121         assert_eq!(
122             task_into(task_id).progress.common_data.state,
123             State::Waiting.repr
124         );
125         assert_eq!(
126             task_into(task_id).common_data.reason,
127             Reason::RunningTaskMeetLimits.repr
128         );
129 
130         manager.pause(uid, task_id);
131         assert_eq!(
132             task_into(task_id).progress.common_data.state,
133             State::Paused.repr
134         );
135         assert_eq!(
136             task_into(task_id).common_data.reason,
137             Reason::UserOperation.repr
138         );
139 
140         manager.resume(uid, task_id);
141         assert_eq!(
142             task_into(task_id).progress.common_data.state,
143             State::Waiting.repr
144         );
145         assert_eq!(
146             task_into(task_id).common_data.reason,
147             Reason::RunningTaskMeetLimits.repr
148         );
149 
150         manager.stop(uid, task_id);
151         assert_eq!(
152             task_into(task_id).progress.common_data.state,
153             State::Stopped.repr
154         );
155         assert_eq!(
156             task_into(task_id).common_data.reason,
157             Reason::UserOperation.repr
158         );
159 
160         manager.start(uid, task_id);
161         assert_eq!(
162             task_into(task_id).progress.common_data.state,
163             State::Waiting.repr
164         );
165         assert_eq!(
166             task_into(task_id).common_data.reason,
167             Reason::RunningTaskMeetLimits.repr
168         );
169 
170         manager.scheduler.reschedule();
171 
172         ylong_runtime::block_on(async move {
173             ylong_runtime::time::sleep(Duration::from_millis(500)).await;
174             assert_eq!(
175                 task_into(task_id).progress.common_data.state,
176                 State::Running.repr
177             );
178             assert_eq!(task_into(task_id).common_data.reason, Reason::Default.repr);
179             ylong_runtime::time::sleep(Duration::from_secs(10)).await;
180             let msg = manager.rx.recv().await.unwrap();
181             assert!(matches!(msg, TaskManagerEvent::Reschedule));
182             let msg = manager.rx.recv().await.unwrap();
183             assert!(matches!(
184                 msg,
185                 TaskManagerEvent::Task(TaskEvent::Completed(info_task_id, info_uid,Mode::BackGround)) if uid == info_uid && task_id == info_task_id
186             ));
187             let file = File::open(file_path).unwrap();
188             assert_eq!(file.metadata().unwrap().len(), GITEE_FILE_LEN);
189         });
190     }
191 
192     #[test]
ut_manager_state_change_error()193     fn ut_manager_state_change_error() {
194         test_init();
195         let _lock = lock_database();
196         let mut manager = task_manager();
197         let file_path = "test_files/ut_manager_state_change_error.txt";
198 
199         let file = File::create(file_path).unwrap();
200         let config = ConfigBuilder::new()
201         .action(Action::Download)
202         .retry(true)
203         .mode(Mode::BackGround)
204         .file_spec(file)
205         .url("https://www.gitee.com/tiga-ultraman/downloadTests/releases/download/v1.01/test.txt")
206         .redirect(true)
207         .build();
208         let uid = config.common_data.uid;
209 
210         // initialized
211         let task_id = manager.create(config.clone()).unwrap();
212         assert_eq!(
213             task_into(task_id).progress.common_data.state,
214             State::Initialized.repr
215         );
216         assert_eq!(manager.pause(uid, task_id), ErrorCode::TaskStateErr);
217         assert_eq!(manager.resume(uid, task_id), ErrorCode::TaskStateErr);
218         assert_eq!(manager.stop(uid, task_id), ErrorCode::TaskStateErr);
219         assert_eq!(manager.remove(uid, task_id), ErrorCode::ErrOk);
220         assert_eq!(
221             task_into(task_id).progress.common_data.state,
222             State::Removed.repr
223         );
224 
225         // started
226         let task_id = manager.create(config.clone()).unwrap();
227         assert_eq!(manager.start(uid, task_id), ErrorCode::ErrOk);
228         assert_eq!(manager.resume(uid, task_id), ErrorCode::TaskStateErr);
229         assert_eq!(manager.start(uid, task_id), ErrorCode::TaskStateErr);
230         assert_eq!(manager.remove(uid, task_id), ErrorCode::ErrOk);
231         assert_eq!(
232             task_into(task_id).progress.common_data.state,
233             State::Removed.repr
234         );
235 
236         // paused
237         let task_id = manager.create(config.clone()).unwrap();
238         assert_eq!(manager.start(uid, task_id), ErrorCode::ErrOk);
239         assert_eq!(manager.pause(uid, task_id), ErrorCode::ErrOk);
240         assert_eq!(manager.pause(uid, task_id), ErrorCode::TaskStateErr);
241         assert_eq!(manager.stop(uid, task_id), ErrorCode::TaskStateErr);
242         assert_eq!(manager.start(uid, task_id), ErrorCode::TaskStateErr);
243         assert_eq!(manager.remove(uid, task_id), ErrorCode::ErrOk);
244         assert_eq!(
245             task_into(task_id).progress.common_data.state,
246             State::Removed.repr
247         );
248 
249         // stopped
250         let task_id = manager.create(config.clone()).unwrap();
251         assert_eq!(manager.start(uid, task_id), ErrorCode::ErrOk);
252         assert_eq!(manager.stop(uid, task_id), ErrorCode::ErrOk);
253         assert_eq!(manager.pause(uid, task_id), ErrorCode::TaskStateErr);
254         assert_eq!(manager.stop(uid, task_id), ErrorCode::TaskStateErr);
255         assert_eq!(manager.resume(uid, task_id), ErrorCode::TaskStateErr);
256         assert_eq!(manager.start(uid, task_id), ErrorCode::ErrOk);
257         assert_eq!(manager.stop(uid, task_id), ErrorCode::ErrOk);
258         assert_eq!(manager.remove(uid, task_id), ErrorCode::ErrOk);
259         assert_eq!(
260             task_into(task_id).progress.common_data.state,
261             State::Removed.repr
262         );
263 
264         // resumed
265         let task_id = manager.create(config.clone()).unwrap();
266         assert_eq!(manager.start(uid, task_id), ErrorCode::ErrOk);
267         assert_eq!(manager.pause(uid, task_id), ErrorCode::ErrOk);
268         assert_eq!(manager.resume(uid, task_id), ErrorCode::ErrOk);
269         assert_eq!(manager.resume(uid, task_id), ErrorCode::TaskStateErr);
270         assert_eq!(manager.start(uid, task_id), ErrorCode::TaskStateErr);
271         assert_eq!(manager.pause(uid, task_id), ErrorCode::ErrOk);
272         assert_eq!(manager.resume(uid, task_id), ErrorCode::ErrOk);
273         assert_eq!(manager.remove(uid, task_id), ErrorCode::ErrOk);
274         assert_eq!(
275             task_into(task_id).progress.common_data.state,
276             State::Removed.repr
277         );
278     }
279 
280     #[test]
ut_manager_reschedule()281     fn ut_manager_reschedule() {
282         test_init();
283         let _lock = lock_database();
284         let mut manager = task_manager();
285         let file_path = "test_files/ut_manager_reschedule.txt";
286 
287         let file = File::create(file_path).unwrap();
288         let config = ConfigBuilder::new()
289         .action(Action::Download)
290         .retry(true)
291         .mode(Mode::BackGround)
292         .file_spec(file)
293         .url("https://www.gitee.com/tiga-ultraman/downloadTests/releases/download/v1.01/test.txt")
294         .redirect(true)
295         .build();
296         let uid = config.common_data.uid;
297         let task_id = manager.create(config.clone()).unwrap();
298         manager.rx.try_recv().unwrap_err();
299         manager.start(uid, task_id);
300         assert!(matches!(
301             manager.rx.try_recv().unwrap(),
302             TaskManagerEvent::Reschedule
303         ));
304         manager.scheduler.resort_scheduled = false;
305         manager.stop(uid, task_id);
306         assert!(matches!(
307             manager.rx.try_recv().unwrap(),
308             TaskManagerEvent::Reschedule
309         ));
310         manager.scheduler.resort_scheduled = false;
311         manager.start(uid, task_id);
312         assert!(matches!(
313             manager.rx.try_recv().unwrap(),
314             TaskManagerEvent::Reschedule
315         ));
316         manager.stop(uid, task_id);
317         manager.rx.try_recv().unwrap_err();
318         manager.scheduler.resort_scheduled = false;
319         manager.start(uid, task_id);
320         assert!(matches!(
321             manager.rx.try_recv().unwrap(),
322             TaskManagerEvent::Reschedule
323         ));
324         manager.scheduler.resort_scheduled = false;
325         manager.pause(uid, task_id);
326         assert!(matches!(
327             manager.rx.try_recv().unwrap(),
328             TaskManagerEvent::Reschedule
329         ));
330         manager.scheduler.resort_scheduled = false;
331         manager.resume(uid, task_id);
332         assert!(matches!(
333             manager.rx.try_recv().unwrap(),
334             TaskManagerEvent::Reschedule
335         ));
336     }
337 }
338