• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ()__anone9af9c8d0411::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,
__anone9af9c8d0502(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 + "'";
__anone9af9c8d0602(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 + "'";
__anone9af9c8d0702(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 
__anone9af9c8d0802() 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