1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 use std::{
17     cmp::Ordering,
18     fs::{self, OpenOptions},
19     io::Write,
20     path::Path,
21 };
22 
23 use asset_common::CallingInfo;
24 use asset_definition::{ErrCode, Extension, Value};
25 
26 use crate::{
27     database::Database,
28     table::Table,
29     types::{column, DbMap, QueryOptions, TABLE_NAME},
30 };
31 
32 const DB_DATA: [(&str, Value); 9] = [
33     (column::OWNER_TYPE, Value::Number(1)),
34     (column::SYNC_TYPE, Value::Number(1)),
35     (column::ACCESSIBILITY, Value::Number(1)),
36     (column::AUTH_TYPE, Value::Number(1)),
37     (column::IS_PERSISTENT, Value::Bool(true)),
38     (column::VERSION, Value::Number(2)),
39     (column::REQUIRE_PASSWORD_SET, Value::Bool(false)),
40     (column::LOCAL_STATUS, Value::Number(0)),
41     (column::SYNC_STATUS, Value::Number(0)),
42 ];
43 
44 const TEST_FILE: &str = "/data/asset_test/0";
45 
create_dir()46 fn create_dir() {
47     let path = Path::new(TEST_FILE);
48     if !path.exists() {
49         fs::create_dir_all(path).unwrap();
50     }
51 }
52 
remove_dir()53 fn remove_dir() {
54     let path = Path::new(TEST_FILE);
55     if path.exists() {
56         fs::remove_dir_all(path).unwrap();
57     }
58 }
59 
open_db_and_insert_data() -> Database60 fn open_db_and_insert_data() -> Database {
61     create_dir();
62     let mut def = DbMap::from(DB_DATA);
63     add_bytes_column(&mut def);
64     let calling_info = CallingInfo::new_self();
65     let mut db =
66         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
67             .unwrap();
68     let count = db.insert_datas(&def).unwrap();
69     assert_eq!(count, 1);
70     db
71 }
72 
add_bytes_column(db_data: &mut DbMap)73 fn add_bytes_column(db_data: &mut DbMap) {
74     db_data.insert(column::SECRET, Value::Bytes(column::SECRET.as_bytes().to_vec()));
75     db_data.insert(column::ALIAS, Value::Bytes(column::ALIAS.as_bytes().to_vec()));
76     db_data.insert(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()));
77     db_data.insert(column::CREATE_TIME, Value::Bytes(column::CREATE_TIME.as_bytes().to_vec()));
78     db_data.insert(column::UPDATE_TIME, Value::Bytes(column::UPDATE_TIME.as_bytes().to_vec()));
79 }
80 
backup_db(db: &Database)81 fn backup_db(db: &Database) {
82     fs::copy(&db.path, &db.backup_path).unwrap();
83 }
84 
85 #[test]
create_and_drop_database()86 fn create_and_drop_database() {
87     fs::create_dir_all("/data/asset_test/0").unwrap();
88     let calling_info = CallingInfo::new_self();
89     let mut db =
90         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
91             .unwrap();
92     backup_db(&db);
93     db.close_db();
94     assert!(Database::delete(0, &db.db_name).is_ok());
95 }
96 
97 #[test]
database_version()98 fn database_version() {
99     fs::create_dir_all("/data/asset_test/0").unwrap();
100     let calling_info = CallingInfo::new_self();
101     let db = Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
102         .unwrap();
103     assert_eq!(3, db.get_version().unwrap());
104     assert!(db.set_version(2).is_ok());
105     assert_eq!(2, db.get_version().unwrap());
106     let _ = Database::delete(0, &db.db_name);
107 }
108 
109 #[test]
error_sql()110 fn error_sql() {
111     fs::create_dir_all("/data/asset_test/0").unwrap();
112     let calling_info = CallingInfo::new_self();
113     let db = Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
114         .unwrap();
115     let sql = "pragma zzz user_version = {} mmm";
116     assert!(db.exec(sql).is_err());
117     let _ = Database::delete(0, &db.db_name);
118 }
119 
120 #[test]
create_delete_asset_table()121 fn create_delete_asset_table() {
122     fs::create_dir_all("/data/asset_test/0").unwrap();
123     let calling_info = CallingInfo::new_self();
124     let mut db =
125         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
126             .unwrap();
127     let table = Table::new(TABLE_NAME, &db);
128     assert!(table.exist().unwrap());
129     assert!(table.delete().is_ok());
130     assert!(!table.exist().unwrap());
131     db.close_db();
132     let _ = Database::delete(0, &db.db_name);
133 }
134 
135 #[test]
insert_data_with_different_alias()136 fn insert_data_with_different_alias() {
137     create_dir();
138     let mut def = DbMap::from(DB_DATA);
139     add_bytes_column(&mut def);
140 
141     let calling_info = CallingInfo::new_self();
142     let mut db =
143         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
144             .unwrap();
145     let count = db.insert_datas(&def).unwrap();
146     assert_eq!(count, 1);
147 
148     def.insert(column::ALIAS, Value::Bytes(b"Alias2".to_vec()));
149     let count = db.insert_datas(&def).unwrap();
150     assert_eq!(count, 1);
151 
152     let ret = db
153         .query_datas(
154             &vec![],
155             &DbMap::from([(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()))]),
156             None,
157             false,
158         )
159         .unwrap();
160     assert_eq!(ret.len(), 2);
161     remove_dir();
162 }
163 
164 #[test]
delete_data()165 fn delete_data() {
166     let mut db = open_db_and_insert_data();
167 
168     let mut datas = DbMap::new();
169     datas.insert(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()));
170     datas.insert(column::ALIAS, Value::Bytes(column::ALIAS.as_bytes().to_vec()));
171 
172     let ret = db.is_data_exists(&datas, false).unwrap();
173     assert!(ret);
174 
175     let count = db.delete_datas(&datas, None, false).unwrap();
176     assert_eq!(count, 1);
177 
178     let ret = db.is_data_exists(&datas, false).unwrap();
179     assert!(!ret);
180 
181     remove_dir();
182 }
183 
184 #[test]
update_data()185 fn update_data() {
186     let mut db = open_db_and_insert_data();
187 
188     let mut datas = DbMap::new();
189     datas.insert(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()));
190     datas.insert(column::ALIAS, Value::Bytes(column::ALIAS.as_bytes().to_vec()));
191     let update_time: Vec<u8> = vec![2];
192     let count = db
193         .update_datas(&datas, true, &DbMap::from([(column::UPDATE_TIME, Value::Bytes(update_time.clone()))]))
194         .unwrap();
195     assert_eq!(count, 1);
196 
197     let res = db.query_datas(&vec![], &datas, None, false).unwrap();
198     assert_eq!(res.len(), 1);
199     let query_update_time = res[0].get_bytes_attr(&column::UPDATE_TIME).unwrap();
200     assert_eq!(update_time.len(), query_update_time.len());
201     for (ins, qy) in update_time.iter().zip(query_update_time.iter()) {
202         assert_eq!(*ins, *qy);
203     }
204 
205     remove_dir();
206 }
207 
208 #[test]
query_ordered_data()209 fn query_ordered_data() {
210     // insert two data
211     create_dir();
212     let mut def = DbMap::from(DB_DATA);
213     add_bytes_column(&mut def);
214 
215     let calling_info = CallingInfo::new_self();
216     let mut db =
217         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
218             .unwrap();
219     let count = db.insert_datas(&def).unwrap();
220     assert_eq!(count, 1);
221 
222     def.insert(column::ALIAS, Value::Bytes(b"AAA".to_vec()));
223     let count = db.insert_datas(&def).unwrap();
224     assert_eq!(count, 1);
225 
226     // query data by order
227     let query = QueryOptions {
228         limit: Some(100),
229         offset: Some(0),
230         order: Some(Ordering::Greater),
231         order_by: Some(vec![column::ALIAS]),
232     };
233     let res = db
234         .query_datas(
235             &vec![column::ID, column::ALIAS],
236             &DbMap::from([(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()))]),
237             Some(&query),
238             false,
239         )
240         .unwrap();
241     assert_eq!(res.len(), 2);
242     assert_eq!(&(b"AAA".to_vec()), res[0].get_bytes_attr(&column::ALIAS).unwrap());
243 
244     remove_dir();
245 }
246 
247 #[test]
insert_error_data()248 fn insert_error_data() {
249     create_dir();
250     let mut datas = DbMap::new();
251     datas.insert(column::OWNER, Value::Bytes(column::OWNER.as_bytes().to_vec()));
252     let calling_info = CallingInfo::new_self();
253     let mut db =
254         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
255             .unwrap();
256     assert!(db.insert_datas(&datas).is_err());
257     remove_dir();
258 }
259 
260 #[test]
backup_and_restore()261 fn backup_and_restore() {
262     let db = open_db_and_insert_data();
263     backup_db(&db);
264     drop(db);
265 
266     // Destroy the main database.
267     let mut db_file =
268         OpenOptions::new().read(true).write(true).open("/data/asset_test/0/Native_asset_service_8100.db").unwrap();
269     let _ = db_file.write(b"buffer buffer buffer").unwrap();
270 
271     // Recovery the main database.
272     let calling_info = CallingInfo::new_self();
273     let mut db =
274         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
275             .unwrap();
276     let mut def = DbMap::from(DB_DATA);
277     add_bytes_column(&mut def);
278 
279     db.query_datas(&vec![], &def, None, false).unwrap();
280     drop(db);
281     remove_dir();
282 }
283 
284 #[test]
insert_duplicated_data()285 fn insert_duplicated_data() {
286     let mut db = open_db_and_insert_data();
287 
288     let mut def = DbMap::from(DB_DATA);
289     add_bytes_column(&mut def);
290     assert_eq!(ErrCode::Duplicated, db.insert_datas(&def).unwrap_err().code);
291 
292     drop(db);
293     remove_dir();
294 }
295 
296 #[test]
query_mismatch_type_data()297 fn query_mismatch_type_data() {
298     create_dir();
299     let mut data = DbMap::from(DB_DATA);
300     add_bytes_column(&mut data);
301     data.insert(column::CREATE_TIME, Value::Number(1));
302     let calling_info = CallingInfo::new_self();
303     let mut db =
304         Database::build(calling_info.user_id(), calling_info.owner_type_enum(), calling_info.owner_info(), false)
305             .unwrap();
306     db.insert_datas(&data).unwrap();
307 
308     assert_eq!(ErrCode::FileOperationError, db.query_datas(&vec![], &data, None, false).unwrap_err().code);
309     drop(db);
310     remove_dir();
311 }
312