1 /*
2 * Copyright (c) 2022 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 #ifndef OMIT_MULTI_VER
17 #include <gtest/gtest.h>
18
19 #include "distributeddb_data_generate_unit_test.h"
20 #include "kvdb_manager.h"
21 #include "native_sqlite.h"
22 #include "sqlite_local_kvdb.h"
23 #include "sqlite_local_kvdb_connection.h"
24
25 using namespace testing::ext;
26 using namespace DistributedDB;
27 using namespace DistributedDBUnitTest;
28 using namespace std;
29
30 namespace {
31 string g_testDir;
32 SQLiteLocalKvDBConnection *g_connection = nullptr;
33 SQLiteLocalKvDB *g_invalidDb = nullptr;
34 SQLiteLocalKvDBConnection *g_invalidConnection = nullptr;
35
CreateConnInInvalidDb()36 void CreateConnInInvalidDb()
37 {
38 ASSERT_EQ(g_invalidDb, nullptr);
39 g_invalidConnection = new (std::nothrow) SQLiteLocalKvDBConnection(g_invalidDb);
40 ASSERT_NE(g_invalidConnection, nullptr);
41 }
42
CloseConnInInvalidDb()43 void CloseConnInInvalidDb()
44 {
45 if (g_invalidConnection != nullptr) {
46 delete g_invalidConnection;
47 g_invalidConnection = nullptr;
48 }
49 }
50
CreateConnInNewDb()51 void CreateConnInNewDb()
52 {
53 g_invalidDb = new (std::nothrow) SQLiteLocalKvDB();
54 ASSERT_NE(g_invalidDb, nullptr);
55 int errCode;
56 g_invalidConnection = static_cast<SQLiteLocalKvDBConnection *>(g_invalidDb->GetDBConnection(errCode));
57 ASSERT_NE(g_invalidConnection, nullptr);
58 RefObject::DecObjRef(g_invalidDb);
59 }
60
CloseConnInNewDb()61 void CloseConnInNewDb()
62 {
63 if (g_invalidConnection != nullptr) {
64 EXPECT_EQ(g_invalidConnection->Close(), E_OK);
65 g_invalidConnection = nullptr;
66 g_invalidDb = nullptr;
67 }
68 if (g_invalidDb != nullptr) {
69 delete g_invalidDb;
70 g_invalidDb = nullptr;
71 }
72 }
73 }
74
75 class DistributedDBStorageDataConnectionTest : public testing::Test {
76 public:
77 static void SetUpTestCase(void);
78 static void TearDownTestCase(void);
79 void SetUp();
80 void TearDown();
81 };
82
SetUpTestCase(void)83 void DistributedDBStorageDataConnectionTest::SetUpTestCase(void)
84 {
85 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
86 }
87
TearDownTestCase(void)88 void DistributedDBStorageDataConnectionTest::TearDownTestCase(void)
89 {
90 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
91 LOGE("rm test db files error!");
92 }
93 }
94
SetUp(void)95 void DistributedDBStorageDataConnectionTest::SetUp(void)
96 {
97 DistributedDBToolsUnitTest::PrintTestCaseInfo();
98 KvDBProperties properties;
99 properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
100 properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE);
101 properties.SetStringProp(KvDBProperties::DATA_DIR, g_testDir);
102 properties.SetStringProp(KvDBProperties::STORE_ID, "test");
103 properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "test");
104
105 int errCode = E_OK;
106 g_connection = static_cast<SQLiteLocalKvDBConnection *>(KvDBManager::GetDatabaseConnection(properties, errCode));
107 EXPECT_EQ(errCode, E_OK);
108 ASSERT_NE(g_connection, nullptr);
109 }
110
TearDown(void)111 void DistributedDBStorageDataConnectionTest::TearDown(void)
112 {
113 if (g_connection != nullptr) {
114 g_connection->Close();
115 g_connection = nullptr;
116 }
117 CloseConnInInvalidDb();
118 CloseConnInNewDb();
119 return;
120 }
121
122 /**
123 * @tc.name: ConnectionTest001
124 * @tc.desc: Get value from abnormal connection
125 * @tc.type: FUNC
126 * @tc.require:
127 * @tc.author: bty
128 */
129 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest001, TestSize.Level1)
130 {
131 /**
132 * @tc.steps: step1. Create a connection when the db is null
133 * @tc.expected: step1. Expect not null
134 */
135 CreateConnInInvalidDb();
136
137 /**
138 * @tc.steps: step2 Get value
139 * @tc.expected: step2. Expect -E_INVALID_DB
140 */
141 IOption option;
142 Value value;
143 EXPECT_EQ(g_invalidConnection->Get(option, KEY_3, value), -E_INVALID_DB);
144 CloseConnInInvalidDb();
145
146 /**
147 * @tc.steps: step3. Use db to create a new connection, but db is not open
148 * @tc.expected: step3. Expect not null
149 */
150 CreateConnInNewDb();
151
152 /**
153 * @tc.steps: step4. Get value
154 * @tc.expected: step4. Expect -E_INVALID_DB
155 */
156 EXPECT_EQ(g_invalidConnection->Get(option, KEY_3, value), -E_INVALID_DB);
157 CloseConnInNewDb();
158 }
159
160 /**
161 * @tc.name: ConnectionTest002
162 * @tc.desc: Delete and clear from abnormal connection
163 * @tc.type: FUNC
164 * @tc.require:
165 * @tc.author: bty
166 */
167 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest002, TestSize.Level1)
168 {
169 /**
170 * @tc.steps: step1. Use db to create a new connection, but db is not open
171 * @tc.expected: step1. Expect not null
172 */
173 CreateConnInNewDb();
174
175 /**
176 * @tc.steps: step2. Clear and delete
177 * @tc.expected: step2. Expect -E_INVALID_DB
178 */
179 IOption option;
180 Value value;
181 EXPECT_EQ(g_invalidConnection->Delete(option, KEY_3), -E_INVALID_DB);
182 EXPECT_EQ(g_invalidConnection->Clear(option), -E_INVALID_DB);
183 CloseConnInNewDb();
184 }
185
186 /**
187 * @tc.name: ConnectionTest003
188 * @tc.desc: Get entries from abnormal connection
189 * @tc.type: FUNC
190 * @tc.require:
191 * @tc.author: bty
192 */
193 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest003, TestSize.Level1)
194 {
195 /**
196 * @tc.steps: step1. Create a connection when the db is null
197 * @tc.expected: step1. Expect not null
198 */
199 CreateConnInInvalidDb();
200
201 /**
202 * @tc.steps: step2. Get entries
203 * @tc.expected: step2. Expect -E_INVALID_DB
204 */
205 IOption option;
206 std::vector<Entry> entry;
207 Key key(DBConstant::MAX_KEY_SIZE + 1, 'w');
208 EXPECT_EQ(g_invalidConnection->GetEntries(option, key, entry), -E_INVALID_DB);
209 CloseConnInInvalidDb();
210
211 /**
212 * @tc.steps: step3. Key is over size
213 * @tc.expected: step3. Expect -E_INVALID_ARGS
214 */
215 CreateConnInNewDb();
216 EXPECT_EQ(g_invalidConnection->GetEntries(option, key, entry), -E_INVALID_ARGS);
217
218 /**
219 * @tc.steps: step4. Key is normal, but the db not open
220 * @tc.expected: step4. Expect -E_INVALID_DB
221 */
222 EXPECT_EQ(g_invalidConnection->GetEntries(option, KEY_3, entry), -E_INVALID_DB);
223 CloseConnInNewDb();
224 }
225
226 /**
227 * @tc.name: ConnectionTest004
228 * @tc.desc: Put batch from abnormal connection
229 * @tc.type: FUNC
230 * @tc.require:
231 * @tc.author: bty
232 */
233 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest004, TestSize.Level1)
234 {
235 /**
236 * @tc.steps: step1. Create a connection when the db is null
237 * @tc.expected: step1. Expect not null
238 */
239 CreateConnInInvalidDb();
240
241 /**
242 * @tc.steps: step2. Put empty entries
243 * @tc.expected: step2. Expect -E_INVALID_ARGS
244 */
245 IOption option;
246 std::vector<Entry> entry;
247 EXPECT_EQ(g_invalidConnection->PutBatch(option, entry), -E_INVALID_ARGS);
248
249 /**
250 * @tc.steps: step3. Entries is normal, but the db is null
251 * @tc.expected: step3. Expect -E_INVALID_ARGS
252 */
253 Value value;
254 Entry ent = {KEY_3, value};
255 entry.push_back(ent);
256 EXPECT_EQ(g_invalidConnection->PutBatch(option, entry), -E_INVALID_ARGS);
257 CloseConnInInvalidDb();
258
259 /**
260 * @tc.steps: step4. The db is not open
261 * @tc.expected: step4. Expect -E_INVALID_DB
262 */
263 CreateConnInNewDb();
264 EXPECT_EQ(g_invalidConnection->PutBatch(option, entry), -E_INVALID_DB);
265 CloseConnInNewDb();
266 }
267
268 /**
269 * @tc.name: ConnectionTest005
270 * @tc.desc: Delete batch from abnormal connection
271 * @tc.type: FUNC
272 * @tc.require:
273 * @tc.author: bty
274 */
275 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest005, TestSize.Level1)
276 {
277 /**
278 * @tc.steps: step1. Create a connection when the db is null
279 * @tc.expected: step1. Expect not null
280 */
281 CreateConnInInvalidDb();
282
283 /**
284 * @tc.steps: step2. delete, but the keys is empty
285 * @tc.expected: step2. Expect -E_INVALID_ARGS
286 */
287 IOption option;
288 std::vector<Key> keys;
289 EXPECT_EQ(g_invalidConnection->DeleteBatch(option, keys), -E_INVALID_ARGS);
290
291 /**
292 * @tc.steps: step3. The key is over size
293 * @tc.expected: step3. Expect -E_INVALID_ARGS
294 */
295 Key key(DBConstant::MAX_KEY_SIZE + 1, 'w');
296 keys.push_back(key);
297 EXPECT_EQ(g_invalidConnection->DeleteBatch(option, keys), -E_INVALID_ARGS);
298
299 /**
300 * @tc.steps: step4. key is normal , but the db is null
301 * @tc.expected: step4. Expect -E_INVALID_DB
302 */
303 keys.clear();
304 keys.push_back(KEY_3);
305 EXPECT_EQ(g_invalidConnection->DeleteBatch(option, keys), -E_INVALID_DB);
306 CloseConnInInvalidDb();
307 }
308
309 /**
310 * @tc.name: ConnectionTest006
311 * @tc.desc: Get snapshot from abnormal connection
312 * @tc.type: FUNC
313 * @tc.require:
314 * @tc.author: bty
315 */
316 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest006, TestSize.Level1)
317 {
318 /**
319 * @tc.steps: step1. Create a connection when the db is null
320 * @tc.expected: step1. Expect not null
321 */
322 CreateConnInInvalidDb();
323
324 /**
325 * @tc.steps: step2. the db is null
326 * @tc.expected: step2. Expect -E_INVALID_DB
327 */
328 IKvDBSnapshot *snapshot = nullptr;
329 EXPECT_EQ(g_invalidConnection->GetSnapshot(snapshot), -E_INVALID_DB);
330 CloseConnInInvalidDb();
331
332 /**
333 * @tc.steps: step3. GetSnapshot after changing db operate perm to DISABLE_PERM
334 * @tc.expected: step3. Expect -E_STALE
335 */
336 SQLiteLocalKvDB *localKvdb = new (std::nothrow) SQLiteLocalKvDB();
337 ASSERT_NE(localKvdb, nullptr);
338 EXPECT_EQ(localKvdb->TryToDisableConnection(OperatePerm::DISABLE_PERM), E_OK);
339 int errCode;
340 SQLiteLocalKvDBConnection *connection =
341 static_cast<SQLiteLocalKvDBConnection *>(localKvdb->NewConnection(errCode));
342 ASSERT_NE(connection, nullptr);
343 EXPECT_EQ(connection->GetSnapshot(snapshot), -E_STALE);
344 EXPECT_EQ(connection->Close(), E_OK);
345 connection = nullptr;
346 localKvdb = nullptr;
347
348 /**
349 * @tc.steps: step4. Get snapshot from normal db, then preClose
350 * @tc.expected: step4. Expect -E_BUSY
351 */
352 EXPECT_EQ(g_connection->GetSnapshot(snapshot), E_OK);
353 EXPECT_EQ(g_connection->PreClose(), -E_BUSY);
354 g_connection->ReleaseSnapshot(snapshot);
355 }
356
357 /**
358 * @tc.name: ConnectionTest007
359 * @tc.desc: Test transaction from abnormal connection
360 * @tc.type: FUNC
361 * @tc.require:
362 * @tc.author: bty
363 */
364 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest007, TestSize.Level1)
365 {
366 /**
367 * @tc.steps: step1. Start transaction when the db is null
368 * @tc.expected: step1. Expect -E_INVALID_DB
369 */
370 CreateConnInInvalidDb();
371 EXPECT_EQ(g_invalidConnection->StartTransaction(), -E_INVALID_DB);
372 CloseConnInInvalidDb();
373
374 /**
375 * @tc.steps: step2. Start transaction and rollback
376 * @tc.expected: step2. Expect true after StartTransaction, false after rollback
377 */
378 g_connection->StartTransaction();
379 EXPECT_EQ(g_connection->IsTransactionStarted(), true);
380 g_connection->RollBack();
381 EXPECT_EQ(g_connection->IsTransactionStarted(), false);
382 }
383
384 /**
385 * @tc.name: ConnectionTest008
386 * @tc.desc: Export,import and rekey from abnormal connection
387 * @tc.type: FUNC
388 * @tc.require:
389 * @tc.author: bty
390 */
391 HWTEST_F(DistributedDBStorageDataConnectionTest, ConnectionTest008, TestSize.Level1)
392 {
393 /**
394 * @tc.steps: step1. the db is null
395 * @tc.expected: step1. Expect -E_INVALID_DB
396 */
397 CreateConnInInvalidDb();
398 CipherPassword passwd;
399 string filePath = g_testDir + "/ExportTest.db";
400 EXPECT_EQ(g_invalidConnection->Rekey(passwd), -E_INVALID_DB);
401 EXPECT_EQ(g_invalidConnection->Export(filePath, passwd), -E_INVALID_DB);
402 EXPECT_EQ(g_invalidConnection->Import(filePath, passwd), -E_INVALID_DB);
403 CloseConnInInvalidDb();
404
405 /**
406 * @tc.steps: step2. Make OperatePerm not equal to NORMAL_PERM
407 * @tc.expected: step2. Expect -E_BUSY
408 */
409 SQLiteLocalKvDB *localKvdb = new (std::nothrow) SQLiteLocalKvDB();
410 ASSERT_NE(localKvdb, nullptr);
411 EXPECT_EQ(localKvdb->TryToDisableConnection(OperatePerm::DISABLE_PERM), E_OK);
412 int errCode;
413 SQLiteLocalKvDBConnection *connection =
414 static_cast<SQLiteLocalKvDBConnection *>(localKvdb->NewConnection(errCode));
415 ASSERT_NE(connection, nullptr);
416 EXPECT_EQ(connection->Import(filePath, passwd), -E_BUSY);
417 EXPECT_EQ(connection->Close(), E_OK);
418 connection = nullptr;
419 localKvdb = nullptr;
420
421 /**
422 * @tc.steps: step3. Test in transaction
423 * @tc.expected: step3. Expect -E_BUSY
424 */
425 g_connection->StartTransaction();
426 EXPECT_EQ(g_connection->Rekey(passwd), -E_BUSY);
427 EXPECT_EQ(g_connection->Import(filePath, passwd), -E_BUSY);
428 g_connection->RollBack();
429
430 /**
431 * @tc.steps: step4. Test after Registering observer
432 * @tc.expected: step4. Expect -E_BUSY
433 */
434 int result;
435 Key key;
436 key.push_back('a');
__anon5b1490a50202(const KvDBCommitNotifyData &data) 437 KvDBObserverAction func = [&](const KvDBCommitNotifyData &data) {};
438 KvDBObserverHandle *handle = g_connection->RegisterObserver(
439 static_cast<unsigned int>(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), key,
440 func, result);
441 EXPECT_EQ(result, E_OK);
442 ASSERT_NE(handle, nullptr);
443 EXPECT_EQ(g_connection->Rekey(passwd), -E_BUSY);
444 EXPECT_EQ(g_connection->Import(filePath, passwd), -E_BUSY);
445 g_connection->UnRegisterObserver(handle);
446 }
447 #endif // OMIT_MULTI_VER