1 /*
2  * Copyright (c) 2024 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 #include "rdb_store_impl.h"
16 
17 #include <gtest/gtest.h>
18 
19 #include <map>
20 #include <string>
21 #include <fstream>
22 
23 #include "common.h"
24 #include "rdb_errno.h"
25 #include "rdb_helper.h"
26 #include "rdb_open_callback.h"
27 
28 using namespace testing::ext;
29 using namespace OHOS::NativeRdb;
30 
31 class RdbStoreBackupRestoreTest : public testing::Test {
32 public:
SetUpTestCase()33     static void SetUpTestCase() {}
TearDownTestCase()34     static void TearDownTestCase() {}
SetUp()35     void SetUp() {}
TearDown()36     void TearDown() {}
37     void CheckResultSet(std::shared_ptr<RdbStore> &store);
38     void CheckAge(std::shared_ptr<ResultSet> &resultSet);
39     void CheckSalary(std::shared_ptr<ResultSet> &resultSet);
40     void CheckBlob(std::shared_ptr<ResultSet> &resultSet);
41 
42     static constexpr char DATABASE_NAME[] = "/data/test/backup_restore_test.db";
43     static constexpr char BACKUP_DATABASE_NAME[] = "/data/test/backup_restore_test_backup.db";
44 };
45 
46 class RdbStoreBackupRestoreTestOpenCallback : public RdbOpenCallback {
47 public:
48     int OnCreate(RdbStore &store) override;
49     int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
50     static const std::string CREATE_TABLE_TEST;
51 };
52 
53 const std::string RdbStoreBackupRestoreTestOpenCallback::CREATE_TABLE_TEST =
54     std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, "
55                                                                   "name TEXT NOT NULL, age INTEGER, salary "
56                                                                   "REAL, blobType BLOB)");
57 
OnCreate(RdbStore & store)58 int RdbStoreBackupRestoreTestOpenCallback::OnCreate(RdbStore &store)
59 {
60     return store.ExecuteSql(CREATE_TABLE_TEST);
61 }
62 
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)63 int RdbStoreBackupRestoreTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
64 {
65     return E_OK;
66 }
67 
CheckResultSet(std::shared_ptr<RdbStore> & store)68 void RdbStoreBackupRestoreTest::CheckResultSet(std::shared_ptr<RdbStore> &store)
69 {
70     std::shared_ptr<ResultSet> resultSet =
71         store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector<std::string>{ "zhangsan" });
72     EXPECT_NE(resultSet, nullptr);
73 
74     int columnIndex;
75     int intVal;
76     std::string strVal;
77     ColumnType columnType;
78     int position;
79     int ret = resultSet->GetRowIndex(position);
80     EXPECT_EQ(ret, E_OK);
81     EXPECT_EQ(position, -1);
82 
83     ret = resultSet->GetColumnType(0, columnType);
84     EXPECT_EQ(ret, E_ROW_OUT_RANGE);
85 
86     ret = resultSet->GoToFirstRow();
87     EXPECT_EQ(ret, E_OK);
88 
89     ret = resultSet->GetColumnIndex("id", columnIndex);
90     EXPECT_EQ(ret, E_OK);
91     EXPECT_EQ(columnIndex, 0);
92     ret = resultSet->GetColumnType(columnIndex, columnType);
93     EXPECT_EQ(ret, E_OK);
94     EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
95     ret = resultSet->GetInt(columnIndex, intVal);
96     EXPECT_EQ(ret, E_OK);
97     EXPECT_EQ(1, intVal);
98 
99     ret = resultSet->GetColumnIndex("name", columnIndex);
100     EXPECT_EQ(ret, E_OK);
101     ret = resultSet->GetColumnType(columnIndex, columnType);
102     EXPECT_EQ(ret, E_OK);
103     EXPECT_EQ(columnType, ColumnType::TYPE_STRING);
104     ret = resultSet->GetString(columnIndex, strVal);
105     EXPECT_EQ(ret, E_OK);
106     EXPECT_EQ("zhangsan", strVal);
107 
108     CheckAge(resultSet);
109     CheckSalary(resultSet);
110     CheckBlob(resultSet);
111 
112     ret = resultSet->GoToNextRow();
113     EXPECT_EQ(ret, E_ROW_OUT_RANGE);
114 
115     ret = resultSet->GetColumnType(columnIndex, columnType);
116     EXPECT_EQ(ret, E_ROW_OUT_RANGE);
117 
118     ret = resultSet->Close();
119     EXPECT_EQ(ret, E_OK);
120 }
121 
CheckAge(std::shared_ptr<ResultSet> & resultSet)122 void RdbStoreBackupRestoreTest::CheckAge(std::shared_ptr<ResultSet> &resultSet)
123 {
124     int columnIndex;
125     int intVal;
126     ColumnType columnType;
127     int ret = resultSet->GetColumnIndex("age", columnIndex);
128     EXPECT_EQ(ret, E_OK);
129     ret = resultSet->GetColumnType(columnIndex, columnType);
130     EXPECT_EQ(ret, E_OK);
131     EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER);
132     ret = resultSet->GetInt(columnIndex, intVal);
133     EXPECT_EQ(ret, E_OK);
134     // 18: age is 18
135     EXPECT_EQ(18, intVal);
136 }
137 
CheckSalary(std::shared_ptr<ResultSet> & resultSet)138 void RdbStoreBackupRestoreTest::CheckSalary(std::shared_ptr<ResultSet> &resultSet)
139 {
140     int columnIndex;
141     double dVal;
142     ColumnType columnType;
143     int ret = resultSet->GetColumnIndex("salary", columnIndex);
144     EXPECT_EQ(ret, E_OK);
145     ret = resultSet->GetColumnType(columnIndex, columnType);
146     EXPECT_EQ(ret, E_OK);
147     EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT);
148     ret = resultSet->GetDouble(columnIndex, dVal);
149     EXPECT_EQ(ret, E_OK);
150     // 100.5: salary is 100.5
151     EXPECT_EQ(100.5, dVal);
152 }
153 
CheckBlob(std::shared_ptr<ResultSet> & resultSet)154 void RdbStoreBackupRestoreTest::CheckBlob(std::shared_ptr<ResultSet> &resultSet)
155 {
156     int columnIndex;
157     std::vector<uint8_t> blob;
158     ColumnType columnType;
159     int ret = resultSet->GetColumnIndex("blobType", columnIndex);
160     EXPECT_EQ(ret, E_OK);
161     ret = resultSet->GetColumnType(columnIndex, columnType);
162     EXPECT_EQ(ret, E_OK);
163     EXPECT_EQ(columnType, ColumnType::TYPE_BLOB);
164     ret = resultSet->GetBlob(columnIndex, blob);
165     EXPECT_EQ(ret, E_OK);
166     // 3: blob size
167     EXPECT_EQ(3, static_cast<int>(blob.size()));
168     // 1: blob[0] is 1
169     EXPECT_EQ(1, blob[0]);
170     // 2: blob[1] is 2
171     EXPECT_EQ(2, blob[1]);
172     // 3: blob[2] is 3
173     EXPECT_EQ(3, blob[2]);
174 }
175 
176 /* *
177  * @tc.name: Rdb_BackupRestoreTest_001
178  * @tc.desc: backup and restore
179  * @tc.type: FUNC
180  */
181 HWTEST_F(RdbStoreBackupRestoreTest, Rdb_BackupRestoreTest_001, TestSize.Level2)
182 {
183     int errCode = E_OK;
184     RdbStoreConfig config(RdbStoreBackupRestoreTest::DATABASE_NAME);
185     config.SetEncryptStatus(true);
186     RdbStoreBackupRestoreTestOpenCallback helper;
187     auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
188     EXPECT_EQ(errCode, E_OK);
189     EXPECT_NE(store, nullptr);
190 
191     int64_t id;
192     ValuesBucket values;
193 
194     values.PutInt("id", 1);
195     values.PutString("name", std::string("zhangsan"));
196     values.PutInt("age", 18);
197     values.PutDouble("salary", 100.5);
198     values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
199     int ret = store->Insert(id, "test", values);
200     EXPECT_EQ(ret, E_OK);
201     EXPECT_EQ(1, id);
202 
203     ret = store->Backup(BACKUP_DATABASE_NAME);
204     EXPECT_EQ(ret, E_OK);
205 
206     int deletedRows = 0;
207     ret = store->Delete(deletedRows, "test", "id = 1");
208     EXPECT_EQ(ret, E_OK);
209     EXPECT_EQ(1, deletedRows);
210 
211     ret = store->Restore(BACKUP_DATABASE_NAME);
212     EXPECT_EQ(ret, E_OK);
213 
214     CheckResultSet(store);
215 
216     RdbHelper::DeleteRdbStore(RdbStoreBackupRestoreTest::DATABASE_NAME);
217     RdbHelper::DeleteRdbStore(RdbStoreBackupRestoreTest::BACKUP_DATABASE_NAME);
218 }
219 
220 /* *
221  * @tc.name: Rdb_BackupRestoreTest_002
222  * @tc.desc: backup and restore for broken original and broken backup db
223  * @tc.type: FUNC
224  */
225 HWTEST_F(RdbStoreBackupRestoreTest, Rdb_BackupRestoreTest_002, TestSize.Level2)
226 {
227     int errCode = E_OK;
228     RdbStoreConfig config(DATABASE_NAME);
229     config.SetEncryptStatus(true);
230     RdbStoreBackupRestoreTestOpenCallback helper;
231     auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
232     EXPECT_EQ(errCode, E_OK);
233     EXPECT_NE(store, nullptr);
234 
235     int64_t id;
236     ValuesBucket values;
237 
238     values.PutInt("id", 1);
239     values.PutString("name", std::string("zhangsan"));
240     values.PutInt("age", 18);
241     values.PutDouble("salary", 100.5);
242     values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
243     int ret = store->Insert(id, "test", values);
244     EXPECT_EQ(ret, E_OK);
245     EXPECT_EQ(1, id);
246 
247     ret = store->Backup(BACKUP_DATABASE_NAME);
248     EXPECT_EQ(ret, E_OK);
249     store = nullptr;
250 
251     std::ofstream fsDb(DATABASE_NAME, std::ios_base::binary | std::ios_base::out);
252     fsDb.seekp(64);
253     fsDb.write("hello", 5);
254     fsDb.close();
255     std::ofstream fsBackupDb(BACKUP_DATABASE_NAME, std::ios_base::binary | std::ios_base::out);
256     fsBackupDb.seekp(64);
257     fsBackupDb.write("hello", 5);
258     fsBackupDb.close();
259 
260     store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
261     EXPECT_EQ(errCode, E_SQLITE_CORRUPT);
262     RdbHelper::DeleteRdbStore(DATABASE_NAME);
263 
264     store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
265     EXPECT_EQ(errCode, E_OK);
266 
267     ret = store->Restore(BACKUP_DATABASE_NAME);
268     EXPECT_EQ(ret, E_SQLITE_CORRUPT);
269 
270     ret = store->ExecuteSql(RdbStoreBackupRestoreTestOpenCallback::CREATE_TABLE_TEST);
271     EXPECT_EQ(ret, E_OK);
272 
273     RdbHelper::DeleteRdbStore(DATABASE_NAME);
274     RdbHelper::DeleteRdbStore(BACKUP_DATABASE_NAME);
275 }
276 
277 /* *
278  * @tc.name: Rdb_BackupRestoreTest_003
279  * @tc.desc: backup and restore
280  * @tc.type: FUNC
281  */
282 HWTEST_F(RdbStoreBackupRestoreTest, Rdb_BackupRestoreTest_003, TestSize.Level2)
283 {
284     int errCode = E_OK;
285     RdbStoreConfig config(RdbStoreBackupRestoreTest::DATABASE_NAME);
286     config.SetEncryptStatus(true);
287     config.SetAllowRebuild(true);
288     config.SetHaMode(HAMode::MAIN_REPLICA);
289     RdbStoreBackupRestoreTestOpenCallback helper;
290     auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
291     EXPECT_EQ(errCode, E_OK);
292     EXPECT_NE(store, nullptr);
293 
294     int64_t id;
295     ValuesBucket values;
296 
297     values.PutInt("id", 1);
298     values.PutString("name", std::string("zhangsan"));
299     values.PutInt("age", 18);
300     values.PutDouble("salary", 100.5);
301     values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
302     int ret = store->Insert(id, "test", values);
303     EXPECT_EQ(ret, E_OK);
304     EXPECT_EQ(1, id);
305 
306     ret = store->Backup(BACKUP_DATABASE_NAME);
307     EXPECT_EQ(ret, E_OK);
308 
309     int deletedRows = 0;
310     ret = store->Delete(deletedRows, "test", "id = 1");
311     EXPECT_EQ(ret, E_OK);
312     EXPECT_EQ(1, deletedRows);
313 
314     ret = store->Restore(BACKUP_DATABASE_NAME);
315     EXPECT_EQ(ret, E_OK);
316 
317     CheckResultSet(store);
318 
319     RdbHelper::DeleteRdbStore(RdbStoreBackupRestoreTest::DATABASE_NAME);
320     RdbHelper::DeleteRdbStore(RdbStoreBackupRestoreTest::BACKUP_DATABASE_NAME);
321 }