1 /*
2 * Copyright (c) 2023 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 <sys/time.h>
17 #include <gtest/gtest.h>
18
19 #include "concurrent_adapter.h"
20 #include "db_common.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "relational_store_client.h"
24 #include "relational_store_delegate_impl.h"
25 #include "relational_store_manager.h"
26 #include "cloud_db_sync_utils_test.h"
27 #include "store_observer.h"
28
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32 using namespace std;
33
34 namespace {
35 constexpr const char *DB_SUFFIX = ".db";
36 constexpr const char *STORE_ID = "Relational_Store_ID";
37 std::string g_dbDir;
38 std::string g_testDir;
39 DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID);
40
41 constexpr int E_OK = 0;
42 constexpr int E_ERROR = 1;
43 const int WAIT_TIME = 1000; // 1000ms
44 constexpr static uint64_t TO_100_NS = 10; // 1us to 100ns
45 const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000;
46 std::mutex g_mutex;
47 std::condition_variable g_cv;
48 bool g_alreadyNotify = false;
49
50 class DistributedDBCloudInterfacesRelationalExtTest : public testing::Test {
51 public:
52 static void SetUpTestCase(void);
53 static void TearDownTestCase(void);
54 void SetUp() override;
55 void TearDown() override;
56 void CheckTriggerObserverTest002(const std::string &tableName, std::atomic<int> &count);
57
ClientObserverFunc(ClientChangedData & clientChangedData)58 void ClientObserverFunc(ClientChangedData &clientChangedData)
59 {
60 for (const auto &tableEntry : clientChangedData.tableData) {
61 LOGD("client observer fired, table: %s", tableEntry.first.c_str());
62 triggerTableData_.insert_or_assign(tableEntry.first, tableEntry.second);
63 }
64 triggeredCount_++;
65 {
66 std::unique_lock<std::mutex> lock(g_mutex);
67 g_alreadyNotify = true;
68 }
69 g_cv.notify_one();
70 }
71
ClientObserverFunc2(ClientChangedData & clientChangedData)72 void ClientObserverFunc2(ClientChangedData &clientChangedData)
73 {
74 triggeredCount2_++;
75 {
76 std::unique_lock<std::mutex> lock(g_mutex);
77 g_alreadyNotify = true;
78 }
79 g_cv.notify_one();
80 }
81
CheckTriggerTableData(size_t dataSize,const std::string & tableName,ChangeProperties & properties,int triggerCount)82 void CheckTriggerTableData(size_t dataSize, const std::string &tableName, ChangeProperties &properties,
83 int triggerCount)
84 {
85 ASSERT_EQ(triggerTableData_.size(), dataSize);
86 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
87 EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, properties.isTrackedDataChange);
88 EXPECT_EQ(triggeredCount_, triggerCount);
89 }
90
WaitAndResetNotify()91 void WaitAndResetNotify()
92 {
93 std::unique_lock<std::mutex> lock(g_mutex);
94 WaitAndResetNotifyWithLock(lock);
95 }
96
WaitAndResetNotifyWithLock(std::unique_lock<std::mutex> & lock)97 void WaitAndResetNotifyWithLock(std::unique_lock<std::mutex> &lock)
98 {
99 g_cv.wait(lock, []() {
100 return g_alreadyNotify;
101 });
102 g_alreadyNotify = false;
103 }
104
105 std::set<std::string> triggerTableNames_;
106 std::map<std::string, ChangeProperties> triggerTableData_;
107 int triggeredCount_ = 0;
108 int triggeredCount2_ = 0;
109 };
110
SetUpTestCase(void)111 void DistributedDBCloudInterfacesRelationalExtTest::SetUpTestCase(void)
112 {
113 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
114 LOGD("Test dir is %s", g_testDir.c_str());
115 g_dbDir = g_testDir + "/";
116 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
117 }
118
TearDownTestCase(void)119 void DistributedDBCloudInterfacesRelationalExtTest::TearDownTestCase(void)
120 {
121 }
122
SetUp()123 void DistributedDBCloudInterfacesRelationalExtTest::SetUp()
124 {
125 }
126
TearDown()127 void DistributedDBCloudInterfacesRelationalExtTest::TearDown()
128 {
129 g_alreadyNotify = false;
130 DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir);
131 }
132
CheckTriggerObserverTest002(const std::string & tableName,std::atomic<int> & count)133 void DistributedDBCloudInterfacesRelationalExtTest::CheckTriggerObserverTest002(const std::string &tableName,
134 std::atomic<int> &count)
135 {
136 count++;
137 ASSERT_EQ(triggerTableData_.size(), 1u);
138 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
139 EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, false);
140 EXPECT_EQ(triggeredCount_, count);
141 }
142
GetCurrentSysTimeIn100Ns(uint64_t & outTime)143 static int GetCurrentSysTimeIn100Ns(uint64_t &outTime)
144 {
145 struct timeval rawTime;
146 int errCode = gettimeofday(&rawTime, nullptr);
147 if (errCode < 0) {
148 return -E_ERROR;
149 }
150 outTime = static_cast<uint64_t>(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS +
151 static_cast<uint64_t>(rawTime.tv_usec);
152 outTime *= TO_100_NS;
153 return E_OK;
154 }
155
SetTracerSchemaTest001(const std::string & tableName)156 static void SetTracerSchemaTest001(const std::string &tableName)
157 {
158 TrackerSchema schema;
159 schema.tableName = tableName;
160 schema.extendColNames = {"id"};
161 schema.trackerColNames = {"name"};
162 RelationalStoreDelegate *delegate = nullptr;
163 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
164 EXPECT_EQ(status, OK);
165 ASSERT_NE(delegate, nullptr);
166 EXPECT_EQ(delegate->SetTrackerTable(schema), OK);
167 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
168 }
169
ExecSqlAndWaitForObserver(sqlite3 * db,const std::string & sql,std::unique_lock<std::mutex> & lock)170 static void ExecSqlAndWaitForObserver(sqlite3 *db, const std::string &sql, std::unique_lock<std::mutex> &lock)
171 {
172 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
173 g_cv.wait(lock, []() {
174 return g_alreadyNotify;
175 });
176 g_alreadyNotify = false;
177 }
178
179 /**
180 * @tc.name: GetRawSysTimeTest001
181 * @tc.desc: Test get_raw_sys_time has been registered in sqlite
182 * @tc.type: FUNC
183 * @tc.require:
184 * @tc.author: zhangshijie
185 */
186 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, GetRawSysTimeTest001, TestSize.Level0)
187 {
188 const std::string sql = "select get_raw_sys_time();";
189 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
190 EXPECT_NE(db, nullptr);
191 uint64_t curTime = 0;
192 int errCode = GetCurrentSysTimeIn100Ns(curTime);
193 EXPECT_EQ(errCode, E_OK);
__anona8aa9dd30402(sqlite3_stmt *stmt) 194 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime] (sqlite3_stmt *stmt) {
195 EXPECT_GT(static_cast<uint64_t>(sqlite3_column_int64(stmt, 0)), curTime);
196 return E_OK;
197 });
198 EXPECT_EQ(errCode, SQLITE_OK);
199 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
200 }
201
PrepareData(const std::vector<std::string> & tableNames,bool primaryKeyIsRowId,DistributedDB::TableSyncType tableSyncType,bool userDefineRowid=true,bool createDistributeTable=true)202 void PrepareData(const std::vector<std::string> &tableNames, bool primaryKeyIsRowId,
203 DistributedDB::TableSyncType tableSyncType, bool userDefineRowid = true, bool createDistributeTable = true)
204 {
205 /**
206 * @tc.steps:step1. create db, create table.
207 * @tc.expected: step1. return ok.
208 */
209 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
210 EXPECT_NE(db, nullptr);
211 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
212 std::string sql;
213 for (const auto &tableName : tableNames) {
214 if (primaryKeyIsRowId) {
215 sql = "create table " + tableName + "(rowid INTEGER primary key, id int, name TEXT);";
216 } else {
217 if (userDefineRowid) {
218 sql = "create table " + tableName + "(rowid int, id int, name TEXT, PRIMARY KEY(id));";
219 } else {
220 sql = "create table " + tableName + "(id int, name TEXT, PRIMARY KEY(id));";
221 }
222 }
223 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
224 }
225 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
226
227 /**
228 * @tc.steps:step2. create distributed table.
229 * @tc.expected: step2. return ok.
230 */
231 RelationalStoreDelegate *delegate = nullptr;
232 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
233 EXPECT_EQ(status, OK);
234 ASSERT_NE(delegate, nullptr);
235 if (createDistributeTable) {
236 for (const auto &tableName : tableNames) {
237 EXPECT_EQ(delegate->CreateDistributedTable(tableName, tableSyncType), OK);
238 }
239 }
240 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
241 delegate = nullptr;
242 }
243
InsertTriggerTest(DistributedDB::TableSyncType tableSyncType)244 void InsertTriggerTest(DistributedDB::TableSyncType tableSyncType)
245 {
246 /**
247 * @tc.steps:step1. prepare data.
248 * @tc.expected: step1. return ok.
249 */
250 const std::string tableName = "sync_data";
251 PrepareData({tableName}, false, tableSyncType);
252
253 /**
254 * @tc.steps:step2. insert data into sync_data.
255 * @tc.expected: step2. return ok.
256 */
257 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
258 EXPECT_NE(db, nullptr);
259 std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');";
260 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
261
262 /**
263 * @tc.steps:step3. select data from log table.
264 * @tc.expected: step3. return ok.
265 */
266 sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;";
267 uint64_t curTime = 0;
268 int errCode = GetCurrentSysTimeIn100Ns(curTime);
269 EXPECT_EQ(errCode, E_OK);
270
271 int resultCount = 0;
272 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr,
273 [tableSyncType, curTime, &resultCount] (sqlite3_stmt *stmt) {
274 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id
275 std::string device = "";
276 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK);
277 EXPECT_EQ(device, "");
278 std::string oriDevice = "";
279 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index
280 EXPECT_EQ(oriDevice, "");
281
282 int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index
283 int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index
284 int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS;
285 EXPECT_TRUE(wtimestamp - timestamp < diff);
286 EXPECT_TRUE(static_cast<int64_t>(curTime - timestamp) < diff);
287 if (tableSyncType == DistributedDB::CLOUD_COOPERATION) {
288 EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index flag == 0x02|0x20
289 } else {
290 EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index flag == 2
291 }
292 resultCount++;
293 return E_OK;
294 });
295 EXPECT_EQ(errCode, SQLITE_OK);
296 EXPECT_EQ(resultCount, 1);
297 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
298 }
299
300 /**
301 * @tc.name: InsertTriggerTest001
302 * @tc.desc: Test insert trigger in sqlite in CLOUD_COOPERATION mode
303 * @tc.type: FUNC
304 * @tc.require:
305 * @tc.author: zhangshijie
306 */
307 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, InsertTriggerTest001, TestSize.Level0)
308 {
309 InsertTriggerTest(DistributedDB::CLOUD_COOPERATION);
310 }
311
312 /**
313 * @tc.name: InsertTriggerTest002
314 * @tc.desc: Test insert trigger in sqlite in DEVICE_COOPERATION mode
315 * @tc.type: FUNC
316 * @tc.require:
317 * @tc.author: zhangshijie
318 */
319 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, InsertTriggerTest002, TestSize.Level0)
320 {
321 InsertTriggerTest(DistributedDB::DEVICE_COOPERATION);
322 }
323
324 /**
325 * @tc.name: InsertTriggerTest003
326 * @tc.desc: Test insert trigger in sqlite when use "insert or replace"
327 * @tc.type: FUNC
328 * @tc.require:
329 * @tc.author: zhangshijie
330 */
331 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, InsertTriggerTest003, TestSize.Level1)
332 {
333 /**
334 * @tc.steps:step1. prepare data.
335 * @tc.expected: step1. return ok.
336 */
337 const std::string tableName = "sync_data";
338 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION);
339
340 /**
341 * @tc.steps:step2. insert data into sync_data.
342 * @tc.expected: step2. return ok.
343 */
344 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
345 EXPECT_NE(db, nullptr);
346 std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan1');";
347 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
348
349 // update cloud_gid in log table
350 std::string gid = "test_gid";
351 sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" + gid + "'";
352 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
353 // use insert or replace to update data
354 sql = "insert or replace into " + tableName + " VALUES(3, 1, 'zhangsan1');";
355 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
356
357 /**
358 * @tc.steps:step3. select data from log table.
359 * @tc.expected: step3. return ok.
360 */
361 sql = "select data_key, device, ori_device, flag, cloud_gid from " + DBCommon::GetLogTableName(tableName);
362 int resultCount = 0;
__anona8aa9dd30602(sqlite3_stmt *stmt) 363 int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&resultCount, gid] (sqlite3_stmt *stmt) {
364 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id
365 std::string device = "";
366 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK);
367 EXPECT_EQ(device, "");
368 std::string oriDevice = "";
369 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index
370 EXPECT_EQ(oriDevice, "");
371
372 EXPECT_EQ(sqlite3_column_int(stmt, 3), 0x02|0x20); // 3 is column index flag == 0x02|0x20
373 std::string gidStr;
374 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 4, gidStr), E_OK); // 4 is column index
375 EXPECT_EQ(gid, gidStr);
376 resultCount++;
377 return E_OK;
378 });
379 EXPECT_EQ(errCode, SQLITE_OK);
380 EXPECT_EQ(resultCount, 1);
381 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
382 }
383
UpdateTriggerTest(bool primaryKeyIsRowId)384 void UpdateTriggerTest(bool primaryKeyIsRowId)
385 {
386 /**
387 * @tc.steps:step1. prepare data.
388 * @tc.expected: step1. return ok.
389 */
390 const std::string tableName = "sync_data";
391 PrepareData({tableName}, primaryKeyIsRowId, DistributedDB::CLOUD_COOPERATION);
392
393 /**
394 * @tc.steps:step2. insert data into sync_data_tmp.
395 * @tc.expected: step2. return ok.
396 */
397 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
398 EXPECT_NE(db, nullptr);
399 std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');";
400 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
401
402 /**
403 * @tc.steps:step3. update data.
404 * @tc.expected: step3. return ok.
405 */
406 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
407 sql = "update " + tableName + " set name = 'lisi';";
408 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
409
410 /**
411 * @tc.steps:step4. select data from log table.
412 * @tc.expected: step4. return ok.
413 */
414 sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;";
415 uint64_t curTime = 0;
416 int errCode = GetCurrentSysTimeIn100Ns(curTime);
417 EXPECT_EQ(errCode, E_OK);
418
419 int resultCount = 0;
420 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount, primaryKeyIsRowId] (
421 sqlite3_stmt *stmt) {
422 if (primaryKeyIsRowId) {
423 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id
424 } else {
425 EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id
426 }
427
428 EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index, flag == 0x02|0x20
429
430 std::string device = "";
431 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK);
432 EXPECT_EQ(device, "");
433 std::string oriDevice = "";
434 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index
435 EXPECT_EQ(oriDevice, "");
436
437 int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index
438 int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index
439 int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS;
440 EXPECT_TRUE(timestamp - wtimestamp > diff);
441 EXPECT_TRUE(static_cast<int64_t>(curTime - timestamp) < diff);
442
443 resultCount++;
444 return E_OK;
445 });
446 EXPECT_EQ(errCode, SQLITE_OK);
447 EXPECT_EQ(resultCount, 1);
448 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
449 }
450
451 /**
452 * @tc.name: UpdateTriggerTest001
453 * @tc.desc: Test update trigger in sqlite for primary key is not row id
454 * @tc.type: FUNC
455 * @tc.require:
456 * @tc.author: zhangshijie
457 */
458 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level0)
459 {
460 UpdateTriggerTest(false);
461 }
462
463 /**
464 * @tc.name: UpdateTriggerTest002
465 * @tc.desc: Test update trigger in sqlite for primary key is row id
466 * @tc.type: FUNC
467 * @tc.require:
468 * @tc.author: zhangshijie
469 */
470 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level0)
471 {
472 UpdateTriggerTest(true);
473 }
474
475 /**
476 * @tc.name: DeleteTriggerTest001
477 * @tc.desc: Test delete trigger in sqlite
478 * @tc.type: FUNC
479 * @tc.require:
480 * @tc.author: zhangshijie
481 */
482 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level0)
483 {
484 /**
485 * @tc.steps:step1. prepare data.
486 * @tc.expected: step1. return ok.
487 */
488 const std::string tableName = "sync_data";
489 PrepareData({tableName}, true, DistributedDB::CLOUD_COOPERATION);
490
491 /**
492 * @tc.steps:step2. insert data into sync_data.
493 * @tc.expected: step2. return ok.
494 */
495 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
496 EXPECT_NE(db, nullptr);
497 std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');";
498 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
499
500 /**
501 * @tc.steps:step3. delete data.
502 * @tc.expected: step3. return ok.
503 */
504 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME));
505 sql = "delete from " + tableName + " where name = 'zhangsan';";
506 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
507
508 /**
509 * @tc.steps:step4. select data from log table.
510 * @tc.expected: step4. return ok.
511 */
512 sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;";
513 uint64_t curTime = 0;
514 int errCode = GetCurrentSysTimeIn100Ns(curTime);
515 EXPECT_EQ(errCode, E_OK);
516
517 int resultCount = 0;
__anona8aa9dd30802(sqlite3_stmt *stmt) 518 errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount] (sqlite3_stmt *stmt) {
519 EXPECT_EQ(sqlite3_column_int64(stmt, 0), -1);
520 EXPECT_EQ(sqlite3_column_int(stmt, 5), 3); // 5 is column index, flag == 3
521
522 std::string device = "de";
523 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK);
524 EXPECT_EQ(device, "");
525 std::string oriDevice = "de";
526 EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index
527 EXPECT_EQ(oriDevice, "");
528
529 int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index
530 int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index
531 int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS;
532 EXPECT_TRUE(timestamp - wtimestamp > diff);
533 EXPECT_TRUE(static_cast<int64_t>(curTime - timestamp) < diff);
534
535 resultCount++;
536 return E_OK;
537 });
538 EXPECT_EQ(errCode, SQLITE_OK);
539 EXPECT_EQ(resultCount, 1);
540 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
541 }
542
543 /**
544 * @tc.name: TriggerObserverTest001
545 * @tc.desc: Test invalid args for RegisterClientObserver and UnRegisterClientObserver
546 * @tc.type: FUNC
547 * @tc.require:
548 * @tc.author: zhangshijie
549 */
550 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest001, TestSize.Level0)
551 {
552 /**
553 * @tc.steps:step1. call RegisterClientObserver and UnRegisterClientObserver with db = nullptr.
554 * @tc.expected: step1. return INVALID_ARGS.
555 */
556 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
557 this, std::placeholders::_1);
558 EXPECT_EQ(RegisterClientObserver(nullptr, clientObserver), INVALID_ARGS);
559 EXPECT_EQ(UnRegisterClientObserver(nullptr), INVALID_ARGS);
560
561 /**
562 * @tc.steps:step2. call RegisterClientObserver with nullptr clientObserver.
563 * @tc.expected: step2. return INVALID_ARGS.
564 */
565 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
566 EXPECT_NE(db, nullptr);
567 EXPECT_EQ(RegisterClientObserver(db, nullptr), INVALID_ARGS);
568
569 /**
570 * @tc.steps:step3. call RegisterClientObserver and UnRegisterClientObserver with closed db handle.
571 * @tc.expected: step3. return INVALID_ARGS.
572 */
573 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
574 EXPECT_EQ(RegisterClientObserver(db, clientObserver), INVALID_ARGS);
575 EXPECT_EQ(UnRegisterClientObserver(db), INVALID_ARGS);
576 }
577
578 /**
579 * @tc.name: TriggerObserverTest002
580 * @tc.desc: Test trigger client observer in sqlite
581 * @tc.type: FUNC
582 * @tc.require:
583 * @tc.author: zhangshijie
584 */
585 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest002, TestSize.Level0)
586 {
587 /**
588 * @tc.steps:step1. prepare data.
589 * @tc.expected: step1. return ok.
590 */
591 const std::string tableName = "sync_data";
592 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
593
594 /**
595 * @tc.steps:step2. register client observer.
596 * @tc.expected: step2. return ok.
597 */
598 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
599 EXPECT_NE(db, nullptr);
600 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
601 this, std::placeholders::_1);
602 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
603 RegisterDbHook(db);
604
605 /**
606 * @tc.steps:step3. insert data into sync_data, check observer.
607 * @tc.expected: step3. check observer ok.
608 */
609 std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
610 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
611 WaitAndResetNotify();
612 std::atomic<int> count = 0; // 0 is observer triggered counts
613 CheckTriggerObserverTest002(tableName, count);
614
615 /**
616 * @tc.steps:step4. update data, check observer.
617 * @tc.expected: step4. check observer ok.
618 */
619 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
620 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
621 WaitAndResetNotify();
622 CheckTriggerObserverTest002(tableName, count);
623
624 /**
625 * @tc.steps:step4. delete data, check observer.
626 * @tc.expected: step4. check observer ok.
627 */
628 sql = "delete from " + tableName + " where id = 3;";
629 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
630 WaitAndResetNotify();
631 CheckTriggerObserverTest002(tableName, count);
632
633 /**
634 * @tc.steps:step5. register another observer, update data, check observer.
635 * @tc.expected: step5. check observer ok.
636 */
637 triggeredCount_ = 0;
638 ClientObserver clientObserver2 = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc2,
639 this, std::placeholders::_1);
640 EXPECT_EQ(RegisterClientObserver(db, clientObserver2), OK);
641 RegisterDbHook(db);
642 sql = "update " + tableName + " set name = 'lisi2' where id = 2;";
643 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
644 WaitAndResetNotify();
645 EXPECT_EQ(triggeredCount_, 0);
646 EXPECT_EQ(triggeredCount2_, 1);
647
648 /**
649 * @tc.steps:step6. UnRegisterClientObserver, update data, check observer.
650 * @tc.expected: step6. check observer ok.
651 */
652 triggeredCount2_ = 0;
653 EXPECT_EQ(UnRegisterClientObserver(db), OK);
654 sql = "update " + tableName + " set name = 'lisi3' where id = 2;";
655 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
656 EXPECT_EQ(triggeredCount2_, 0); // observer2 will not be triggered
657 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
658 }
659
660 /**
661 * @tc.name: TriggerObserverTest003
662 * @tc.desc: Test RegisterClientObserver and UnRegisterClientObserver concurrently
663 * @tc.type: FUNC
664 * @tc.require:
665 * @tc.author: zhangshijie
666 */
667 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest003, TestSize.Level1)
668 {
669 for (int i = 0; i < 1000; i++) { // 1000 is loop times
__anona8aa9dd30902() 670 std::thread t1 ([this]() {
671 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
672 EXPECT_NE(db, nullptr);
673 ClientObserver clientObserver = std::bind(
674 &DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc, this, std::placeholders::_1);
675 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
676 EXPECT_EQ(UnRegisterClientObserver(db), OK);
677 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
678 });
679
__anona8aa9dd30a02() 680 std::thread t2 ([this]() {
681 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
682 EXPECT_NE(db, nullptr);
683 ClientObserver clientObserver = std::bind(
684 &DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc2, this, std::placeholders::_1);
685 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
686 EXPECT_EQ(UnRegisterClientObserver(db), OK);
687 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
688 });
689
690 t1.join();
691 t2.join();
692 }
693 }
694
695 /**
696 * @tc.name: TriggerObserverTest004
697 * @tc.desc: Test batch insert/update/delete data then trigger client observer
698 * @tc.type: FUNC
699 * @tc.require:
700 * @tc.author: zhangshijie
701 */
702 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest004, TestSize.Level1)
703 {
704 /**
705 * @tc.steps:step1. prepare data.
706 * @tc.expected: step1. return ok.
707 */
708 const std::string tableName = "sync_data";
709 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
710
711 /**
712 * @tc.steps:step2. register client observer.
713 * @tc.expected: step2. return ok.
714 */
715 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
716 EXPECT_NE(db, nullptr);
717 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
718 this, std::placeholders::_1);
719 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
720 RegisterDbHook(db);
721
722 /**
723 * @tc.steps:step3. insert data into sync_data, check observer.
724 * @tc.expected: step3. check observer ok.
725 */
726 std::string sql;
727 int dataCounts = 1000; // 1000 is count of insert options.
728 for (int i = 1; i <= dataCounts; i++) {
729 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
730 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
731 }
732 std::unique_lock<std::mutex> lock(g_mutex);
__anona8aa9dd30b02() 733 bool isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this, dataCounts]() { // 1 is wait time
734 return triggeredCount_ == dataCounts;
735 });
736 EXPECT_EQ(isEqual, true);
737 WaitAndResetNotifyWithLock(lock);
738 ASSERT_EQ(triggerTableData_.size(), 1u);
739 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
740 EXPECT_EQ(triggeredCount_, dataCounts);
741
742 /**
743 * @tc.steps:step4. insert or replace, check observer.
744 * @tc.expected: step5. check observer ok.
745 */
746 triggeredCount_ = 0;
747 sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');";
748 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
__anona8aa9dd30c02() 749 isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this]() { // 1 is wait time
750 return triggeredCount_ == 1;
751 });
752 EXPECT_EQ(isEqual, true);
753 WaitAndResetNotifyWithLock(lock);
754 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert
755 EXPECT_EQ(UnRegisterClientObserver(db), OK);
756 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
757 }
758
759 /**
760 * @tc.name: TriggerObserverTest005
761 * @tc.desc: Test commit and rollback for one table then trigger client observer
762 * @tc.type: FUNC
763 * @tc.require:
764 * @tc.author: chenchaohao
765 */
766 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest005, TestSize.Level1)
767 {
768 /**
769 * @tc.steps:step1. prepare data.
770 * @tc.expected: step1. return ok.
771 */
772 const std::string tableName = "sync_data";
773 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
774
775 /**
776 * @tc.steps:step2. register client observer.
777 * @tc.expected: step2. return ok.
778 */
779 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
780 EXPECT_NE(db, nullptr);
781 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
782 this, std::placeholders::_1);
783 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
784 RegisterDbHook(db);
785
786 /**
787 * @tc.steps:step3. begin transaction and commit.
788 * @tc.expected: step3. check observer ok.
789 */
790 std::string sql = "begin;";
791 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
792 int dataCounts = 1000; // 1000 is count of insert options.
793 for (int i = 1; i <= dataCounts; i++) {
794 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
795 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
796 }
797 sql = "commit;";
798 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
799 WaitAndResetNotify();
800 ASSERT_EQ(triggerTableData_.size(), 1u);
801 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
802 EXPECT_EQ(triggeredCount_, 1);
803
804 /**
805 * @tc.steps:step4. begin transaction and rollback.
806 * @tc.expected: step3. check observer ok.
807 */
808 triggerTableData_.clear();
809 triggeredCount_ = 0;
810 sql = "begin;";
811 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
812 for (int i = dataCounts + 1; i <= 2 * dataCounts; i++) { // 2 is double dataCounts
813 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
814 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
815 }
816 sql = "rollback;";
817 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
818 EXPECT_TRUE(triggerTableData_.empty());
819 EXPECT_EQ(triggeredCount_, 0);
820
821 /**
822 * @tc.steps:step5. insert or replace, check observer.
823 * @tc.expected: step5. check observer ok.
824 */
825 triggeredCount_ = 0;
826 sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');";
827 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
828 WaitAndResetNotify();
829 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert
830 EXPECT_EQ(UnRegisterClientObserver(db), OK);
831 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
832 }
833
834 /**
835 * @tc.name: TriggerObserverTest006
836 * @tc.desc: Test commit and rollback for multi-table then trigger client observer
837 * @tc.type: FUNC
838 * @tc.require:
839 * @tc.author: chenchaohao
840 */
841 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest006, TestSize.Level1)
842 {
843 /**
844 * @tc.steps:step1. prepare data.
845 * @tc.expected: step1. return ok.
846 */
847 const std::string tableName1 = "sync_data1";
848 const std::string tableName2 = "sync_data2";
849 PrepareData({tableName1, tableName2}, false, DistributedDB::CLOUD_COOPERATION, false);
850
851 /**
852 * @tc.steps:step2. register client observer.
853 * @tc.expected: step2. return ok.
854 */
855 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
856 EXPECT_NE(db, nullptr);
857 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
858 this, std::placeholders::_1);
859 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
860 RegisterDbHook(db);
861
862 /**
863 * @tc.steps:step3. begin transaction and commit.
864 * @tc.expected: step3. check observer ok.
865 */
866 std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
867 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
868 WaitAndResetNotify();
869 ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size
870 EXPECT_EQ(triggerTableData_.begin()->first, tableName1);
871 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count
872
873 /**
874 * @tc.steps:step4. UnRegisterClientObserver and insert table2.
875 * @tc.expected: step3. check observer ok.
876 */
877 triggerTableData_.clear();
878 triggeredCount_ = 0;
879 EXPECT_EQ(UnRegisterClientObserver(db), OK);
880 sql = "insert into " + tableName2 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
881 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
882 EXPECT_TRUE(triggerTableData_.empty());
883 EXPECT_EQ(triggeredCount_, 0);
884
885 /**
886 * @tc.steps:step5. RegisterClientObserver again and insert table1, check observer.
887 * @tc.expected: step5. check observer ok.
888 */
889 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
890 RegisterDbHook(db);
891 sql = "insert into " + tableName1 + " VALUES(7, 'zhangjiu');";
892 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
893 WaitAndResetNotify();
894 ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size
895 EXPECT_EQ(triggerTableData_.begin()->first, tableName1);
896 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count
897 EXPECT_EQ(UnRegisterClientObserver(db), OK);
898 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
899 }
900
901 /**
902 * @tc.name: TriggerObserverTest007
903 * @tc.desc: Test trigger client observer in tracker table
904 * @tc.type: FUNC
905 * @tc.require:
906 * @tc.author: zhangshijie
907 */
908 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest007, TestSize.Level0)
909 {
910 /**
911 * @tc.steps:step1. prepare data and set trackerTable
912 * @tc.expected: step1. return ok.
913 */
914 const std::string tableName = "sync_data";
915 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false, false);
916 SetTracerSchemaTest001(tableName);
917
918 /**
919 * @tc.steps:step2. register client observer.
920 * @tc.expected: step2. return ok.
921 */
922 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
923 EXPECT_NE(db, nullptr);
924 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
925 this, std::placeholders::_1);
926 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
927 RegisterDbHook(db);
928
929 /**
930 * @tc.steps:step3. insert data into sync_data, check observer.
931 * @tc.expected: step3. check observer ok.
932 */
933 std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
934 std::unique_lock<std::mutex> lock(g_mutex);
935 ExecSqlAndWaitForObserver(db, sql, lock);
936 ChangeProperties properties;
937 properties.isTrackedDataChange = true;
938 int triggerCount = 1;
939 CheckTriggerTableData(1u, tableName, properties, triggerCount);
940
941 /**
942 * @tc.steps:step4. update data, check observer.
943 * @tc.expected: step4. check observer ok.
944 */
945 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
946 ExecSqlAndWaitForObserver(db, sql, lock);
947 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
948
949 /**
950 * @tc.steps:step5. update to the same data again, check observer.
951 * @tc.expected: step5. check observer ok.
952 */
953 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
954 ExecSqlAndWaitForObserver(db, sql, lock);
955 properties.isTrackedDataChange = false;
956 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
957
958 /**
959 * @tc.steps:step6. update to the same data again, set name is NULL, check observer.
960 * @tc.expected: step6. check observer ok.
961 */
962 sql = "update " + tableName + " set name = NULL where id = 2;";
963 ExecSqlAndWaitForObserver(db, sql, lock);
964 properties.isTrackedDataChange = true;
965 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
966
967 /**
968 * @tc.steps:step7. update to the same data again, set name is empty, check observer.
969 * @tc.expected: step7. check observer ok.
970 */
971 sql = "update " + tableName + " set name = '' where id = 2;";
972 ExecSqlAndWaitForObserver(db, sql, lock);
973 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
974
975 /**
976 * @tc.steps:step8. delete data, check observer.
977 * @tc.expected: step8. check observer ok.
978 */
979 sql = "delete from " + tableName + " where id = 2;";
980 ExecSqlAndWaitForObserver(db, sql, lock);
981 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
982 EXPECT_EQ(UnRegisterClientObserver(db), OK);
983 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
984 }
985
InitLogicDeleteData(sqlite3 * & db,const std::string & tableName,uint64_t num)986 void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num)
987 {
988 for (size_t i = 0; i < num; ++i) {
989 std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');";
990 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
991 }
992 std::string sql = "update " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log" +
993 " SET flag = flag | 0x08";
994 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
995 }
996
CheckLogicDeleteData(sqlite3 * & db,const std::string & tableName,uint64_t expectNum)997 void CheckLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t expectNum)
998 {
999 std::string sql = "select count(*) from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"
1000 " where flag&0x08=0x08 and flag&0x01=0";
1001 sqlite3_stmt *stmt = nullptr;
1002 EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
1003 while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1004 uint64_t count = static_cast<uint64_t>(sqlite3_column_int64(stmt, 0));
1005 EXPECT_EQ(count, expectNum);
1006 }
1007 int errCode;
1008 SQLiteUtils::ResetStatement(stmt, true, errCode);
1009 stmt = nullptr;
1010 sql = "select count(*) from " + tableName;
1011 while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1012 uint64_t count = static_cast<uint64_t>(sqlite3_column_int64(stmt, 0));
1013 EXPECT_EQ(count, expectNum);
1014 }
1015 SQLiteUtils::ResetStatement(stmt, true, errCode);
1016 }
1017
1018 /**
1019 * @tc.name: DropDeleteData001
1020 * @tc.desc: Test trigger client observer in tracker table
1021 * @tc.type: FUNC
1022 * @tc.require:
1023 * @tc.author:
1024 */
1025 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DropDeleteData001, TestSize.Level0)
1026 {
1027 /**
1028 * @tc.steps:step1. prepare data.
1029 * @tc.expected: step1. return ok.
1030 */
1031 const std::string tableName = "sync_data";
1032 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1033 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1034 EXPECT_NE(db, nullptr);
1035 uint64_t num = 10;
1036 InitLogicDeleteData(db, tableName, num);
1037
1038 /**
1039 * @tc.steps:step2. db handle is nullptr
1040 * @tc.expected: step2. return INVALID_ARGS.
1041 */
1042 EXPECT_EQ(DropLogicDeletedData(nullptr, tableName, 0u), INVALID_ARGS);
1043
1044 /**
1045 * @tc.steps:step3. tableName is empty
1046 * @tc.expected: step3. return INVALID_ARGS.
1047 */
1048 EXPECT_EQ(DropLogicDeletedData(db, "", 0u), INVALID_ARGS);
1049
1050 /**
1051 * @tc.steps:step4. tableName is no exist
1052 * @tc.expected: step4. return INVALID_ARGS.
1053 */
1054 EXPECT_EQ(DropLogicDeletedData(db, tableName + "_", 0u), DB_ERROR);
1055
1056 /**
1057 * @tc.steps:step5. cursor is 0
1058 * @tc.expected: step5. return OK.
1059 */
1060 EXPECT_EQ(DropLogicDeletedData(db, tableName, 0u), OK);
1061 CheckLogicDeleteData(db, tableName, 0u);
1062
1063 /**
1064 * @tc.steps:step6. init data again, and cursor is 15
1065 * @tc.expected: step6. return OK.
1066 */
1067 uint64_t cursor = 15;
1068 InitLogicDeleteData(db, tableName, num);
1069 EXPECT_EQ(DropLogicDeletedData(db, tableName, cursor), OK);
1070 CheckLogicDeleteData(db, tableName, cursor - num);
1071 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1072 }
1073
1074 /**
1075 * @tc.name: FfrtTest001
1076 * @tc.desc: Test ffrt concurrency
1077 * @tc.type: FUNC
1078 * @tc.require:
1079 * @tc.author:
1080 */
1081 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level0)
1082 {
1083 std::map<int, int> ans;
1084 #ifdef USE_FFRT
1085 ffrt::mutex mutex;
1086 #else
1087 std::mutex mutex;
1088 #endif
1089 size_t num = 1000;
1090
1091 /**
1092 * @tc.steps:step1. submit insert map task
1093 * @tc.expected: step1. return ok.
1094 */
__anona8aa9dd30d02() 1095 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1096 for (size_t j = 0; j < num; j++) {
1097 ConcurrentAdapter::AdapterAutoLock(mutex);
1098 for (size_t i = 0; i < num; i++) {
1099 ans.insert_or_assign(i, i);
1100 }
1101 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1102 }
1103 }, nullptr, &ans);
1104
1105 /**
1106 * @tc.steps:step2. submit erase map task
1107 * @tc.expected: step2. return ok.
1108 */
__anona8aa9dd30e02() 1109 TaskHandle h2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1110 for (size_t i = 0; i < num; i++) {
1111 ConcurrentAdapter::AdapterAutoLock(mutex);
1112 for (auto it = ans.begin(); it != ans.end();) {
1113 it = ans.erase(it);
1114 }
1115 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1116 }
1117 }, nullptr, &ans);
1118
1119 /**
1120 * @tc.steps:step3. submit get from map task
1121 * @tc.expected: step3. return ok.
1122 */
__anona8aa9dd30f02() 1123 TaskHandle h3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1124 for (size_t i = 0; i < num; i++) {
1125 ConcurrentAdapter::AdapterAutoLock(mutex);
1126 for (auto it = ans.begin(); it != ans.end(); it++) {
1127 int j = it->first;
1128 EXPECT_GE(j, 0);
1129 }
1130 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1131 }
1132 }, &ans, nullptr);
1133 ADAPTER_WAIT(h1);
1134 ADAPTER_WAIT(h2);
1135 ADAPTER_WAIT(h3);
1136 ASSERT_TRUE(ans.empty());
1137 }
1138
1139 /**
1140 * @tc.name: FfrtTest002
1141 * @tc.desc: Test ffrt concurrency
1142 * @tc.type: FUNC
1143 * @tc.require:
1144 * @tc.author:
1145 */
1146 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level0)
1147 {
1148 std::map<int, int> ans;
1149 #ifdef USE_FFRT
1150 ffrt::mutex mutex;
1151 #else
1152 std::mutex mutex;
1153 #endif
1154 size_t num = 1000;
1155
1156 /**
1157 * @tc.steps:step1. subtask submit insert map task
1158 * @tc.expected: step1. return ok.
1159 */
__anona8aa9dd31002() 1160 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1161 TaskHandle hh1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1162 for (size_t j = 0; j < num; j++) {
1163 ConcurrentAdapter::AdapterAutoLock(mutex);
1164 for (size_t i = 0; i < num; i++) {
1165 ans.insert_or_assign(i, i);
1166 }
1167 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1168 }
1169 }, nullptr, &ans);
1170 ADAPTER_WAIT(hh1);
1171 });
1172
1173 /**
1174 * @tc.steps:step2. subtask submit erase map task
1175 * @tc.expected: step2. return ok.
1176 */
__anona8aa9dd31202() 1177 TaskHandle h2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1178 TaskHandle hh2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1179 for (size_t i = 0; i < num; i++) {
1180 ConcurrentAdapter::AdapterAutoLock(mutex);
1181 for (auto it = ans.begin(); it != ans.end();) {
1182 it = ans.erase(it);
1183 }
1184 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1185 }
1186 }, nullptr, &ans);
1187 ADAPTER_WAIT(hh2);
1188 });
1189
1190 /**
1191 * @tc.steps:step3. subtask submit get from map task
1192 * @tc.expected: step3. return ok.
1193 */
__anona8aa9dd31402() 1194 TaskHandle h3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1195 TaskHandle hh3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1196 for (size_t i = 0; i < num; i++) {
1197 ConcurrentAdapter::AdapterAutoLock(mutex);
1198 for (auto it = ans.begin(); it != ans.end(); it++) {
1199 int j = it->first;
1200 EXPECT_GE(j, 0);
1201 }
1202 ConcurrentAdapter::AdapterAutoUnLock(mutex);
1203 }
1204 }, &ans, nullptr);
1205 ADAPTER_WAIT(hh3);
1206 });
1207 ADAPTER_WAIT(h1);
1208 ADAPTER_WAIT(h2);
1209 ADAPTER_WAIT(h3);
1210 }
1211
1212 /**
1213 * @tc.name: FfrtTest003
1214 * @tc.desc: Test ffrt concurrency
1215 * @tc.type: FUNC
1216 * @tc.require:
1217 * @tc.author:
1218 */
1219 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level0)
1220 {
1221 size_t count = 0;
1222 size_t num = 3000;
1223 std::vector<TaskHandle> waitVec;
1224
1225 /**
1226 * @tc.steps:step1. submit increase task
1227 * @tc.expected: step1. return ok.
1228 */
1229 for (size_t j = 0; j < num; j++) {
__anona8aa9dd31602() 1230 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &count, num]() {
1231 for (size_t i = 0; i < num; i++) {
1232 count++;
1233 }
1234 }, nullptr, nullptr);
1235 waitVec.push_back(std::move(h1));
1236 }
1237 for (const auto &item : waitVec) {
1238 ADAPTER_WAIT(item);
1239 }
1240
1241 /**
1242 * @tc.steps:step2. check count
1243 * @tc.expected: step2. return ok.
1244 */
1245 #ifdef USE_FFRT
1246 EXPECT_LE(count, num * num);
1247 #else
1248 EXPECT_EQ(count, num * num);
1249 #endif
1250 }
1251
1252 /**
1253 * @tc.name: AbnormalDelegateTest001
1254 * @tc.desc: Test delegate interface after delegate is closed
1255 * @tc.type: FUNC
1256 * @tc.require:
1257 * @tc.author: chenchaohao
1258 */
1259 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateTest001, TestSize.Level0)
1260 {
1261 /**
1262 * @tc.steps:step1. create db and open store
1263 * @tc.expected: step1. return ok.
1264 */
1265 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1266 ASSERT_NE(db, nullptr);
1267 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1268 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1269 RelationalStoreDelegate *delegate = nullptr;
1270 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1271 EXPECT_EQ(status, OK);
1272 ASSERT_NE(delegate, nullptr);
1273
1274 /**
1275 * @tc.steps:step2. close delegate
1276 * @tc.expected: step2. return ok.
1277 */
1278 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1279 status = delegateImpl->Close();
1280 EXPECT_EQ(status, OK);
1281
1282 /**
1283 * @tc.steps:step3. test interface after delegate is closed
1284 * @tc.expected: step3. return ok.
1285 */
1286 const std::string tableName = "sync_data";
1287 EXPECT_EQ(delegateImpl->RemoveDeviceData("", tableName), DB_ERROR);
1288 EXPECT_EQ(delegate->RemoveDeviceData("", FLAG_AND_DATA), DB_ERROR);
1289 EXPECT_EQ(delegate->GetCloudSyncTaskCount(), -1); // -1 is error count
1290 EXPECT_EQ(delegate->CreateDistributedTable(tableName, CLOUD_COOPERATION), DB_ERROR);
1291 EXPECT_EQ(delegate->UnRegisterObserver(), DB_ERROR);
1292 DataBaseSchema dataBaseSchema;
1293 EXPECT_EQ(delegate->SetCloudDbSchema(dataBaseSchema), DB_ERROR);
1294 EXPECT_EQ(delegate->SetReference({}), DB_ERROR);
1295 TrackerSchema trackerSchema;
1296 EXPECT_EQ(delegate->SetTrackerTable(trackerSchema), DB_ERROR);
1297 EXPECT_EQ(delegate->CleanTrackerData(tableName, 0), DB_ERROR);
1298 bool logicDelete = true;
1299 auto data = static_cast<PragmaData>(&logicDelete);
1300 EXPECT_EQ(delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data), DB_ERROR);
1301 std::vector<VBucket> records;
1302 RecordStatus recordStatus = RecordStatus::WAIT_COMPENSATED_SYNC;
1303 EXPECT_EQ(delegate->UpsertData(tableName, records, recordStatus), DB_ERROR);
1304
1305 /**
1306 * @tc.steps:step4. close store
1307 * @tc.expected: step4. return ok.
1308 */
1309 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1310 delegate = nullptr;
1311 }
1312
InitDataStatus(const std::string & tableName,int count,sqlite3 * db)1313 void InitDataStatus(const std::string &tableName, int count, sqlite3 *db)
1314 {
1315 int type = 4; // the num of different status
1316 for (int i = 1; i <= type * count; i++) {
1317 std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" +
1318 std::to_string(i) + "');";
1319 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1320 }
1321 std::string countStr = std::to_string(count);
1322 std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status=(CASE WHEN data_key<=" +
1323 countStr + " THEN 0 WHEN data_key>" + countStr + " AND data_key<=2*" + countStr + " THEN 1 WHEN data_key>2*" +
1324 countStr + " AND data_key<=3*" + countStr + " THEN 2 ELSE 3 END)";
1325 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1326 }
1327
CheckDataStatus(const std::string & tableName,const std::string & condition,sqlite3 * db,int64_t expect)1328 void CheckDataStatus(const std::string &tableName, const std::string &condition, sqlite3 *db, int64_t expect)
1329 {
1330 std::string sql = "SELECT count(1) FROM " + DBCommon::GetLogTableName(tableName) + " WHERE " + condition;
1331 sqlite3_stmt *stmt = nullptr;
1332 EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
1333 while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1334 int64_t count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
1335 EXPECT_EQ(count, expect);
1336 }
1337 int errCode;
1338 SQLiteUtils::ResetStatement(stmt, true, errCode);
1339 }
1340
1341 /**
1342 * @tc.name: LockDataTest001
1343 * @tc.desc: Test status after lock
1344 * @tc.type: FUNC
1345 * @tc.require:
1346 * @tc.author: bty
1347 */
1348 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level0)
1349 {
1350 /**
1351 * @tc.steps:step1. init data and lock, hashKey has no matching data
1352 * @tc.expected: step1. return NOT_FOUND.
1353 */
1354 const std::string tableName = "sync_data";
1355 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1356 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1357 EXPECT_NE(db, nullptr);
1358 int count = 10;
1359 InitDataStatus(tableName, count, db);
1360 std::vector<std::vector<uint8_t>> hashKey;
1361 hashKey.push_back({'1'});
1362 EXPECT_EQ(Lock(tableName, hashKey, db), NOT_FOUND);
1363
1364 /**
1365 * @tc.steps:step2. init data and lock, hashKey has matching data
1366 * @tc.expected: step2. return OK.
1367 */
1368 hashKey.clear();
1369 CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey);
1370 EXPECT_EQ(Lock(tableName, hashKey, db), OK);
1371
1372 /**
1373 * @tc.steps:step3. check status
1374 * @tc.expected: step3. return OK.
1375 */
1376 CheckDataStatus(tableName, " status = 2 and data_key <= 10 ", db, count);
1377 CheckDataStatus(tableName, " status = 3 and data_key <= 20 ", db, count);
1378 CheckDataStatus(tableName, " status = 2 ", db, count + count);
1379 CheckDataStatus(tableName, " status = 3 ", db, count + count);
1380 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1381 }
1382
1383 /**
1384 * @tc.name: LockDataTest002
1385 * @tc.desc: Test status after unLock
1386 * @tc.type: FUNC
1387 * @tc.require:
1388 * @tc.author: bty
1389 */
1390 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level0)
1391 {
1392 /**
1393 * @tc.steps:step1. init data and unLock, there is data to be compensated for
1394 * @tc.expected: step1. return WAIT_COMPENSATED_SYNC.
1395 */
1396 const std::string tableName = "sync_data";
1397 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1398 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1399 EXPECT_NE(db, nullptr);
1400 int count = 10;
1401 InitDataStatus(tableName, count, db);
1402 std::vector<std::vector<uint8_t>> hashKey;
1403 CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey);
1404 EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC);
1405
1406 /**
1407 * @tc.steps:step2. check status
1408 * @tc.expected: step2. return OK.
1409 */
1410 CheckDataStatus(tableName, " status = 0 and data_key <= 10 ", db, count);
1411 CheckDataStatus(tableName, " status = 1 and data_key <= 20 ", db, count);
1412 CheckDataStatus(tableName, " status = 0 ", db, count + count);
1413 CheckDataStatus(tableName, " status = 1 ", db, count + count);
1414
1415 /**
1416 * @tc.steps:step3. unLock again, there is data to be compensated for
1417 * @tc.expected: step3. return WAIT_COMPENSATED_SYNC.
1418 */
1419 EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC);
1420
1421 /**
1422 * @tc.steps:step4. unLock again, there is no data to be compensated for
1423 * @tc.expected: step4. return OK.
1424 */
1425 std::string sql = "update " + DBCommon::GetLogTableName(tableName) + " SET status=0";
1426 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1427 EXPECT_EQ(UnLock(tableName, hashKey, db), OK);
1428
1429 /**
1430 * @tc.steps:step5. unLock again, hashKey has matching data
1431 * @tc.expected: step5. return NOT_FOUND.
1432 */
1433 hashKey.clear();
1434 hashKey.push_back({'1'});
1435 EXPECT_EQ(UnLock(tableName, hashKey, db), NOT_FOUND);
1436 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1437 }
1438
1439 /**
1440 * @tc.name: LockDataTest003
1441 * @tc.desc: Test status after local change
1442 * @tc.type: FUNC
1443 * @tc.require:
1444 * @tc.author: bty
1445 */
1446 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest003, TestSize.Level0)
1447 {
1448 /**
1449 * @tc.steps:step1. update data and check
1450 * @tc.expected: step1. return E_OK.
1451 */
1452 const std::string tableName = "sync_data";
1453 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1454 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1455 EXPECT_NE(db, nullptr);
1456 int count = 10;
1457 InitDataStatus(tableName, count, db);
1458 std::string sql = "update " + tableName + " SET name='1' where id in (1,11,21,31)";
1459 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1460 CheckDataStatus(tableName, " status = 3 and data_key in (1,11,21,31) ", db, 2); // 2 is changed count
1461
1462 /**
1463 * @tc.steps:step1. delete data and check
1464 * @tc.expected: step1. return E_OK.
1465 */
1466 sql = "delete from " + tableName + " where id in (2,12,22,32)";
1467 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1468 CheckDataStatus(tableName, " status = 1 and data_key = -1 ", db, 3); // 3 is changed count
1469 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1470 }
1471
1472 DistributedDB::StoreObserver::StoreChangedInfo g_changedData;
1473
1474 class MockStoreObserver : public StoreObserver {
1475 public:
~MockStoreObserver()1476 virtual ~MockStoreObserver() {};
OnChange(StoreChangedInfo && data)1477 void OnChange(StoreChangedInfo &&data) override
1478 {
1479 g_changedData = data;
1480 std::unique_lock<std::mutex> lock(g_mutex);
1481 g_cv.notify_one();
1482 g_alreadyNotify = true;
1483 };
1484 };
1485
CreateTableForStoreObserver(sqlite3 * db,const std::string tableName)1486 void CreateTableForStoreObserver(sqlite3 *db, const std::string tableName)
1487 {
1488 std::string sql = "create table " + tableName + "(id INTEGER primary key, name TEXT);";
1489 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1490 sql = "create table no_" + tableName + "(id INTEGER, name TEXT);";
1491 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1492 sql = "create table mult_" + tableName + "(id INTEGER, name TEXT, age int, ";
1493 sql += "PRIMARY KEY (id, name));";
1494 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1495 }
1496
PrepareDataForStoreObserver(sqlite3 * db,const std::string & tableName,int begin,int dataCounts)1497 void PrepareDataForStoreObserver(sqlite3 *db, const std::string &tableName, int begin, int dataCounts)
1498 {
1499 std::string sql = "begin;";
1500 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1501 for (int i = begin; i < begin + dataCounts; i++) {
1502 sql = "insert into " + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan" +
1503 std::to_string(i + 1) + "');";
1504 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1505 sql = "insert into no_" + tableName +" VALUES(" + std::to_string(i + 1) + ", 'zhangsan" +
1506 std::to_string(i + 1) + "');";
1507 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1508 sql = "insert into mult_" + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan";
1509 sql += std::to_string(i + 1) + "', 18);";
1510 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1511 }
1512 for (int i = begin; i < dataCounts / 2 + begin; i++) { // 2 is half
1513 sql = "update " + tableName + " set name = 'lisi' where id = " + std::to_string(i + 1) + ";";
1514 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1515 sql = "update no_" + tableName + " set name = 'lisi' where _rowid_ = " + std::to_string(i + 1) + ";";
1516 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1517 sql = "update mult_" + tableName + " set age = 20 where id = " + std::to_string(i + 1);
1518 sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';";
1519 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1520 }
1521 for (int i = dataCounts / 2 + begin; i < dataCounts + begin; i++) { // 2 is half
1522 sql = "delete from " + tableName + " where id = " + std::to_string(i + 1) + ";";
1523 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1524 sql = "delete from no_" + tableName + " where _rowid_ = " + std::to_string(i + 1) + ";";
1525 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1526 sql = "delete from mult_" + tableName + " where id = " + std::to_string(i + 1);
1527 sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';";
1528 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1529 }
1530 sql = "commit;";
1531 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1532 }
1533
CheckChangedData(int num,int times=0,int offset=0)1534 void CheckChangedData(int num, int times = 0, int offset = 0)
1535 {
1536 if (num == 1) {
1537 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) {
1538 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]),
1539 static_cast<int64_t>(i + offset - times * 5)); // 5 is rowid times
1540 }
1541 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) {
1542 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]),
1543 static_cast<int64_t>(i + offset + 5)); // 5 is offset
1544 }
1545 return;
1546 }
1547 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) {
1548 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]),
1549 static_cast<int64_t>(i + offset));
1550 }
1551 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_UPDATE].size(); i++) {
1552 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_UPDATE][i - 1][0]),
1553 static_cast<int64_t>(i + offset));
1554 }
1555 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) {
1556 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]),
1557 static_cast<int64_t>(i + offset + 5)); // 5 is offset
1558 }
1559 }
1560
1561 /**
1562 * @tc.name: RegisterStoreObserverTest001
1563 * @tc.desc: Test commit for three table then trigger store observer
1564 * @tc.type: FUNC
1565 * @tc.require:
1566 * @tc.author: chenchaohao
1567 */
1568 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest001, TestSize.Level1)
1569 {
1570 /**
1571 * @tc.steps:step1. prepare db and create table.
1572 * @tc.expected: step1. return ok.
1573 */
1574 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1575 EXPECT_NE(db, nullptr);
1576 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1577 std::string tableName = "primary_test";
1578 CreateTableForStoreObserver(db, tableName);
1579
1580 /**
1581 * @tc.steps:step2. register store observer and check onchange.
1582 * @tc.expected: step2. return ok.
1583 */
1584 auto storeObserver = std::make_shared<MockStoreObserver>();
1585 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1586 RegisterDbHook(db);
1587 EXPECT_TRUE(g_changedData.empty());
1588 int dataCounts = 10; // 10 is count of insert options.
1589 int begin = 0;
1590 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1591 {
1592 std::unique_lock<std::mutex> lock(g_mutex);
__anona8aa9dd31702() 1593 g_cv.wait(lock, []() {
1594 return g_alreadyNotify;
1595 });
1596 g_alreadyNotify = false;
1597 }
1598 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1599 CheckChangedData(0);
1600 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1601 CheckChangedData(1);
1602 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1603 CheckChangedData(2); // 2 is mult primary table
1604 g_changedData.clear();
1605
1606 /**
1607 * @tc.steps:step3. unregister store observer and update data check onchange.
1608 * @tc.expected: step3. return ok.
1609 */
1610 EXPECT_EQ(UnregisterStoreObserver(db), OK);
1611 begin = 10; // 10 is begin id
1612 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1613 EXPECT_TRUE(g_changedData.empty());
1614 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1615 }
1616
1617 /**
1618 * @tc.name: RegisterStoreObserverTest002
1619 * @tc.desc: Test commit for three table then trigger client observer when register then create table
1620 * @tc.type: FUNC
1621 * @tc.require:
1622 * @tc.author: chenchaohao
1623 */
1624 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest002, TestSize.Level1)
1625 {
1626 /**
1627 * @tc.steps:step1. prepare db and register store observer then create table.
1628 * @tc.expected: step1. return ok.
1629 */
1630 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1631 EXPECT_NE(db, nullptr);
1632 auto storeObserver = std::make_shared<MockStoreObserver>();
1633 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1634 RegisterDbHook(db);
1635 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1636 std::string tableName = "primary_test";
1637 CreateTableForStoreObserver(db, tableName);
1638
1639 /**
1640 * @tc.steps:step2. update data and check onchange.
1641 * @tc.expected: step2. return ok.
1642 */
1643 EXPECT_TRUE(g_changedData.empty());
1644 int dataCounts = 10; // 10 is count of insert options.
1645 int begin = 0;
1646 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1647 WaitAndResetNotify();
1648 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1649 CheckChangedData(0);
1650 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1651 CheckChangedData(1);
1652 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1653 CheckChangedData(2); // 2 is mult primary table
1654 g_changedData.clear();
1655
1656 /**
1657 * @tc.steps:step3. unregister store observer and update data check onchange.
1658 * @tc.expected: step3. return ok.
1659 */
1660 EXPECT_EQ(UnregisterStoreObserver(db), OK);
1661 begin = 10; // 11 is begin id
1662 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1663 EXPECT_TRUE(g_changedData.empty());
1664 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1665 }
1666
1667 /**
1668 * @tc.name: RegisterStoreObserverTest003
1669 * @tc.desc: Test commit for three table then trigger client observer when register two observer
1670 * @tc.type: FUNC
1671 * @tc.require:
1672 * @tc.author: chenchaohao
1673 */
1674 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest003, TestSize.Level1)
1675 {
1676 /**
1677 * @tc.steps:step1. prepare db and register store observer then create table.
1678 * @tc.expected: step1. return ok.
1679 */
1680 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1681 EXPECT_NE(db, nullptr);
1682 auto storeObserver1 = std::make_shared<MockStoreObserver>();
1683 auto storeObserver2 = std::make_shared<MockStoreObserver>();
1684 EXPECT_EQ(RegisterStoreObserver(db, storeObserver1), OK);
1685 EXPECT_EQ(RegisterStoreObserver(db, storeObserver2), OK);
1686 RegisterDbHook(db);
1687 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1688 std::string tableName = "primary_test";
1689 CreateTableForStoreObserver(db, tableName);
1690
1691 /**
1692 * @tc.steps:step2. update data and check onchange.
1693 * @tc.expected: step2. return ok.
1694 */
1695 EXPECT_TRUE(g_changedData.empty());
1696 int dataCounts = 10; // 10 is count of insert options.
1697 int begin = 0;
1698 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1699 WaitAndResetNotify();
1700 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1701 CheckChangedData(0);
1702 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1703 CheckChangedData(1);
1704 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1705 CheckChangedData(2); // 2 is mult primary table
1706 g_changedData.clear();
1707
1708 /**
1709 * @tc.steps:step3. unregister store observer and update data check onchange.
1710 * @tc.expected: step3. return ok.
1711 */
1712 EXPECT_EQ(UnregisterStoreObserver(db, storeObserver1), OK);
1713 begin = 10; // 11 is begin id
1714 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1715 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1716 CheckChangedData(0, 1, dataCounts);
1717 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1718 CheckChangedData(1, 1, dataCounts);
1719 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1720 CheckChangedData(2, 1, dataCounts); // 2 is mult primary table
1721 g_changedData.clear();
1722
1723 EXPECT_EQ(UnregisterStoreObserver(db, storeObserver2), OK);
1724 begin = 20; // 21 is begin id
1725 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1726 EXPECT_TRUE(g_changedData.empty());
1727 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1728 }
1729
1730 /**
1731 * @tc.name: RegisterStoreObserverTest004
1732 * @tc.desc: Test register two same observer
1733 * @tc.type: FUNC
1734 * @tc.require:
1735 * @tc.author: chenchaohao
1736 */
1737 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest004, TestSize.Level1)
1738 {
1739 /**
1740 * @tc.steps:step1. prepare db and register store observer then create table.
1741 * @tc.expected: step1. return ok.
1742 */
1743 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1744 EXPECT_NE(db, nullptr);
1745 auto storeObserver = std::make_shared<MockStoreObserver>();
1746 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1747 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1748 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1749 }
1750
1751 /**
1752 * @tc.name: AbnormalDelegateImplTest001
1753 * @tc.desc: Test delegateImpl interface after delegate is closed
1754 * @tc.type: FUNC
1755 * @tc.require:
1756 * @tc.author: suyue
1757 */
1758 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest001, TestSize.Level0)
1759 {
1760 /**
1761 * @tc.steps:step1. create db and open store.
1762 * @tc.expected: step1. return ok.
1763 */
1764 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1765 ASSERT_NE(db, nullptr);
1766 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1767 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1768 RelationalStoreDelegate *delegate = nullptr;
1769 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1770 EXPECT_EQ(status, OK);
1771 ASSERT_NE(delegate, nullptr);
1772
1773 /**
1774 * @tc.steps: step2. close delegate.
1775 * @tc.expected: step2. return ok.
1776 */
1777 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1778 status = delegateImpl->Close();
1779 EXPECT_EQ(status, OK);
1780
1781 /**
1782 * @tc.steps:step3. test DelegateImpl interface after delegate is closed.
1783 * @tc.expected: step3. return DB_ERROR.
1784 */
1785 const RemoteCondition condition;
1786 std::shared_ptr<ResultSet> result = nullptr;
1787 DBStatus ret = delegateImpl->RemoteQuery("", condition, 0, result);
1788 EXPECT_EQ(ret, DB_ERROR);
1789 EXPECT_EQ(delegateImpl->RemoveDeviceData(), DB_ERROR);
1790
1791 StoreObserver observer;
1792 EXPECT_EQ(delegateImpl->RegisterObserver(&observer), DB_ERROR);
1793 EXPECT_EQ(delegateImpl->UnRegisterObserver(&observer), DB_ERROR);
1794 DistributedDB::SqlCondition sqlCondition;
1795 std::vector<VBucket> records = {};
1796 EXPECT_EQ(delegateImpl->ExecuteSql(sqlCondition, records), DB_ERROR);
1797 EXPECT_EQ(delegateImpl->UpsertData("", records, RecordStatus::WAIT_COMPENSATED_SYNC), DB_ERROR);
1798 const CloudSyncConfig config;
1799 EXPECT_EQ(delegateImpl->SetCloudSyncConfig(config), DB_ERROR);
1800
1801 /**
1802 * @tc.steps:step4. close store.
1803 * @tc.expected: step4. return ok.
1804 */
1805 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1806 delegate = nullptr;
1807 }
1808
1809 /**
1810 * @tc.name: AbnormalDelegateImplTest002
1811 * @tc.desc: Test delegate interface after delegate is closed
1812 * @tc.type: FUNC
1813 * @tc.require:
1814 * @tc.author: suyue
1815 */
1816 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest002, TestSize.Level0)
1817 {
1818 /**
1819 * @tc.steps:step1. create db and open store.
1820 * @tc.expected: step1. return ok.
1821 */
1822 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1823 ASSERT_NE(db, nullptr);
1824 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1825 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1826 RelationalStoreDelegate *delegate = nullptr;
1827 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1828 EXPECT_EQ(status, OK);
1829 ASSERT_NE(delegate, nullptr);
1830
1831 /**
1832 * @tc.steps:step2. test DelegateImpl interface when para is err.
1833 * @tc.expected: step2. return INVALID_ARGS or NOT_FOUND.
1834 */
1835 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1836 const CloudSyncConfig config;
1837 EXPECT_EQ(delegateImpl->SetCloudSyncConfig(config), OK);
1838 DistributedDB::SqlCondition sqlCondition;
1839 std::vector<VBucket> records = {};
1840 EXPECT_EQ(delegateImpl->ExecuteSql(sqlCondition, records), INVALID_ARGS);
1841 EXPECT_EQ(delegateImpl->UpsertData("", records, RecordStatus::WAIT_COMPENSATED_SYNC), INVALID_ARGS);
1842 EXPECT_EQ(delegateImpl->CleanTrackerData("", 0), INVALID_ARGS);
1843 TrackerSchema schema;
1844 EXPECT_EQ(delegateImpl->SetTrackerTable(schema), INVALID_ARGS);
1845 schema = {.tableName = "test", .extendColNames = {}, .trackerColNames = {}};
1846 EXPECT_EQ(delegateImpl->SetTrackerTable(schema), NOT_FOUND);
1847
1848 /**
1849 * @tc.steps:step3. close store.
1850 * @tc.expected: step3. return ok.
1851 */
1852 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1853 delegate = nullptr;
1854 }
1855 }
1856