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 #include <gtest/gtest.h>
17 #include <queue>
18 #include <random>
19
20 #include "db_common.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "log_print.h"
24 #include "platform_specific.h"
25 #include "relational_store_manager.h"
26 #include "relational_store_sqlite_ext.h"
27 #include "relational_virtual_device.h"
28 #include "runtime_config.h"
29 #include "virtual_relational_ver_sync_db_interface.h"
30
31 using namespace testing::ext;
32 using namespace DistributedDB;
33 using namespace DistributedDBUnitTest;
34 using namespace std;
35
36 namespace {
37 constexpr const char *DB_SUFFIX = ".db";
38 constexpr const char *STORE_ID = "Relational_Store_ID";
39 std::string g_testDir;
40 std::string g_dbDir;
41 DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
42
43 const std::string DEVICE_A = "real_device";
44 const std::string DEVICE_B = "deviceB";
45 VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
46 RelationalVirtualDevice *g_deviceB = nullptr;
47
48 const std::string NORMAL_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS sync_data(" \
49 "key BLOB NOT NULL UNIQUE," \
50 "value BLOB," \
51 "timestamp INT NOT NULL," \
52 "flag INT NOT NULL," \
53 "device BLOB," \
54 "ori_device BLOB," \
55 "hash_key BLOB PRIMARY KEY NOT NULL," \
56 "w_timestamp INT," \
57 "UNIQUE(device, ori_device));" \
58 "CREATE INDEX key_index ON sync_data (key, flag);";
59
60 const std::string SIMPLE_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS t1(a INT, b TEXT)";
61
62 const std::string CREATE_TABLE_SQL_NO_PRIMARY_KEY = "CREATE TABLE IF NOT EXISTS sync_data(" \
63 "key BLOB NOT NULL UNIQUE," \
64 "value BLOB," \
65 "timestamp INT NOT NULL," \
66 "flag INT NOT NULL," \
67 "device BLOB," \
68 "ori_device BLOB," \
69 "hash_key BLOB NOT NULL," \
70 "w_timestamp INT," \
71 "UNIQUE(device, ori_device));" \
72 "CREATE INDEX key_index ON sync_data (key, flag);";
73
74 const std::string UNSUPPORTED_FIELD_TABLE_SQL = "CREATE TABLE IF NOT EXISTS test('$.ID' INT, val BLOB);";
75
76 const std::string COMPOSITE_PRIMARY_KEY_TABLE_SQL = R"(CREATE TABLE workers (
77 worker_id INTEGER,
78 last_name VARCHAR NOT NULL,
79 first_name VARCHAR,
80 join_date DATE,
81 PRIMARY KEY (last_name, first_name)
82 );)";
83
84 const std::string INSERT_SYNC_DATA_SQL = "INSERT OR REPLACE INTO sync_data (key, timestamp, flag, hash_key) "
85 "VALUES('KEY', 123456789, 1, 'HASH_KEY');";
86
87 const std::string INVALID_TABLE_FIELD_SQL = "create table if not exists t1 ('1 = 1; --' int primary key, b blob)";
88 }
89
90 class DistributedDBInterfacesRelationalTest : public testing::Test {
91 public:
92 static void SetUpTestCase(void);
93 static void TearDownTestCase(void);
94 void SetUp();
95 void TearDown();
96 };
97
SetUpTestCase(void)98 void DistributedDBInterfacesRelationalTest::SetUpTestCase(void)
99 {
100 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
101 LOGD("Test dir is %s", g_testDir.c_str());
102 g_dbDir = g_testDir + "/";
103 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
104
105 g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
106 ASSERT_TRUE(g_communicatorAggregator != nullptr);
107 RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
108 }
109
TearDownTestCase(void)110 void DistributedDBInterfacesRelationalTest::TearDownTestCase(void)
111 {
112 }
113
SetUp(void)114 void DistributedDBInterfacesRelationalTest::SetUp(void)
115 {
116 DistributedDBToolsUnitTest::PrintTestCaseInfo();
117
118 g_deviceB = new (std::nothrow) RelationalVirtualDevice(DEVICE_B);
119 ASSERT_TRUE(g_deviceB != nullptr);
120 auto *syncInterfaceB = new (std::nothrow) VirtualRelationalVerSyncDBInterface();
121 ASSERT_TRUE(syncInterfaceB != nullptr);
122 ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
123 auto permissionCheckCallback = [] (const std::string &userId, const std::string &appId, const std::string &storeId,
124 const std::string &deviceId, uint8_t flag) -> bool {
125 return true;
126 };
127 EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(permissionCheckCallback), OK);
128 }
129
TearDown(void)130 void DistributedDBInterfacesRelationalTest::TearDown(void)
131 {
132 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
133 if (g_deviceB != nullptr) {
134 delete g_deviceB;
135 g_deviceB = nullptr;
136 }
137 PermissionCheckCallbackV2 nullCallback;
138 EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(nullCallback), OK);
139 if (g_communicatorAggregator != nullptr) {
140 g_communicatorAggregator->RegOnDispatch(nullptr);
141 }
142 }
143
144 /**
145 * @tc.name: RelationalStoreTest001
146 * @tc.desc: Test open store and create distributed db
147 * @tc.type: FUNC
148 * @tc.require: AR000GK58F
149 * @tc.author: lianhuix
150 */
151 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize.Level1)
152 {
153 /**
154 * @tc.steps:step1. Prepare db file
155 * @tc.expected: step1. Return OK.
156 */
157 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
158 ASSERT_NE(db, nullptr);
159 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
160 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
161 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A");
162 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
163
164 /**
165 * @tc.steps:step2. open relational store, create distributed table, close store
166 * @tc.expected: step2. Return OK.
167 */
168 RelationalStoreDelegate *delegate = nullptr;
169 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
170 EXPECT_EQ(status, OK);
171 ASSERT_NE(delegate, nullptr);
172
173 status = delegate->CreateDistributedTable("sync_data");
174 EXPECT_EQ(status, OK);
175
176 // test create same table again
177 status = delegate->CreateDistributedTable("sync_data");
178 EXPECT_EQ(status, OK);
179
180 status = g_mgr.CloseStore(delegate);
181 EXPECT_EQ(status, OK);
182
183 /**
184 * @tc.steps:step3. drop sync_data table
185 * @tc.expected: step3. Return OK.
186 */
187 db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
188 ASSERT_NE(db, nullptr);
189 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "drop table sync_data;"), SQLITE_OK);
190 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
191
192 /**
193 * @tc.steps:step4. open again, check auxiliary should be delete
194 * @tc.expected: step4. Return OK.
195 */
196 delegate = nullptr;
197 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
198 EXPECT_EQ(status, OK);
199 ASSERT_NE(delegate, nullptr);
200 status = g_mgr.CloseStore(delegate);
201 EXPECT_EQ(status, OK);
202 }
203
204 /**
205 * @tc.name: RelationalStoreTest002
206 * @tc.desc: Test open store with invalid path or store ID
207 * @tc.type: FUNC
208 * @tc.require: AR000GK58F
209 * @tc.author: lianhuix
210 */
211 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize.Level1)
212 {
213 /**
214 * @tc.steps:step1. Prepare db file
215 * @tc.expected: step1. Return OK.
216 */
217 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
218 ASSERT_NE(db, nullptr);
219 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
220 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
221 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
222
223 /**
224 * @tc.steps:step2. Test open store with invalid path or store ID
225 * @tc.expected: step2. open store failed.
226 */
227 RelationalStoreDelegate *delegate = nullptr;
228
229 // test open store with path not exist
230 DBStatus status = g_mgr.OpenStore(g_dbDir + "tmp/" + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
231 EXPECT_NE(status, OK);
232 ASSERT_EQ(delegate, nullptr);
233
234 // test open store with empty store_id
235 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, {}, {}, delegate);
236 EXPECT_NE(status, OK);
237 ASSERT_EQ(delegate, nullptr);
238
239 // test open store with path has invalid character
240 status = g_mgr.OpenStore(g_dbDir + "t&m$p/" + STORE_ID + DB_SUFFIX, {}, {}, delegate);
241 EXPECT_NE(status, OK);
242 ASSERT_EQ(delegate, nullptr);
243
244 // test open store with store_id has invalid character
245 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, "Relation@al_S$tore_ID", {}, delegate);
246 EXPECT_NE(status, OK);
247 ASSERT_EQ(delegate, nullptr);
248
249 // test open store with store_id length over MAX_STORE_ID_LENGTH
250 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX,
251 std::string(DBConstant::MAX_STORE_ID_LENGTH + 1, 'a'), {}, delegate);
252 EXPECT_NE(status, OK);
253 ASSERT_EQ(delegate, nullptr);
254 }
255
256 /**
257 * @tc.name: RelationalStoreTest003
258 * @tc.desc: Test open store with journal_mode is not WAL
259 * @tc.type: FUNC
260 * @tc.require: AR000GK58F
261 * @tc.author: lianhuix
262 */
263 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest003, TestSize.Level1)
264 {
265 /**
266 * @tc.steps:step1. Prepare db file with string is not WAL
267 * @tc.expected: step1. Return OK.
268 */
269 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
270 ASSERT_NE(db, nullptr);
271 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=PERSIST;"), SQLITE_OK);
272 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
273 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
274
275 /**
276 * @tc.steps:step2. Test open store
277 * @tc.expected: step2. Open store failed.
278 */
279 RelationalStoreDelegate *delegate = nullptr;
280
281 // test open store with journal mode is not WAL
282 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
283 EXPECT_NE(status, OK);
284 ASSERT_EQ(delegate, nullptr);
285 }
286
287 /**
288 * @tc.name: RelationalStoreTest004
289 * @tc.desc: Test create distributed table with over limit
290 * @tc.type: FUNC
291 * @tc.require: AR000GK58F
292 * @tc.author: lianhuix
293 */
294 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize.Level1)
295 {
296 /**
297 * @tc.steps:step1. Prepare db file with multiple tables
298 * @tc.expected: step1. Return OK.
299 */
300 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
301 ASSERT_NE(db, nullptr);
302 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
303 const int tableCount = DBConstant::MAX_DISTRIBUTED_TABLE_COUNT + 10; // 10: additional size for test abnormal scene
304 for (int i=0; i<tableCount; i++) {
305 std::string sql = "CREATE TABLE TEST_" + std::to_string(i) + "(id INT PRIMARY KEY, value TEXT);";
306 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK);
307 }
308 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
309
310 RelationalStoreDelegate *delegate = nullptr;
311
312 /**
313 * @tc.steps:step2. Open store and create multiple distributed table
314 * @tc.expected: step2. The tables in limited quantity were created successfully, the others failed.
315 */
316 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
317 EXPECT_EQ(status, OK);
318 ASSERT_NE(delegate, nullptr);
319
320 for (int i=0; i<tableCount; i++) {
321 if (i < DBConstant::MAX_DISTRIBUTED_TABLE_COUNT) {
322 EXPECT_EQ(delegate->CreateDistributedTable("TEST_" + std::to_string(i)), OK);
323 } else {
324 EXPECT_NE(delegate->CreateDistributedTable("TEST_" + std::to_string(i)), OK);
325 }
326 }
327
328 /**
329 * @tc.steps:step3. Close store
330 * @tc.expected: step3. Return OK.
331 */
332 status = g_mgr.CloseStore(delegate);
333 EXPECT_EQ(status, OK);
334 }
335
336 /**
337 * @tc.name: RelationalStoreTest005
338 * @tc.desc: Test create distributed table with invalid table name
339 * @tc.type: FUNC
340 * @tc.require: AR000GK58F
341 * @tc.author: lianhuix
342 */
343 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1)
344 {
345 /**
346 * @tc.steps:step1. Prepare db file
347 * @tc.expected: step1. Return OK.
348 */
349 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
350 ASSERT_NE(db, nullptr);
351 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
352 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
353
354 /**
355 * @tc.steps:step2. Open store
356 * @tc.expected: step2. return OK
357 */
358 RelationalStoreDelegate *delegate = nullptr;
359 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
360 EXPECT_EQ(status, OK);
361 ASSERT_NE(delegate, nullptr);
362
363 /**
364 * @tc.steps:step3. Create distributed table with invalid table name
365 * @tc.expected: step3. Create distributed table failed.
366 */
367 EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp"), OK);
368
369 EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^."), INVALID_ARGS);
370
371 EXPECT_EQ(RelationalTestUtils::ExecSql(db, INVALID_TABLE_FIELD_SQL), SQLITE_OK);
372 EXPECT_EQ(delegate->CreateDistributedTable("t1"), NOT_SUPPORT);
373
374 /**
375 * @tc.steps:step4. Close store
376 * @tc.expected: step4. Return OK.
377 */
378 status = g_mgr.CloseStore(delegate);
379 EXPECT_EQ(status, OK);
380 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
381 }
382
383 /**
384 * @tc.name: RelationalStoreTest006
385 * @tc.desc: Test create distributed table with non primary key schema
386 * @tc.type: FUNC
387 * @tc.require: AR000GK58F
388 * @tc.author: lianhuix
389 */
390 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1)
391 {
392 /**
393 * @tc.steps:step1. Prepare db file
394 * @tc.expected: step1. Return OK.
395 */
396 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
397 ASSERT_NE(db, nullptr);
398 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
399 EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_TABLE_SQL_NO_PRIMARY_KEY), SQLITE_OK);
400 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
401
402 /**
403 * @tc.steps:step2. Open store
404 * @tc.expected: step2. return OK
405 */
406 RelationalStoreDelegate *delegate = nullptr;
407 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
408 EXPECT_EQ(status, OK);
409 ASSERT_NE(delegate, nullptr);
410
411 /**
412 * @tc.steps:step3. Create distributed table with invalid table name
413 * @tc.expected: step3. Create distributed table failed.
414 */
415 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK);
416
417 /**
418 * @tc.steps:step4. Close store
419 * @tc.expected: step4. Return OK.
420 */
421 status = g_mgr.CloseStore(delegate);
422 EXPECT_EQ(status, OK);
423 delegate = nullptr;
424
425 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
426 EXPECT_EQ(status, OK);
427 ASSERT_NE(delegate, nullptr);
428
429 status = g_mgr.CloseStore(delegate);
430 EXPECT_EQ(status, OK);
431 }
432
433 /**
434 * @tc.name: RelationalStoreTest007
435 * @tc.desc: Test create distributed table with table has invalid field name
436 * @tc.type: FUNC
437 * @tc.require: AR000GK58F
438 * @tc.author: lianhuix
439 */
440 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize.Level1)
441 {
442 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
443 ASSERT_NE(db, nullptr);
444 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
445 EXPECT_EQ(RelationalTestUtils::ExecSql(db, UNSUPPORTED_FIELD_TABLE_SQL), SQLITE_OK);
446 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
447
448 RelationalStoreDelegate *delegate = nullptr;
449 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
450 EXPECT_EQ(status, OK);
451 ASSERT_NE(delegate, nullptr);
452
453 EXPECT_EQ(delegate->CreateDistributedTable("test"), NOT_SUPPORT);
454 status = g_mgr.CloseStore(delegate);
455 EXPECT_EQ(status, OK);
456 }
457
458 /**
459 * @tc.name: RelationalStoreTest008
460 * @tc.desc: Test create distributed table with table has composite primary keys
461 * @tc.type: FUNC
462 * @tc.require: AR000GK58F
463 * @tc.author: lianhuix
464 */
465 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize.Level1)
466 {
467 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
468 ASSERT_NE(db, nullptr);
469 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
470 EXPECT_EQ(RelationalTestUtils::ExecSql(db, COMPOSITE_PRIMARY_KEY_TABLE_SQL), SQLITE_OK);
471 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
472
473 RelationalStoreDelegate *delegate = nullptr;
474 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
475 EXPECT_EQ(status, OK);
476 ASSERT_NE(delegate, nullptr);
477
478 EXPECT_EQ(delegate->CreateDistributedTable("workers"), NOT_SUPPORT);
479 status = g_mgr.CloseStore(delegate);
480 EXPECT_EQ(status, OK);
481 }
482
483 /**
484 * @tc.name: RelationalStoreTest009
485 * @tc.desc: Test create distributed table with table has history data
486 * @tc.type: FUNC
487 * @tc.require: AR000GK58F
488 * @tc.author: lianhuix
489 */
490 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize.Level1)
491 {
492 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
493 ASSERT_NE(db, nullptr);
494 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
495 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
496 EXPECT_EQ(RelationalTestUtils::ExecSql(db, INSERT_SYNC_DATA_SQL), SQLITE_OK);
497 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
498
499 RelationalStoreDelegate *delegate = nullptr;
500 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
501 EXPECT_EQ(status, OK);
502 ASSERT_NE(delegate, nullptr);
503
504 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), NOT_SUPPORT);
505 status = g_mgr.CloseStore(delegate);
506 EXPECT_EQ(status, OK);
507 }
508
509
510 namespace {
TableModifyTest(const std::string & modifySql,DBStatus expect)511 void TableModifyTest(const std::string &modifySql, DBStatus expect)
512 {
513 /**
514 * @tc.steps:step1. Prepare db file
515 * @tc.expected: step1. Return OK.
516 */
517 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
518 ASSERT_NE(db, nullptr);
519 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
520 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
521
522 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A");
523 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_B");
524 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_C");
525
526 /**
527 * @tc.steps:step2. Open store
528 * @tc.expected: step2. return OK
529 */
530 RelationalStoreDelegate *delegate = nullptr;
531 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
532 EXPECT_EQ(status, OK);
533 ASSERT_NE(delegate, nullptr);
534
535 /**
536 * @tc.steps:step3. Create distributed table
537 * @tc.expected: step3. Create distributed table OK.
538 */
539 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK);
540
541 /**
542 * @tc.steps:step4. Upgrade table with modifySql
543 * @tc.expected: step4. return OK
544 */
545 EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK);
546
547 /**
548 * @tc.steps:step5. Create distributed table again
549 * @tc.expected: step5. Create distributed table return expect.
550 */
551 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), expect);
552
553 /**
554 * @tc.steps:step6. Close store
555 * @tc.expected: step6 Return OK.
556 */
557 status = g_mgr.CloseStore(delegate);
558 EXPECT_EQ(status, OK);
559 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
560 }
561 }
562
563 /**
564 * @tc.name: RelationalTableModifyTest001
565 * @tc.desc: Test modify distributed table with compatible upgrade
566 * @tc.type: FUNC
567 * @tc.require: AR000GK58F
568 * @tc.author: lianhuix
569 */
570 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, TestSize.Level1)
571 {
572 TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL DEFAULT 123;", OK);
573 }
574
575 /**
576 * @tc.name: RelationalTableModifyTest002
577 * @tc.desc: Test modify distributed table with incompatible upgrade
578 * @tc.type: FUNC
579 * @tc.require: AR000GK58F
580 * @tc.author: lianhuix
581 */
582 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, TestSize.Level1)
583 {
584 TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL;", SCHEMA_MISMATCH);
585 }
586
587 /**
588 * @tc.name: RelationalTableModifyTest003
589 * @tc.desc: Test modify distributed table with incompatible upgrade
590 * @tc.type: FUNC
591 * @tc.require: AR000GK58F
592 * @tc.author: lianhuix
593 */
594 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003, TestSize.Level1)
595 {
596 TableModifyTest("ALTER TABLE sync_data DROP COLUMN w_timestamp;", SCHEMA_MISMATCH);
597 }
598
599 /**
600 * @tc.name: RelationalTableModifyTest004
601 * @tc.desc: Test upgrade distributed table with device table exists
602 * @tc.type: FUNC
603 * @tc.require: AR000GK58F
604 * @tc.author: lianhuix
605 */
606 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, TestSize.Level1)
607 {
608 /**
609 * @tc.steps:step1. Prepare db file
610 * @tc.expected: step1. Return OK.
611 */
612 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
613 ASSERT_NE(db, nullptr);
614 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
615 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
616 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A");
617 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_B");
618 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_C");
619
620 /**
621 * @tc.steps:step2. Open store
622 * @tc.expected: step2. return OK
623 */
624 RelationalStoreDelegate *delegate = nullptr;
625 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
626 EXPECT_EQ(status, OK);
627 ASSERT_NE(delegate, nullptr);
628
629 /**
630 * @tc.steps:step3. Create distributed table
631 * @tc.expected: step3. Create distributed table OK.
632 */
633 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK);
634
635 /**
636 * @tc.steps:step4. Upgrade table
637 * @tc.expected: step4. return OK
638 */
639 std::string modifySql = "ALTER TABLE sync_data ADD COLUMN add_field INTEGER;";
640 EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK);
641 std::string indexSql = "CREATE INDEX add_index ON sync_data (add_field);";
642 EXPECT_EQ(RelationalTestUtils::ExecSql(db, indexSql), SQLITE_OK);
643 std::string deleteIndexSql = "DROP INDEX IF EXISTS key_index";
644 EXPECT_EQ(RelationalTestUtils::ExecSql(db, deleteIndexSql), SQLITE_OK);
645 EXPECT_EQ(RelationalTestUtils::ExecSql(db, INSERT_SYNC_DATA_SQL), SQLITE_OK);
646
647 /**
648 * @tc.steps:step5. Create distributed table again
649 * @tc.expected: step5. Create distributed table return expect.
650 */
651 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK);
652
653 /**
654 * @tc.steps:step6. Close store
655 * @tc.expected: step6 Return OK.
656 */
657 status = g_mgr.CloseStore(delegate);
658 EXPECT_EQ(status, OK);
659 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
660 }
661
662 /**
663 * @tc.name: RelationalTableModifyTest005
664 * @tc.desc: Test modify distributed table with compatible upgrade
665 * @tc.type: FUNC
666 * @tc.require: AR000GK58F
667 * @tc.author: lianhuix
668 */
669 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest005, TestSize.Level1)
670 {
671 TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field STRING NOT NULL DEFAULT 'asdf';", OK);
672 }
673
674 /**
675 * @tc.name: RelationalRemoveDeviceDataTest001
676 * @tc.desc: Test remove device data
677 * @tc.type: FUNC
678 * @tc.require: AR000GK58F
679 * @tc.author: lianhuix
680 */
681 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest001, TestSize.Level1)
682 {
683 /**
684 * @tc.steps:step1. Prepare db file
685 * @tc.expected: step1. Return OK.
686 */
687 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
688 ASSERT_NE(db, nullptr);
689 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
690 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
691 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A");
692 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_B");
693 RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_C");
694
695 /**
696 * @tc.steps:step2. Open store
697 * @tc.expected: step2. return OK
698 */
699 RelationalStoreDelegate *delegate = nullptr;
700 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
701 EXPECT_EQ(status, OK);
702 ASSERT_NE(delegate, nullptr);
703
704 /**
705 * @tc.steps:step3. Remove device data
706 * @tc.expected: step3. ok
707 */
708 EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK);
709 EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A"), OK);
710 EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_B"), OK);
711 EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_C", "sync_data"), OK);
712
713 /**
714 * @tc.steps:step4. Remove device data with invalid args
715 * @tc.expected: step4. invalid
716 */
717 EXPECT_EQ(delegate->RemoveDeviceData(""), INVALID_ARGS);
718 EXPECT_EQ(delegate->RemoveDeviceData("", "sync_data"), INVALID_ARGS);
719 EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A", "Handle-J@^."), INVALID_ARGS);
720
721 /**
722 * @tc.steps:step5. Close store
723 * @tc.expected: step5 Return OK.
724 */
725 status = g_mgr.CloseStore(delegate);
726 EXPECT_EQ(status, OK);
727 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
728 }
729
730 namespace {
731 struct TableT1 {
732 int a;
733 std::string b;
734 int rowid;
735 int flag;
736 int timestamp;
737
operator ()__anon67a0b66e0411::TableT1738 VirtualRowData operator() () const
739 {
740 VirtualRowData rowData;
741 DataValue dA;
742 dA = static_cast<int64_t>(a);
743 rowData.objectData.PutDataValue("a", dA);
744 DataValue dB;
745 dB.SetText(b);
746 rowData.objectData.PutDataValue("b", dB);
747 rowData.logInfo.dataKey = rowid;
748 rowData.logInfo.device = DEVICE_B;
749 rowData.logInfo.originDev = DEVICE_B;
750 rowData.logInfo.timestamp = timestamp;
751 rowData.logInfo.wTimestamp = timestamp;
752 rowData.logInfo.flag = flag;
753 Key key;
754 DBCommon::StringToVector(std::to_string(rowid), key);
755 std::vector<uint8_t> hashKey;
756 DBCommon::CalcValueHash(key, hashKey);
757 rowData.logInfo.hashKey = hashKey;
758 return rowData;
759 }
760 };
761
AddDeviceSchema(RelationalVirtualDevice * device,sqlite3 * db,const std::string & name)762 void AddDeviceSchema(RelationalVirtualDevice *device, sqlite3 *db, const std::string &name)
763 {
764 TableInfo table;
765 SQLiteUtils::AnalysisSchema(db, name, table);
766 device->SetLocalFieldInfo(table.GetFieldInfos());
767 device->SetTableInfo(table);
768 }
769 }
770
771 /**
772 * @tc.name: RelationalRemoveDeviceDataTest002
773 * @tc.desc: Test remove device data and syn
774 * @tc.type: FUNC
775 * @tc.require: AR000GK58F
776 * @tc.author: lianhuix
777 */
778 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest002, TestSize.Level1)
779 {
780 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
781 ASSERT_NE(db, nullptr);
782 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
783 EXPECT_EQ(RelationalTestUtils::ExecSql(db, SIMPLE_CREATE_TABLE_SQL), SQLITE_OK);
784 AddDeviceSchema(g_deviceB, db, "t1");
785
786 RelationalStoreDelegate *delegate = nullptr;
787 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
788 EXPECT_EQ(status, OK);
789 ASSERT_NE(delegate, nullptr);
790
791 EXPECT_EQ(delegate->CreateDistributedTable("t1"), OK);
792
793 g_deviceB->PutDeviceData("t1", std::vector<TableT1>{
794 {1, "111", 1, 2, 1}, // test data
795 {2, "222", 2, 2, 2}, // test data
796 {3, "333", 3, 2, 3}, // test data
797 {4, "444", 4, 2, 4} // test data
798 });
799 std::vector<std::string> devices = {DEVICE_B};
800 Query query = Query::Select("t1").NotEqualTo("a", 0);
801 status = delegate->Sync(devices, SyncMode::SYNC_MODE_PULL_ONLY, query,
__anon67a0b66e0502(const std::map<std::string, std::vector<TableStatus>> &devicesMap) 802 [&devices](const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
803 EXPECT_EQ(devicesMap.size(), devices.size());
804 EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK);
805 }, true);
806 EXPECT_EQ(status, OK);
807
808 EXPECT_EQ(delegate->RemoveDeviceData(DEVICE_B), OK);
809
810 int logCnt = -1;
811 std::string checkLogSql = "SELECT count(*) FROM naturalbase_rdb_aux_t1_log WHERE device = '" + DEVICE_B + "'";
__anon67a0b66e0602(sqlite3_stmt *stmt) 812 RelationalTestUtils::ExecSql(db, checkLogSql, nullptr, [&logCnt](sqlite3_stmt *stmt) {
813 logCnt = sqlite3_column_int(stmt, 0);
814 return E_OK;
815 });
816 EXPECT_EQ(logCnt, 0);
817
818 int dataCnt = -1;
819 std::string deviceTable = g_mgr.GetDistributedTableName(DEVICE_B, "t1");
820 std::string checkDataSql = "SELECT count(*) FROM " + deviceTable + " WHERE device = '" + DEVICE_B + "'";
__anon67a0b66e0702(sqlite3_stmt *stmt) 821 RelationalTestUtils::ExecSql(db, checkDataSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) {
822 dataCnt = sqlite3_column_int(stmt, 0);
823 return E_OK;
824 });
825 EXPECT_EQ(logCnt, 0);
826
827 status = g_mgr.CloseStore(delegate);
828 EXPECT_EQ(status, OK);
829 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
830 }
831
832 /**
833 * @tc.name: RelationalOpenStorePathCheckTest001
834 * @tc.desc: Test open store with same label but different path.
835 * @tc.type: FUNC
836 * @tc.require: AR000GK58F
837 * @tc.author: lianhuix
838 */
839 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest001, TestSize.Level1)
840 {
841 std::string dir1 = g_dbDir + "dbDir1";
842 EXPECT_EQ(OS::MakeDBDirectory(dir1), E_OK);
843 sqlite3 *db1 = RelationalTestUtils::CreateDataBase(dir1 + STORE_ID + DB_SUFFIX);
844 ASSERT_NE(db1, nullptr);
845 EXPECT_EQ(RelationalTestUtils::ExecSql(db1, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
846 EXPECT_EQ(RelationalTestUtils::ExecSql(db1, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
847 EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK);
848
849 std::string dir2 = g_dbDir + "dbDir2";
850 EXPECT_EQ(OS::MakeDBDirectory(dir2), E_OK);
851 sqlite3 *db2 = RelationalTestUtils::CreateDataBase(dir2 + STORE_ID + DB_SUFFIX);
852 ASSERT_NE(db2, nullptr);
853 EXPECT_EQ(RelationalTestUtils::ExecSql(db2, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
854 EXPECT_EQ(RelationalTestUtils::ExecSql(db2, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
855 EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK);
856
857 DBStatus status = OK;
858 RelationalStoreDelegate *delegate1 = nullptr;
859 status = g_mgr.OpenStore(dir1 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate1);
860 EXPECT_EQ(status, OK);
861 ASSERT_NE(delegate1, nullptr);
862
863 RelationalStoreDelegate *delegate2 = nullptr;
864 status = g_mgr.OpenStore(dir2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2);
865 EXPECT_EQ(status, INVALID_ARGS);
866 ASSERT_EQ(delegate2, nullptr);
867
868 status = g_mgr.CloseStore(delegate1);
869 EXPECT_EQ(status, OK);
870
871 status = g_mgr.CloseStore(delegate2);
872 EXPECT_EQ(status, INVALID_ARGS);
873 }
874
875 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePressureTest001, TestSize.Level1)
876 {
877 /**
878 * @tc.steps:step1. Prepare db file
879 * @tc.expected: step1. Return OK.
880 */
881 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
882 ASSERT_NE(db, nullptr);
883 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
884 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
885 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
886
887 DBStatus status = OK;
888 for (int i = 0; i < 1000; i++) {
889 RelationalStoreDelegate *delegate = nullptr;
890 status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
891 EXPECT_EQ(status, OK);
892 ASSERT_NE(delegate, nullptr);
893
894 status = g_mgr.CloseStore(delegate);
895 EXPECT_EQ(status, OK);
896 delegate = nullptr;
897 }
898 }
899
900 HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePressureTest002, TestSize.Level1)
901 {
902 /**
903 * @tc.steps:step1. Prepare db file
904 * @tc.expected: step1. Return OK.
905 */
906 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
907 ASSERT_NE(db, nullptr);
908 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
909 EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK);
910 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
911
912 std::queue<RelationalStoreDelegate *> delegateQueue;
913 std::mutex queueLock;
914 std::random_device rd;
915 default_random_engine e(rd());
916 uniform_int_distribution<unsigned> u(0, 9);
917
__anon67a0b66e0802() 918 std::thread openStoreThread([&, this]() {
919 for (int i = 0; i < 1000; i++) {
920 LOGD("++++> open store delegate: %d", i);
921 RelationalStoreDelegate *delegate = nullptr;
922 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
923 EXPECT_EQ(status, OK);
924 ASSERT_NE(delegate, nullptr);
925 {
926 std::lock_guard<std::mutex> lock(queueLock);
927 delegateQueue.push(delegate);
928 }
929 LOGD("++++< open store delegate: %d", i);
930 }
931 });
932
933 int cnt = 0;
934 while (cnt < 1000) {
935 RelationalStoreDelegate *delegate = nullptr;
936 {
937 std::lock_guard<std::mutex> lock(queueLock);
938 if (delegateQueue.empty()) {
939 std::this_thread::sleep_for(std::chrono::microseconds(100));
940 continue;
941 }
942 delegate = delegateQueue.front();
943 delegateQueue.pop();
944 }
945 LOGD("++++> close store delegate: %d", cnt);
946 DBStatus status = g_mgr.CloseStore(delegate);
947 LOGD("++++< close store delegate: %d", cnt);
948 EXPECT_EQ(status, OK);
949 delegate = nullptr;
950 cnt++;
951 std::this_thread::sleep_for(std::chrono::microseconds(100 * u(e)));
952 }
953 openStoreThread.join();
954 }
955