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.extendColName = "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);
__anon41da56cb0402(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 " + 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;
__anon41da56cb0602(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 " + 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 " + 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;
__anon41da56cb0802(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
604 /**
605 * @tc.steps:step3. insert data into sync_data, check observer.
606 * @tc.expected: step3. check observer ok.
607 */
608 std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
609 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
610 WaitAndResetNotify();
611 std::atomic<int> count = 0; // 0 is observer triggered counts
612 CheckTriggerObserverTest002(tableName, count);
613
614 /**
615 * @tc.steps:step4. update data, check observer.
616 * @tc.expected: step4. check observer ok.
617 */
618 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
619 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
620 WaitAndResetNotify();
621 CheckTriggerObserverTest002(tableName, count);
622
623 /**
624 * @tc.steps:step4. delete data, check observer.
625 * @tc.expected: step4. check observer ok.
626 */
627 sql = "delete from " + tableName + " where id = 3;";
628 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
629 WaitAndResetNotify();
630 CheckTriggerObserverTest002(tableName, count);
631
632 /**
633 * @tc.steps:step5. register another observer, update data, check observer.
634 * @tc.expected: step5. check observer ok.
635 */
636 triggeredCount_ = 0;
637 ClientObserver clientObserver2 = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc2,
638 this, std::placeholders::_1);
639 EXPECT_EQ(RegisterClientObserver(db, clientObserver2), OK);
640 sql = "update " + tableName + " set name = 'lisi2' where id = 2;";
641 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
642 WaitAndResetNotify();
643 EXPECT_EQ(triggeredCount_, 0);
644 EXPECT_EQ(triggeredCount2_, 1);
645
646 /**
647 * @tc.steps:step6. UnRegisterClientObserver, update data, check observer.
648 * @tc.expected: step6. check observer ok.
649 */
650 triggeredCount2_ = 0;
651 EXPECT_EQ(UnRegisterClientObserver(db), OK);
652 sql = "update " + tableName + " set name = 'lisi3' where id = 2;";
653 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
654 EXPECT_EQ(triggeredCount2_, 0); // observer2 will not be triggered
655 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
656 }
657
658 /**
659 * @tc.name: TriggerObserverTest003
660 * @tc.desc: Test RegisterClientObserver and UnRegisterClientObserver concurrently
661 * @tc.type: FUNC
662 * @tc.require:
663 * @tc.author: zhangshijie
664 */
665 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest003, TestSize.Level1)
666 {
667 for (int i = 0; i < 1000; i++) { // 1000 is loop times
__anon41da56cb0902() 668 std::thread t1 ([this]() {
669 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
670 EXPECT_NE(db, nullptr);
671 ClientObserver clientObserver = std::bind(
672 &DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc, this, std::placeholders::_1);
673 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
674 EXPECT_EQ(UnRegisterClientObserver(db), OK);
675 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
676 });
677
__anon41da56cb0a02() 678 std::thread t2 ([this]() {
679 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
680 EXPECT_NE(db, nullptr);
681 ClientObserver clientObserver = std::bind(
682 &DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc2, this, std::placeholders::_1);
683 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
684 EXPECT_EQ(UnRegisterClientObserver(db), OK);
685 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
686 });
687
688 t1.join();
689 t2.join();
690 }
691 }
692
693 /**
694 * @tc.name: TriggerObserverTest004
695 * @tc.desc: Test batch insert/update/delete data then trigger client observer
696 * @tc.type: FUNC
697 * @tc.require:
698 * @tc.author: zhangshijie
699 */
700 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest004, TestSize.Level1)
701 {
702 /**
703 * @tc.steps:step1. prepare data.
704 * @tc.expected: step1. return ok.
705 */
706 const std::string tableName = "sync_data";
707 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
708
709 /**
710 * @tc.steps:step2. register client observer.
711 * @tc.expected: step2. return ok.
712 */
713 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
714 EXPECT_NE(db, nullptr);
715 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
716 this, std::placeholders::_1);
717 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
718
719 /**
720 * @tc.steps:step3. insert data into sync_data, check observer.
721 * @tc.expected: step3. check observer ok.
722 */
723 std::string sql;
724 int dataCounts = 1000; // 1000 is count of insert options.
725 for (int i = 1; i <= dataCounts; i++) {
726 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
727 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
728 }
729 std::unique_lock<std::mutex> lock(g_mutex);
__anon41da56cb0b02() 730 bool isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this, dataCounts]() { // 1 is wait time
731 return triggeredCount_ == dataCounts;
732 });
733 EXPECT_EQ(isEqual, true);
734 WaitAndResetNotifyWithLock(lock);
735 ASSERT_EQ(triggerTableData_.size(), 1u);
736 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
737 EXPECT_EQ(triggeredCount_, dataCounts);
738
739 /**
740 * @tc.steps:step4. insert or replace, check observer.
741 * @tc.expected: step5. check observer ok.
742 */
743 triggeredCount_ = 0;
744 sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');";
745 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
__anon41da56cb0c02() 746 isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this]() { // 1 is wait time
747 return triggeredCount_ == 1;
748 });
749 EXPECT_EQ(isEqual, true);
750 WaitAndResetNotifyWithLock(lock);
751 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert
752 EXPECT_EQ(UnRegisterClientObserver(db), OK);
753 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
754 }
755
756 /**
757 * @tc.name: TriggerObserverTest005
758 * @tc.desc: Test commit and rollback for one table then trigger client observer
759 * @tc.type: FUNC
760 * @tc.require:
761 * @tc.author: chenchaohao
762 */
763 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest005, TestSize.Level1)
764 {
765 /**
766 * @tc.steps:step1. prepare data.
767 * @tc.expected: step1. return ok.
768 */
769 const std::string tableName = "sync_data";
770 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
771
772 /**
773 * @tc.steps:step2. register client observer.
774 * @tc.expected: step2. return ok.
775 */
776 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
777 EXPECT_NE(db, nullptr);
778 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
779 this, std::placeholders::_1);
780 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
781
782 /**
783 * @tc.steps:step3. begin transaction and commit.
784 * @tc.expected: step3. check observer ok.
785 */
786 std::string sql = "begin;";
787 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
788 int dataCounts = 1000; // 1000 is count of insert options.
789 for (int i = 1; i <= dataCounts; i++) {
790 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
791 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
792 }
793 sql = "commit;";
794 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
795 WaitAndResetNotify();
796 ASSERT_EQ(triggerTableData_.size(), 1u);
797 EXPECT_EQ(triggerTableData_.begin()->first, tableName);
798 EXPECT_EQ(triggeredCount_, 1);
799
800 /**
801 * @tc.steps:step4. begin transaction and rollback.
802 * @tc.expected: step3. check observer ok.
803 */
804 triggerTableData_.clear();
805 triggeredCount_ = 0;
806 sql = "begin;";
807 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
808 for (int i = dataCounts + 1; i <= 2 * dataCounts; i++) { // 2 is double dataCounts
809 sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');";
810 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
811 }
812 sql = "rollback;";
813 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
814 EXPECT_TRUE(triggerTableData_.empty());
815 EXPECT_EQ(triggeredCount_, 0);
816
817 /**
818 * @tc.steps:step5. insert or replace, check observer.
819 * @tc.expected: step5. check observer ok.
820 */
821 triggeredCount_ = 0;
822 sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');";
823 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
824 WaitAndResetNotify();
825 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert
826 EXPECT_EQ(UnRegisterClientObserver(db), OK);
827 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
828 }
829
830 /**
831 * @tc.name: TriggerObserverTest006
832 * @tc.desc: Test commit and rollback for multi-table then trigger client observer
833 * @tc.type: FUNC
834 * @tc.require:
835 * @tc.author: chenchaohao
836 */
837 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest006, TestSize.Level1)
838 {
839 /**
840 * @tc.steps:step1. prepare data.
841 * @tc.expected: step1. return ok.
842 */
843 const std::string tableName1 = "sync_data1";
844 const std::string tableName2 = "sync_data2";
845 PrepareData({tableName1, tableName2}, false, DistributedDB::CLOUD_COOPERATION, false);
846
847 /**
848 * @tc.steps:step2. register client observer.
849 * @tc.expected: step2. return ok.
850 */
851 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
852 EXPECT_NE(db, nullptr);
853 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
854 this, std::placeholders::_1);
855 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
856
857 /**
858 * @tc.steps:step3. begin transaction and commit.
859 * @tc.expected: step3. check observer ok.
860 */
861 std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
862 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
863 WaitAndResetNotify();
864 ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size
865 EXPECT_EQ(triggerTableData_.begin()->first, tableName1);
866 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count
867
868 /**
869 * @tc.steps:step4. UnRegisterClientObserver and insert table2.
870 * @tc.expected: step3. check observer ok.
871 */
872 triggerTableData_.clear();
873 triggeredCount_ = 0;
874 EXPECT_EQ(UnRegisterClientObserver(db), OK);
875 sql = "insert into " + tableName2 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
876 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
877 EXPECT_TRUE(triggerTableData_.empty());
878 EXPECT_EQ(triggeredCount_, 0);
879
880 /**
881 * @tc.steps:step5. RegisterClientObserver again and insert table1, check observer.
882 * @tc.expected: step5. check observer ok.
883 */
884 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
885 sql = "insert into " + tableName1 + " VALUES(7, 'zhangjiu');";
886 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
887 WaitAndResetNotify();
888 ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size
889 EXPECT_EQ(triggerTableData_.begin()->first, tableName1);
890 EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count
891 EXPECT_EQ(UnRegisterClientObserver(db), OK);
892 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
893 }
894
895 /**
896 * @tc.name: TriggerObserverTest007
897 * @tc.desc: Test trigger client observer in tracker table
898 * @tc.type: FUNC
899 * @tc.require:
900 * @tc.author: zhangshijie
901 */
902 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest007, TestSize.Level0)
903 {
904 /**
905 * @tc.steps:step1. prepare data and set trackerTable
906 * @tc.expected: step1. return ok.
907 */
908 const std::string tableName = "sync_data";
909 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false, false);
910 SetTracerSchemaTest001(tableName);
911
912 /**
913 * @tc.steps:step2. register client observer.
914 * @tc.expected: step2. return ok.
915 */
916 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
917 EXPECT_NE(db, nullptr);
918 ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc,
919 this, std::placeholders::_1);
920 EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK);
921
922 /**
923 * @tc.steps:step3. insert data into sync_data, check observer.
924 * @tc.expected: step3. check observer ok.
925 */
926 std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');";
927 std::unique_lock<std::mutex> lock(g_mutex);
928 ExecSqlAndWaitForObserver(db, sql, lock);
929 ChangeProperties properties;
930 properties.isTrackedDataChange = true;
931 int triggerCount = 1;
932 CheckTriggerTableData(1u, tableName, properties, triggerCount);
933
934 /**
935 * @tc.steps:step4. update data, check observer.
936 * @tc.expected: step4. check observer ok.
937 */
938 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
939 ExecSqlAndWaitForObserver(db, sql, lock);
940 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
941
942 /**
943 * @tc.steps:step5. update to the same data again, check observer.
944 * @tc.expected: step5. check observer ok.
945 */
946 sql = "update " + tableName + " set name = 'lisi1' where id = 2;";
947 ExecSqlAndWaitForObserver(db, sql, lock);
948 properties.isTrackedDataChange = false;
949 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
950
951 /**
952 * @tc.steps:step6. update to the same data again, set name is NULL, check observer.
953 * @tc.expected: step6. check observer ok.
954 */
955 sql = "update " + tableName + " set name = NULL where id = 2;";
956 ExecSqlAndWaitForObserver(db, sql, lock);
957 properties.isTrackedDataChange = true;
958 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
959
960 /**
961 * @tc.steps:step7. update to the same data again, set name is empty, check observer.
962 * @tc.expected: step7. check observer ok.
963 */
964 sql = "update " + tableName + " set name = '' where id = 2;";
965 ExecSqlAndWaitForObserver(db, sql, lock);
966 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
967
968 /**
969 * @tc.steps:step8. delete data, check observer.
970 * @tc.expected: step8. check observer ok.
971 */
972 sql = "delete from " + tableName + " where id = 2;";
973 ExecSqlAndWaitForObserver(db, sql, lock);
974 CheckTriggerTableData(1u, tableName, properties, ++triggerCount);
975 EXPECT_EQ(UnRegisterClientObserver(db), OK);
976 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
977 }
978
InitLogicDeleteData(sqlite3 * & db,const std::string & tableName,uint64_t num)979 void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num)
980 {
981 for (size_t i = 0; i < num; ++i) {
982 std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');";
983 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
984 }
985 std::string sql = "update " + DBConstant::RELATIONAL_PREFIX + tableName + "_log" + " SET flag = flag | 0x08";
986 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
987 }
988
CheckLogicDeleteData(sqlite3 * & db,const std::string & tableName,uint64_t expectNum)989 void CheckLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t expectNum)
990 {
991 std::string sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log"
992 " where flag&0x08=0x08 and flag&0x01=0";
993 sqlite3_stmt *stmt = nullptr;
994 EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
995 while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
996 uint64_t count = static_cast<uint64_t>(sqlite3_column_int64(stmt, 0));
997 EXPECT_EQ(count, expectNum);
998 }
999 int errCode;
1000 SQLiteUtils::ResetStatement(stmt, true, errCode);
1001 stmt = nullptr;
1002 sql = "select count(*) from " + tableName;
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 SQLiteUtils::ResetStatement(stmt, true, errCode);
1008 }
1009
1010 /**
1011 * @tc.name: DropDeleteData001
1012 * @tc.desc: Test trigger client observer in tracker table
1013 * @tc.type: FUNC
1014 * @tc.require:
1015 * @tc.author:
1016 */
1017 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DropDeleteData001, TestSize.Level0)
1018 {
1019 /**
1020 * @tc.steps:step1. prepare data.
1021 * @tc.expected: step1. return ok.
1022 */
1023 const std::string tableName = "sync_data";
1024 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1025 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1026 EXPECT_NE(db, nullptr);
1027 uint64_t num = 10;
1028 InitLogicDeleteData(db, tableName, num);
1029
1030 /**
1031 * @tc.steps:step2. db handle is nullptr
1032 * @tc.expected: step2. return INVALID_ARGS.
1033 */
1034 EXPECT_EQ(DropLogicDeletedData(nullptr, tableName, 0u), INVALID_ARGS);
1035
1036 /**
1037 * @tc.steps:step3. tableName is empty
1038 * @tc.expected: step3. return INVALID_ARGS.
1039 */
1040 EXPECT_EQ(DropLogicDeletedData(db, "", 0u), INVALID_ARGS);
1041
1042 /**
1043 * @tc.steps:step4. tableName is no exist
1044 * @tc.expected: step4. return INVALID_ARGS.
1045 */
1046 EXPECT_EQ(DropLogicDeletedData(db, tableName + "_", 0u), DB_ERROR);
1047
1048 /**
1049 * @tc.steps:step5. cursor is 0
1050 * @tc.expected: step5. return OK.
1051 */
1052 EXPECT_EQ(DropLogicDeletedData(db, tableName, 0u), OK);
1053 CheckLogicDeleteData(db, tableName, 0u);
1054
1055 /**
1056 * @tc.steps:step6. init data again, and cursor is 15
1057 * @tc.expected: step6. return OK.
1058 */
1059 uint64_t cursor = 15;
1060 InitLogicDeleteData(db, tableName, num);
1061 EXPECT_EQ(DropLogicDeletedData(db, tableName, cursor), OK);
1062 CheckLogicDeleteData(db, tableName, cursor - num);
1063 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1064 }
1065
1066 /**
1067 * @tc.name: FfrtTest001
1068 * @tc.desc: Test ffrt concurrency
1069 * @tc.type: FUNC
1070 * @tc.require:
1071 * @tc.author:
1072 */
1073 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level0)
1074 {
1075 std::map<int, int> ans;
1076 std::mutex mutex;
1077 size_t num = 1000;
1078
1079 /**
1080 * @tc.steps:step1. submit insert map task
1081 * @tc.expected: step1. return ok.
1082 */
__anon41da56cb0d02() 1083 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1084 for (size_t j = 0; j < num; j++) {
1085 ADAPTER_AUTO_LOCK(lock, mutex);
1086 for (size_t i = 0; i < num; i++) {
1087 ans.insert_or_assign(i, i);
1088 }
1089 }
1090 }, nullptr, &ans);
1091
1092 /**
1093 * @tc.steps:step2. submit erase map task
1094 * @tc.expected: step2. return ok.
1095 */
__anon41da56cb0e02() 1096 TaskHandle h2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1097 for (size_t i = 0; i < num; i++) {
1098 ADAPTER_AUTO_LOCK(lock, mutex);
1099 for (auto it = ans.begin(); it != ans.end();) {
1100 it = ans.erase(it);
1101 }
1102 }
1103 }, nullptr, &ans);
1104
1105 /**
1106 * @tc.steps:step3. submit get from map task
1107 * @tc.expected: step3. return ok.
1108 */
__anon41da56cb0f02() 1109 TaskHandle h3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1110 for (size_t i = 0; i < num; i++) {
1111 ADAPTER_AUTO_LOCK(lock, mutex);
1112 for (auto it = ans.begin(); it != ans.end(); it++) {
1113 int j = it->first;
1114 EXPECT_GE(j, 0);
1115 }
1116 }
1117 }, &ans, nullptr);
1118 ADAPTER_WAIT(h1);
1119 ADAPTER_WAIT(h2);
1120 ADAPTER_WAIT(h3);
1121 ASSERT_TRUE(ans.empty());
1122 }
1123
1124 /**
1125 * @tc.name: FfrtTest002
1126 * @tc.desc: Test ffrt concurrency
1127 * @tc.type: FUNC
1128 * @tc.require:
1129 * @tc.author:
1130 */
1131 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level0)
1132 {
1133 std::map<int, int> ans;
1134 std::mutex mutex;
1135 size_t num = 1000;
1136
1137 /**
1138 * @tc.steps:step1. subtask submit insert map task
1139 * @tc.expected: step1. return ok.
1140 */
__anon41da56cb1002() 1141 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1142 TaskHandle hh1 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1143 for (size_t j = 0; j < num; j++) {
1144 ADAPTER_AUTO_LOCK(lock, mutex);
1145 for (size_t i = 0; i < num; i++) {
1146 ans.insert_or_assign(i, i);
1147 }
1148 }
1149 }, nullptr, &ans);
1150 ADAPTER_WAIT(hh1);
1151 });
1152
1153 /**
1154 * @tc.steps:step2. subtask submit erase map task
1155 * @tc.expected: step2. return ok.
1156 */
__anon41da56cb1202() 1157 TaskHandle h2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1158 TaskHandle hh2 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1159 for (size_t i = 0; i < num; i++) {
1160 ADAPTER_AUTO_LOCK(lock, mutex);
1161 for (auto it = ans.begin(); it != ans.end();) {
1162 it = ans.erase(it);
1163 }
1164 }
1165 }, nullptr, &ans);
1166 ADAPTER_WAIT(hh2);
1167 });
1168
1169 /**
1170 * @tc.steps:step3. subtask submit get from map task
1171 * @tc.expected: step3. return ok.
1172 */
__anon41da56cb1402() 1173 TaskHandle h3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1174 TaskHandle hh3 = ConcurrentAdapter::ScheduleTaskH([this, &ans, &mutex, num]() {
1175 for (size_t i = 0; i < num; i++) {
1176 ADAPTER_AUTO_LOCK(lock, mutex);
1177 for (auto it = ans.begin(); it != ans.end(); it++) {
1178 int j = it->first;
1179 EXPECT_GE(j, 0);
1180 }
1181 }
1182 }, &ans, nullptr);
1183 ADAPTER_WAIT(hh3);
1184 });
1185 ADAPTER_WAIT(h1);
1186 ADAPTER_WAIT(h2);
1187 ADAPTER_WAIT(h3);
1188 }
1189
1190 /**
1191 * @tc.name: FfrtTest003
1192 * @tc.desc: Test ffrt concurrency
1193 * @tc.type: FUNC
1194 * @tc.require:
1195 * @tc.author:
1196 */
1197 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level0)
1198 {
1199 size_t count = 0;
1200 size_t num = 3000;
1201 std::vector<TaskHandle> waitVec;
1202
1203 /**
1204 * @tc.steps:step1. submit increase task
1205 * @tc.expected: step1. return ok.
1206 */
1207 for (size_t j = 0; j < num; j++) {
__anon41da56cb1602() 1208 TaskHandle h1 = ConcurrentAdapter::ScheduleTaskH([this, &count, num]() {
1209 for (size_t i = 0; i < num; i++) {
1210 count++;
1211 }
1212 }, nullptr, nullptr);
1213 waitVec.push_back(std::move(h1));
1214 }
1215 for (const auto &item : waitVec) {
1216 ADAPTER_WAIT(item);
1217 }
1218
1219 /**
1220 * @tc.steps:step2. check count
1221 * @tc.expected: step2. return ok.
1222 */
1223 #ifdef USE_FFRT
1224 EXPECT_NE(count, num * num);
1225 #else
1226 EXPECT_EQ(count, num * num);
1227 #endif
1228 }
1229
1230 /**
1231 * @tc.name: AbnormalDelegateTest001
1232 * @tc.desc: Test delegate interface after delegate is closed
1233 * @tc.type: FUNC
1234 * @tc.require:
1235 * @tc.author: chenchaohao
1236 */
1237 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateTest001, TestSize.Level0)
1238 {
1239 /**
1240 * @tc.steps:step1. create db and open store
1241 * @tc.expected: step1. return ok.
1242 */
1243 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1244 ASSERT_NE(db, nullptr);
1245 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1246 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1247 RelationalStoreDelegate *delegate = nullptr;
1248 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1249 EXPECT_EQ(status, OK);
1250 ASSERT_NE(delegate, nullptr);
1251
1252 /**
1253 * @tc.steps:step2. close delegate
1254 * @tc.expected: step2. return ok.
1255 */
1256 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1257 status = delegateImpl->Close();
1258 EXPECT_EQ(status, OK);
1259
1260 /**
1261 * @tc.steps:step3. test interface after delegate is closed
1262 * @tc.expected: step3. return ok.
1263 */
1264 const std::string tableName = "sync_data";
1265 EXPECT_EQ(delegateImpl->RemoveDeviceData("", tableName), DB_ERROR);
1266 EXPECT_EQ(delegate->RemoveDeviceData("", FLAG_AND_DATA), DB_ERROR);
1267 EXPECT_EQ(delegate->GetCloudSyncTaskCount(), -1); // -1 is error count
1268 EXPECT_EQ(delegate->CreateDistributedTable(tableName, CLOUD_COOPERATION), DB_ERROR);
1269 EXPECT_EQ(delegate->UnRegisterObserver(), DB_ERROR);
1270 DataBaseSchema dataBaseSchema;
1271 EXPECT_EQ(delegate->SetCloudDbSchema(dataBaseSchema), DB_ERROR);
1272 EXPECT_EQ(delegate->SetReference({}), DB_ERROR);
1273 TrackerSchema trackerSchema;
1274 EXPECT_EQ(delegate->SetTrackerTable(trackerSchema), DB_ERROR);
1275 EXPECT_EQ(delegate->CleanTrackerData(tableName, 0), DB_ERROR);
1276 bool logicDelete = true;
1277 auto data = static_cast<PragmaData>(&logicDelete);
1278 EXPECT_EQ(delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data), DB_ERROR);
1279 std::vector<VBucket> records;
1280 RecordStatus recordStatus = RecordStatus::WAIT_COMPENSATED_SYNC;
1281 EXPECT_EQ(delegate->UpsertData(tableName, records, recordStatus), DB_ERROR);
1282
1283 /**
1284 * @tc.steps:step4. close store
1285 * @tc.expected: step4. return ok.
1286 */
1287 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1288 delegate = nullptr;
1289 }
1290
InitDataStatus(const std::string & tableName,int count,sqlite3 * db)1291 void InitDataStatus(const std::string &tableName, int count, sqlite3 *db)
1292 {
1293 int type = 4; // the num of different status
1294 for (int i = 1; i <= type * count; i++) {
1295 std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" +
1296 std::to_string(i) + "');";
1297 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1298 }
1299 std::string countStr = std::to_string(count);
1300 std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status=(CASE WHEN data_key<=" +
1301 countStr + " THEN 0 WHEN data_key>" + countStr + " AND data_key<=2*" + countStr + " THEN 1 WHEN data_key>2*" +
1302 countStr + " AND data_key<=3*" + countStr + " THEN 2 ELSE 3 END)";
1303 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1304 }
1305
CheckDataStatus(const std::string & tableName,const std::string & condition,sqlite3 * db,int64_t expect)1306 void CheckDataStatus(const std::string &tableName, const std::string &condition, sqlite3 *db, int64_t expect)
1307 {
1308 std::string sql = "SELECT count(1) FROM " + DBCommon::GetLogTableName(tableName) + " WHERE " + condition;
1309 sqlite3_stmt *stmt = nullptr;
1310 EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK);
1311 while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1312 int64_t count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
1313 EXPECT_EQ(count, expect);
1314 }
1315 int errCode;
1316 SQLiteUtils::ResetStatement(stmt, true, errCode);
1317 }
1318
1319 /**
1320 * @tc.name: LockDataTest001
1321 * @tc.desc: Test status after lock
1322 * @tc.type: FUNC
1323 * @tc.require:
1324 * @tc.author: bty
1325 */
1326 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level0)
1327 {
1328 /**
1329 * @tc.steps:step1. init data and lock, hashKey has no matching data
1330 * @tc.expected: step1. return NOT_FOUND.
1331 */
1332 const std::string tableName = "sync_data";
1333 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1334 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1335 EXPECT_NE(db, nullptr);
1336 int count = 10;
1337 InitDataStatus(tableName, count, db);
1338 std::vector<std::vector<uint8_t>> hashKey;
1339 hashKey.push_back({'1'});
1340 EXPECT_EQ(Lock(tableName, hashKey, db), NOT_FOUND);
1341
1342 /**
1343 * @tc.steps:step2. init data and lock, hashKey has matching data
1344 * @tc.expected: step2. return OK.
1345 */
1346 hashKey.clear();
1347 CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey);
1348 EXPECT_EQ(Lock(tableName, hashKey, db), OK);
1349
1350 /**
1351 * @tc.steps:step3. check status
1352 * @tc.expected: step3. return OK.
1353 */
1354 CheckDataStatus(tableName, " status = 2 and data_key <= 10 ", db, count);
1355 CheckDataStatus(tableName, " status = 3 and data_key <= 20 ", db, count);
1356 CheckDataStatus(tableName, " status = 2 ", db, count + count);
1357 CheckDataStatus(tableName, " status = 3 ", db, count + count);
1358 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1359 }
1360
1361 /**
1362 * @tc.name: LockDataTest002
1363 * @tc.desc: Test status after unLock
1364 * @tc.type: FUNC
1365 * @tc.require:
1366 * @tc.author: bty
1367 */
1368 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level0)
1369 {
1370 /**
1371 * @tc.steps:step1. init data and unLock, there is data to be compensated for
1372 * @tc.expected: step1. return WAIT_COMPENSATED_SYNC.
1373 */
1374 const std::string tableName = "sync_data";
1375 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1376 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1377 EXPECT_NE(db, nullptr);
1378 int count = 10;
1379 InitDataStatus(tableName, count, db);
1380 std::vector<std::vector<uint8_t>> hashKey;
1381 CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey);
1382 EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC);
1383
1384 /**
1385 * @tc.steps:step2. check status
1386 * @tc.expected: step2. return OK.
1387 */
1388 CheckDataStatus(tableName, " status = 0 and data_key <= 10 ", db, count);
1389 CheckDataStatus(tableName, " status = 1 and data_key <= 20 ", db, count);
1390 CheckDataStatus(tableName, " status = 0 ", db, count + count);
1391 CheckDataStatus(tableName, " status = 1 ", db, count + count);
1392
1393 /**
1394 * @tc.steps:step3. unLock again, there is data to be compensated for
1395 * @tc.expected: step3. return WAIT_COMPENSATED_SYNC.
1396 */
1397 EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC);
1398
1399 /**
1400 * @tc.steps:step4. unLock again, there is no data to be compensated for
1401 * @tc.expected: step4. return OK.
1402 */
1403 std::string sql = "update " + DBCommon::GetLogTableName(tableName) + " SET status=0";
1404 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1405 EXPECT_EQ(UnLock(tableName, hashKey, db), OK);
1406
1407 /**
1408 * @tc.steps:step5. unLock again, hashKey has matching data
1409 * @tc.expected: step5. return NOT_FOUND.
1410 */
1411 hashKey.clear();
1412 hashKey.push_back({'1'});
1413 EXPECT_EQ(UnLock(tableName, hashKey, db), NOT_FOUND);
1414 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
1415 }
1416
1417 /**
1418 * @tc.name: LockDataTest003
1419 * @tc.desc: Test status after local change
1420 * @tc.type: FUNC
1421 * @tc.require:
1422 * @tc.author: bty
1423 */
1424 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest003, TestSize.Level0)
1425 {
1426 /**
1427 * @tc.steps:step1. update data and check
1428 * @tc.expected: step1. return E_OK.
1429 */
1430 const std::string tableName = "sync_data";
1431 PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false);
1432 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1433 EXPECT_NE(db, nullptr);
1434 int count = 10;
1435 InitDataStatus(tableName, count, db);
1436 std::string sql = "update " + tableName + " SET name='1' where id in (1,11,21,31)";
1437 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1438 CheckDataStatus(tableName, " status = 3 and data_key in (1,11,21,31) ", db, 2); // 2 is changed count
1439
1440 /**
1441 * @tc.steps:step1. delete data and check
1442 * @tc.expected: step1. return E_OK.
1443 */
1444 sql = "delete from " + tableName + " where id in (2,12,22,32)";
1445 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1446 CheckDataStatus(tableName, " status = 1 and data_key = -1 ", db, 3); // 3 is changed count
1447 }
1448
1449 DistributedDB::StoreObserver::StoreChangedInfo g_changedData;
1450
1451 class MockStoreObserver : public StoreObserver {
1452 public:
~MockStoreObserver()1453 virtual ~MockStoreObserver() {};
OnChange(StoreChangedInfo && data)1454 void OnChange(StoreChangedInfo &&data) override
1455 {
1456 g_changedData = data;
1457 std::unique_lock<std::mutex> lock(g_mutex);
1458 g_cv.notify_one();
1459 g_alreadyNotify = true;
1460 };
1461 };
1462
CreateTableForStoreObserver(sqlite3 * db,const std::string tableName)1463 void CreateTableForStoreObserver(sqlite3 *db, const std::string tableName)
1464 {
1465 std::string sql = "create table " + tableName + "(id INTEGER primary key, name TEXT);";
1466 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1467 sql = "create table no_" + tableName + "(id INTEGER, name TEXT);";
1468 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1469 sql = "create table mult_" + tableName + "(id INTEGER, name TEXT, age int, ";
1470 sql += "PRIMARY KEY (id, name));";
1471 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1472 }
1473
PrepareDataForStoreObserver(sqlite3 * db,const std::string & tableName,int begin,int dataCounts)1474 void PrepareDataForStoreObserver(sqlite3 *db, const std::string &tableName, int begin, int dataCounts)
1475 {
1476 std::string sql = "begin;";
1477 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1478 for (int i = begin; i < begin + dataCounts; i++) {
1479 sql = "insert into " + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan" +
1480 std::to_string(i + 1) + "');";
1481 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1482 sql = "insert into no_" + tableName +" VALUES(" + std::to_string(i + 1) + ", 'zhangsan" +
1483 std::to_string(i + 1) + "');";
1484 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1485 sql = "insert into mult_" + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan";
1486 sql += std::to_string(i + 1) + "', 18);";
1487 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1488 }
1489 for (int i = begin; i < dataCounts / 2 + begin; i++) { // 2 is half
1490 sql = "update " + tableName + " set name = 'lisi' where id = " + std::to_string(i + 1) + ";";
1491 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1492 sql = "update no_" + tableName + " set name = 'lisi' where _rowid_ = " + std::to_string(i + 1) + ";";
1493 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1494 sql = "update mult_" + tableName + " set age = 20 where id = " + std::to_string(i + 1);
1495 sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';";
1496 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1497 }
1498 for (int i = dataCounts / 2 + begin; i < dataCounts + begin; i++) { // 2 is half
1499 sql = "delete from " + tableName + " where id = " + std::to_string(i + 1) + ";";
1500 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1501 sql = "delete from no_" + tableName + " where _rowid_ = " + std::to_string(i + 1) + ";";
1502 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1503 sql = "delete from mult_" + tableName + " where id = " + std::to_string(i + 1);
1504 sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';";
1505 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1506 }
1507 sql = "commit;";
1508 EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK);
1509 }
1510
CheckChangedData(int num,int times=0,int offset=0)1511 void CheckChangedData(int num, int times = 0, int offset = 0)
1512 {
1513 if (num == 1) {
1514 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) {
1515 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]),
1516 static_cast<int64_t>(i + offset - times * 5)); // 5 is rowid times
1517 }
1518 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) {
1519 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]),
1520 static_cast<int64_t>(i + offset + 5)); // 5 is offset
1521 }
1522 return;
1523 }
1524 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) {
1525 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]),
1526 static_cast<int64_t>(i + offset));
1527 }
1528 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_UPDATE].size(); i++) {
1529 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_UPDATE][i - 1][0]),
1530 static_cast<int64_t>(i + offset));
1531 }
1532 for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) {
1533 EXPECT_EQ(std::get<int64_t>(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]),
1534 static_cast<int64_t>(i + offset + 5)); // 5 is offset
1535 }
1536 }
1537
1538 /**
1539 * @tc.name: RegisterStoreObserverTest001
1540 * @tc.desc: Test commit for three table then trigger store observer
1541 * @tc.type: FUNC
1542 * @tc.require:
1543 * @tc.author: chenchaohao
1544 */
1545 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest001, TestSize.Level1)
1546 {
1547 /**
1548 * @tc.steps:step1. prepare db and create table.
1549 * @tc.expected: step1. return ok.
1550 */
1551 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1552 EXPECT_NE(db, nullptr);
1553 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1554 std::string tableName = "primary_test";
1555 CreateTableForStoreObserver(db, tableName);
1556
1557 /**
1558 * @tc.steps:step2. register store observer and check onchange.
1559 * @tc.expected: step2. return ok.
1560 */
1561 auto storeObserver = std::make_shared<MockStoreObserver>();
1562 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1563 EXPECT_TRUE(g_changedData.empty());
1564 int dataCounts = 10; // 10 is count of insert options.
1565 int begin = 0;
1566 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1567 {
1568 std::unique_lock<std::mutex> lock(g_mutex);
__anon41da56cb1702() 1569 g_cv.wait(lock, []() {
1570 return g_alreadyNotify;
1571 });
1572 g_alreadyNotify = false;
1573 }
1574 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1575 CheckChangedData(0);
1576 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1577 CheckChangedData(1);
1578 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1579 CheckChangedData(2); // 2 is mult primary table
1580 g_changedData.clear();
1581
1582 /**
1583 * @tc.steps:step3. unregister store observer and update data check onchange.
1584 * @tc.expected: step3. return ok.
1585 */
1586 EXPECT_EQ(UnregisterStoreObserver(db), OK);
1587 begin = 10; // 10 is begin id
1588 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1589 EXPECT_TRUE(g_changedData.empty());
1590 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1591 }
1592
1593 /**
1594 * @tc.name: RegisterStoreObserverTest002
1595 * @tc.desc: Test commit for three table then trigger client observer when register then create table
1596 * @tc.type: FUNC
1597 * @tc.require:
1598 * @tc.author: chenchaohao
1599 */
1600 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest002, TestSize.Level1)
1601 {
1602 /**
1603 * @tc.steps:step1. prepare db and register store observer then create table.
1604 * @tc.expected: step1. return ok.
1605 */
1606 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1607 EXPECT_NE(db, nullptr);
1608 auto storeObserver = std::make_shared<MockStoreObserver>();
1609 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1610 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1611 std::string tableName = "primary_test";
1612 CreateTableForStoreObserver(db, tableName);
1613
1614 /**
1615 * @tc.steps:step2. update data and check onchange.
1616 * @tc.expected: step2. return ok.
1617 */
1618 EXPECT_TRUE(g_changedData.empty());
1619 int dataCounts = 10; // 10 is count of insert options.
1620 int begin = 0;
1621 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1622 WaitAndResetNotify();
1623 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1624 CheckChangedData(0);
1625 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1626 CheckChangedData(1);
1627 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1628 CheckChangedData(2); // 2 is mult primary table
1629 g_changedData.clear();
1630
1631 /**
1632 * @tc.steps:step3. unregister store observer and update data check onchange.
1633 * @tc.expected: step3. return ok.
1634 */
1635 EXPECT_EQ(UnregisterStoreObserver(db), OK);
1636 begin = 10; // 11 is begin id
1637 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1638 EXPECT_TRUE(g_changedData.empty());
1639 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1640 }
1641
1642 /**
1643 * @tc.name: RegisterStoreObserverTest003
1644 * @tc.desc: Test commit for three table then trigger client observer when register two observer
1645 * @tc.type: FUNC
1646 * @tc.require:
1647 * @tc.author: chenchaohao
1648 */
1649 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest003, TestSize.Level1)
1650 {
1651 /**
1652 * @tc.steps:step1. prepare db and register store observer then create table.
1653 * @tc.expected: step1. return ok.
1654 */
1655 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1656 EXPECT_NE(db, nullptr);
1657 auto storeObserver1 = std::make_shared<MockStoreObserver>();
1658 auto storeObserver2 = std::make_shared<MockStoreObserver>();
1659 EXPECT_EQ(RegisterStoreObserver(db, storeObserver1), OK);
1660 EXPECT_EQ(RegisterStoreObserver(db, storeObserver2), OK);
1661 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1662 std::string tableName = "primary_test";
1663 CreateTableForStoreObserver(db, tableName);
1664
1665 /**
1666 * @tc.steps:step2. update data and check onchange.
1667 * @tc.expected: step2. return ok.
1668 */
1669 EXPECT_TRUE(g_changedData.empty());
1670 int dataCounts = 10; // 10 is count of insert options.
1671 int begin = 0;
1672 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1673 WaitAndResetNotify();
1674 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1675 CheckChangedData(0);
1676 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1677 CheckChangedData(1);
1678 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1679 CheckChangedData(2); // 2 is mult primary table
1680 g_changedData.clear();
1681
1682 /**
1683 * @tc.steps:step3. unregister store observer and update data check onchange.
1684 * @tc.expected: step3. return ok.
1685 */
1686 EXPECT_EQ(UnregisterStoreObserver(db, storeObserver1), OK);
1687 begin = 10; // 11 is begin id
1688 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1689 EXPECT_EQ(g_changedData[0].tableName, "primary_test");
1690 CheckChangedData(0, 1, dataCounts);
1691 EXPECT_EQ(g_changedData[1].tableName, "no_primary_test");
1692 CheckChangedData(1, 1, dataCounts);
1693 EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table
1694 CheckChangedData(2, 1, dataCounts); // 2 is mult primary table
1695 g_changedData.clear();
1696
1697 EXPECT_EQ(UnregisterStoreObserver(db, storeObserver2), OK);
1698 begin = 20; // 21 is begin id
1699 PrepareDataForStoreObserver(db, tableName, begin, dataCounts);
1700 EXPECT_TRUE(g_changedData.empty());
1701 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1702 }
1703
1704 /**
1705 * @tc.name: RegisterStoreObserverTest004
1706 * @tc.desc: Test register two same observer
1707 * @tc.type: FUNC
1708 * @tc.require:
1709 * @tc.author: chenchaohao
1710 */
1711 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTest004, TestSize.Level1)
1712 {
1713 /**
1714 * @tc.steps:step1. prepare db and register store observer then create table.
1715 * @tc.expected: step1. return ok.
1716 */
1717 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1718 EXPECT_NE(db, nullptr);
1719 auto storeObserver = std::make_shared<MockStoreObserver>();
1720 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK);
1721 EXPECT_EQ(RegisterStoreObserver(db, storeObserver), INVALID_ARGS);
1722 }
1723
1724 /**
1725 * @tc.name: AbnormalDelegateImplTest001
1726 * @tc.desc: Test delegateImpl interface after delegate is closed
1727 * @tc.type: FUNC
1728 * @tc.require: DTS2024073106613
1729 * @tc.author: suyue
1730 */
1731 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest001, TestSize.Level0)
1732 {
1733 /**
1734 * @tc.steps:step1. create db and open store.
1735 * @tc.expected: step1. return ok.
1736 */
1737 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1738 ASSERT_NE(db, nullptr);
1739 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1740 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1741 RelationalStoreDelegate *delegate = nullptr;
1742 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1743 EXPECT_EQ(status, OK);
1744 ASSERT_NE(delegate, nullptr);
1745
1746 /**
1747 * @tc.steps:step2. close delegate.
1748 * @tc.expected: step2. return ok.
1749 */
1750 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1751 status = delegateImpl->Close();
1752 EXPECT_EQ(status, OK);
1753
1754 /**
1755 * @tc.steps:step3. test DelegateImpl interface after delegate is closed.
1756 * @tc.expected: step3. return DB_ERROR.
1757 */
1758 const RemoteCondition condition;
1759 std::shared_ptr<ResultSet> result = nullptr;
1760 DBStatus ret = delegateImpl->RemoteQuery("", condition, 0, result);
1761 EXPECT_EQ(ret, DB_ERROR);
1762 EXPECT_EQ(delegateImpl->RemoveDeviceData(), DB_ERROR);
1763
1764 StoreObserver observer;
1765 EXPECT_EQ(delegateImpl->RegisterObserver(&observer), DB_ERROR);
1766 EXPECT_EQ(delegateImpl->UnRegisterObserver(&observer), DB_ERROR);
1767 DistributedDB::SqlCondition sqlCondition;
1768 std::vector<VBucket> records = {};
1769 EXPECT_EQ(delegateImpl->ExecuteSql(sqlCondition, records), DB_ERROR);
1770 EXPECT_EQ(delegateImpl->UpsertData("", records, RecordStatus::WAIT_COMPENSATED_SYNC), DB_ERROR);
1771 const CloudSyncConfig config;
1772 EXPECT_EQ(delegateImpl->SetCloudSyncConfig(config), DB_ERROR);
1773
1774 /**
1775 * @tc.steps:step4. close store.
1776 * @tc.expected: step4. return ok.
1777 */
1778 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1779 delegate = nullptr;
1780 }
1781
1782 /**
1783 * @tc.name: AbnormalDelegateImplTest002
1784 * @tc.desc: Test delegate interface after delegate is closed
1785 * @tc.type: FUNC
1786 * @tc.require: DTS2024073106613
1787 * @tc.author: suyue
1788 */
1789 HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest002, TestSize.Level0)
1790 {
1791 /**
1792 * @tc.steps:step1. create db and open store.
1793 * @tc.expected: step1. return ok.
1794 */
1795 sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX);
1796 ASSERT_NE(db, nullptr);
1797 EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK);
1798 EXPECT_EQ(sqlite3_close_v2(db), E_OK);
1799 RelationalStoreDelegate *delegate = nullptr;
1800 DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate);
1801 EXPECT_EQ(status, OK);
1802 ASSERT_NE(delegate, nullptr);
1803
1804 /**
1805 * @tc.steps:step2. test DelegateImpl interface when para is err.
1806 * @tc.expected: step2. return INVALID_ARGS or NOT_FOUND.
1807 */
1808 auto delegateImpl = static_cast<RelationalStoreDelegateImpl *>(delegate);
1809 const CloudSyncConfig config;
1810 EXPECT_EQ(delegateImpl->SetCloudSyncConfig(config), OK);
1811 DistributedDB::SqlCondition sqlCondition;
1812 std::vector<VBucket> records = {};
1813 EXPECT_EQ(delegateImpl->ExecuteSql(sqlCondition, records), INVALID_ARGS);
1814 EXPECT_EQ(delegateImpl->UpsertData("", records, RecordStatus::WAIT_COMPENSATED_SYNC), INVALID_ARGS);
1815 EXPECT_EQ(delegateImpl->CleanTrackerData("", 0), INVALID_ARGS);
1816 TrackerSchema schema;
1817 EXPECT_EQ(delegateImpl->SetTrackerTable(schema), INVALID_ARGS);
1818 schema = {.tableName = "test", .extendColName = "", .trackerColNames = {}};
1819 EXPECT_EQ(delegateImpl->SetTrackerTable(schema), NOT_FOUND);
1820
1821 /**
1822 * @tc.steps:step3. close store.
1823 * @tc.expected: step3. return ok.
1824 */
1825 EXPECT_EQ(g_mgr.CloseStore(delegate), OK);
1826 delegate = nullptr;
1827 }
1828 }
1829