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 }