1 /*
2 * Copyright (c) 2021 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 "distributeddb_tools_unit_test.h"
17
18 #include <codecvt>
19 #include <cstdio>
20 #include <cstring>
21 #include <dirent.h>
22 #include <fstream>
23 #include <gtest/gtest.h>
24 #include <locale>
25 #include <openssl/rand.h>
26 #include <random>
27 #include <set>
28 #include <sys/types.h>
29
30 #include "cloud/cloud_db_constant.h"
31 #include "cloud/cloud_db_sync_utils_test.h"
32 #include "cloud/cloud_db_types.h"
33 #include "cloud/virtual_cloud_data_translate.h"
34 #include "db_common.h"
35 #include "db_constant.h"
36 #include "generic_single_ver_kv_entry.h"
37 #include "get_query_info.h"
38 #include "platform_specific.h"
39 #include "res_finalizer.h"
40 #include "runtime_config.h"
41 #include "single_ver_data_packet.h"
42 #include "sqlite_relational_utils.h"
43 #include "store_observer.h"
44 #include "time_helper.h"
45 #include "value_hash_calc.h"
46
47 using namespace DistributedDB;
48
49 namespace DistributedDBUnitTest {
50 namespace {
51 const std::string CREATE_LOCAL_TABLE_SQL =
52 "CREATE TABLE IF NOT EXISTS local_data(" \
53 "key BLOB PRIMARY KEY," \
54 "value BLOB," \
55 "timestamp INT," \
56 "hash_key BLOB);";
57
58 const std::string CREATE_META_TABLE_SQL =
59 "CREATE TABLE IF NOT EXISTS meta_data(" \
60 "key BLOB PRIMARY KEY NOT NULL," \
61 "value BLOB);";
62
63 const std::string CREATE_SYNC_TABLE_SQL =
64 "CREATE TABLE IF NOT EXISTS sync_data(" \
65 "key BLOB NOT NULL," \
66 "value BLOB," \
67 "timestamp INT NOT NULL," \
68 "flag INT NOT NULL," \
69 "device BLOB," \
70 "ori_device BLOB," \
71 "hash_key BLOB PRIMARY KEY NOT NULL," \
72 "w_timestamp INT);";
73
74 const std::string CREATE_SYNC_TABLE_INDEX_SQL =
75 "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key);";
76
77 const std::string CREATE_TABLE_SQL =
78 "CREATE TABLE IF NOT EXISTS version_data(key BLOB, value BLOB, oper_flag INTEGER, version INTEGER, " \
79 "timestamp INTEGER, ori_timestamp INTEGER, hash_key BLOB, " \
80 "PRIMARY key(hash_key, version));";
81
82 const std::string CREATE_SQL =
83 "CREATE TABLE IF NOT EXISTS data(key BLOB PRIMARY key, value BLOB);";
84
CompareEntry(const DistributedDB::Entry & a,const DistributedDB::Entry & b)85 bool CompareEntry(const DistributedDB::Entry &a, const DistributedDB::Entry &b)
86 {
87 return (a.key < b.key);
88 }
89 }
90
91 // OpenDbProperties.uri do not need
CreateMockSingleDb(DatabaseInfo & dbInfo,OpenDbProperties & properties)92 int DistributedDBToolsUnitTest::CreateMockSingleDb(DatabaseInfo &dbInfo, OpenDbProperties &properties)
93 {
94 std::string identifier = dbInfo.userId + "-" + dbInfo.appId + "-" + dbInfo.storeId;
95 std::string hashIdentifier = DBCommon::TransferHashString(identifier);
96 std::string identifierName = DBCommon::TransferStringToHex(hashIdentifier);
97
98 if (OS::GetRealPath(dbInfo.dir, properties.uri) != E_OK) {
99 LOGE("Failed to canonicalize the path.");
100 return -E_INVALID_ARGS;
101 }
102
103 int errCode = DBCommon::CreateStoreDirectory(dbInfo.dir, identifierName, DBConstant::SINGLE_SUB_DIR, true);
104 if (errCode != E_OK) {
105 return errCode;
106 }
107
108 properties.uri = dbInfo.dir + "/" + identifierName + "/" +
109 DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
110 if (properties.sqls.empty()) {
111 std::vector<std::string> defaultCreateTableSqls = {
112 CREATE_LOCAL_TABLE_SQL,
113 CREATE_META_TABLE_SQL,
114 CREATE_SYNC_TABLE_SQL,
115 CREATE_SYNC_TABLE_INDEX_SQL
116 };
117 properties.sqls = defaultCreateTableSqls;
118 }
119
120 sqlite3 *db = nullptr;
121 errCode = SQLiteUtils::OpenDatabase(properties, db);
122 if (errCode != E_OK) {
123 return errCode;
124 }
125 errCode = SQLiteUtils::SetUserVer(properties, dbInfo.dbUserVersion);
126 if (errCode != E_OK) {
127 return errCode;
128 }
129
130 (void)sqlite3_close_v2(db);
131 db = nullptr;
132 return errCode;
133 }
134
CreatMockMultiDb(OpenDbProperties & properties,DatabaseInfo & dbInfo)135 static int CreatMockMultiDb(OpenDbProperties &properties, DatabaseInfo &dbInfo)
136 {
137 sqlite3 *db = nullptr;
138 (void)SQLiteUtils::OpenDatabase(properties, db);
139 int errCode = SQLiteUtils::SetUserVer(properties, dbInfo.dbUserVersion);
140 (void)sqlite3_close_v2(db);
141 db = nullptr;
142 if (errCode != E_OK) {
143 return errCode;
144 }
145 return errCode;
146 }
147
OpenMockMultiDb(DatabaseInfo & dbInfo,OpenDbProperties & properties)148 int DistributedDBToolsUnitTest::OpenMockMultiDb(DatabaseInfo &dbInfo, OpenDbProperties &properties)
149 {
150 std::string identifier = dbInfo.userId + "-" + dbInfo.appId + "-" + dbInfo.storeId;
151 std::string hashIdentifier = DBCommon::TransferHashString(identifier);
152 std::string identifierName = DBCommon::TransferStringToHex(hashIdentifier);
153
154 OpenDbProperties commitProperties = properties;
155 commitProperties.uri = dbInfo.dir + "/" + identifierName + "/" + DBConstant::MULTI_SUB_DIR +
156 "/commit_logs" + DBConstant::DB_EXTENSION;
157
158 commitProperties.sqls = {CREATE_SQL};
159
160 OpenDbProperties kvStorageProperties = commitProperties;
161 kvStorageProperties.uri = dbInfo.dir + "/" + identifierName + "/" +
162 DBConstant::MULTI_SUB_DIR + "/value_storage" + DBConstant::DB_EXTENSION;
163 OpenDbProperties metaStorageProperties = commitProperties;
164 metaStorageProperties.uri = dbInfo.dir + "/" + identifierName + "/" +
165 DBConstant::MULTI_SUB_DIR + "/meta_storage" + DBConstant::DB_EXTENSION;
166
167 // test code, Don't needpay too much attention to exception handling
168 int errCode = CreatMockMultiDb(properties, dbInfo);
169 if (errCode != E_OK) {
170 return errCode;
171 }
172
173 errCode = CreatMockMultiDb(kvStorageProperties, dbInfo);
174 if (errCode != E_OK) {
175 return errCode;
176 }
177
178 errCode = CreatMockMultiDb(metaStorageProperties, dbInfo);
179 if (errCode != E_OK) {
180 return errCode;
181 }
182
183 return errCode;
184 }
185
186 // OpenDbProperties.uri do not need
CreateMockMultiDb(DatabaseInfo & dbInfo,OpenDbProperties & properties)187 int DistributedDBToolsUnitTest::CreateMockMultiDb(DatabaseInfo &dbInfo, OpenDbProperties &properties)
188 {
189 std::string identifier = dbInfo.userId + "-" + dbInfo.appId + "-" + dbInfo.storeId;
190 std::string hashIdentifier = DBCommon::TransferHashString(identifier);
191 std::string identifierName = DBCommon::TransferStringToHex(hashIdentifier);
192
193 if (OS::GetRealPath(dbInfo.dir, properties.uri) != E_OK) {
194 LOGE("Failed to canonicalize the path.");
195 return -E_INVALID_ARGS;
196 }
197
198 int errCode = DBCommon::CreateStoreDirectory(dbInfo.dir, identifierName, DBConstant::MULTI_SUB_DIR, true);
199 if (errCode != E_OK) {
200 return errCode;
201 }
202
203 properties.uri = dbInfo.dir + "/" + identifierName + "/" + DBConstant::MULTI_SUB_DIR +
204 "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION;
205
206 if (properties.sqls.empty()) {
207 properties.sqls = {CREATE_TABLE_SQL};
208 }
209
210 OpenMockMultiDb(dbInfo, properties);
211
212 return errCode;
213 }
214
GetResourceDir(std::string & dir)215 int DistributedDBToolsUnitTest::GetResourceDir(std::string& dir)
216 {
217 int errCode = GetCurrentDir(dir);
218 if (errCode != E_OK) {
219 return -E_INVALID_PATH;
220 }
221 #ifdef DB_DEBUG_ENV
222 dir = dir + "/resource/";
223 #endif
224 return E_OK;
225 }
226
GetCurrentDir(std::string & dir)227 int DistributedDBToolsUnitTest::GetCurrentDir(std::string &dir)
228 {
229 static const int maxFileLength = 1024;
230 dir = "";
231 char buffer[maxFileLength] = {0};
232 int length = readlink("/proc/self/exe", buffer, maxFileLength);
233 if (length < 0 || length >= maxFileLength) {
234 LOGE("read directory err length:%d", length);
235 return -E_LENGTH_ERROR;
236 }
237 LOGD("DIR = %s", buffer);
238 dir = buffer;
239 if (dir.rfind("/") == std::string::npos && dir.rfind("\\") == std::string::npos) {
240 LOGE("current patch format err");
241 return -E_INVALID_PATH;
242 }
243
244 if (dir.rfind("/") != std::string::npos) {
245 dir.erase(dir.rfind("/") + 1);
246 }
247 return E_OK;
248 }
249
TestDirInit(std::string & dir)250 void DistributedDBToolsUnitTest::TestDirInit(std::string &dir)
251 {
252 if (GetCurrentDir(dir) != E_OK) {
253 dir = "/";
254 }
255
256 dir.append("testDbDir");
257 DIR *dirTmp = opendir(dir.c_str());
258 if (dirTmp == nullptr) {
259 if (OS::MakeDBDirectory(dir) != 0) {
260 LOGI("MakeDirectory err!");
261 dir = "/";
262 return;
263 }
264 } else {
265 closedir(dirTmp);
266 }
267 }
268
RemoveTestDbFiles(const std::string & dir)269 int DistributedDBToolsUnitTest::RemoveTestDbFiles(const std::string &dir)
270 {
271 bool isExisted = OS::CheckPathExistence(dir);
272 if (!isExisted) {
273 return E_OK;
274 }
275
276 int nFile = 0;
277 std::string dirName;
278 struct dirent *direntPtr = nullptr;
279 DIR *dirPtr = opendir(dir.c_str());
280 if (dirPtr == nullptr) {
281 LOGE("opendir error!");
282 return -E_INVALID_PATH;
283 }
284 while (true) {
285 direntPtr = readdir(dirPtr);
286 // condition to exit the loop
287 if (direntPtr == nullptr) {
288 break;
289 }
290 // only remove all *.db files
291 std::string str(direntPtr->d_name);
292 if (str == "." || str == "..") {
293 continue;
294 }
295 dirName.clear();
296 dirName.append(dir).append("/").append(str);
297 if (direntPtr->d_type == DT_DIR) {
298 RemoveTestDbFiles(dirName);
299 rmdir(dirName.c_str());
300 } else if (remove(dirName.c_str()) != 0) {
301 LOGI("remove file: %s failed!", dirName.c_str());
302 continue;
303 }
304 nFile++;
305 }
306 closedir(dirPtr);
307 LOGI("Total %d test db files are removed!", nFile);
308 return 0;
309 }
310
311 #ifndef OMIT_MULTI_VER
KvStoreDelegateCallback(DBStatus statusSrc,KvStoreDelegate * kvStoreSrc,DBStatus & statusDst,KvStoreDelegate * & kvStoreDst)312 void DistributedDBToolsUnitTest::KvStoreDelegateCallback(
313 DBStatus statusSrc, KvStoreDelegate *kvStoreSrc, DBStatus &statusDst, KvStoreDelegate *&kvStoreDst)
314 {
315 statusDst = statusSrc;
316 kvStoreDst = kvStoreSrc;
317 }
318
SnapshotDelegateCallback(DBStatus statusSrc,KvStoreSnapshotDelegate * snapshot,DBStatus & statusDst,KvStoreSnapshotDelegate * & snapshotDst)319 void DistributedDBToolsUnitTest::SnapshotDelegateCallback(
320 DBStatus statusSrc, KvStoreSnapshotDelegate* snapshot, DBStatus &statusDst, KvStoreSnapshotDelegate *&snapshotDst)
321 {
322 statusDst = statusSrc;
323 snapshotDst = snapshot;
324 }
325 #endif
326
KvStoreNbDelegateCallback(DBStatus statusSrc,KvStoreNbDelegate * kvStoreSrc,DBStatus & statusDst,KvStoreNbDelegate * & kvStoreDst)327 void DistributedDBToolsUnitTest::KvStoreNbDelegateCallback(
328 DBStatus statusSrc, KvStoreNbDelegate* kvStoreSrc, DBStatus &statusDst, KvStoreNbDelegate *&kvStoreDst)
329 {
330 statusDst = statusSrc;
331 kvStoreDst = kvStoreSrc;
332 }
333
ValueCallback(DBStatus statusSrc,const Value & valueSrc,DBStatus & statusDst,Value & valueDst)334 void DistributedDBToolsUnitTest::ValueCallback(
335 DBStatus statusSrc, const Value &valueSrc, DBStatus &statusDst, Value &valueDst)
336 {
337 statusDst = statusSrc;
338 valueDst = valueSrc;
339 }
340
EntryVectorCallback(DBStatus statusSrc,const std::vector<Entry> & entrySrc,DBStatus & statusDst,unsigned long & matchSize,std::vector<Entry> & entryDst)341 void DistributedDBToolsUnitTest::EntryVectorCallback(DBStatus statusSrc, const std::vector<Entry> &entrySrc,
342 DBStatus &statusDst, unsigned long &matchSize, std::vector<Entry> &entryDst)
343 {
344 statusDst = statusSrc;
345 matchSize = static_cast<unsigned long>(entrySrc.size());
346 entryDst = entrySrc;
347 }
348
349 // size need bigger than prefixkey length
GetRandPrefixKey(const std::vector<uint8_t> & prefixKey,uint32_t size)350 std::vector<uint8_t> DistributedDBToolsUnitTest::GetRandPrefixKey(const std::vector<uint8_t> &prefixKey, uint32_t size)
351 {
352 std::vector<uint8_t> value;
353 if (size <= prefixKey.size()) {
354 return value;
355 }
356 DistributedDBToolsUnitTest::GetRandomKeyValue(value, size - prefixKey.size());
357 std::vector<uint8_t> res(prefixKey);
358 res.insert(res.end(), value.begin(), value.end());
359 return res;
360 }
361
GetRandomKeyValue(std::vector<uint8_t> & value,uint32_t defaultSize)362 void DistributedDBToolsUnitTest::GetRandomKeyValue(std::vector<uint8_t> &value, uint32_t defaultSize)
363 {
364 uint32_t randSize = 0;
365 if (defaultSize == 0) {
366 uint8_t simSize = 0;
367 RAND_bytes(&simSize, 1);
368 randSize = (simSize == 0) ? 1 : simSize;
369 } else {
370 randSize = defaultSize;
371 }
372
373 value.resize(randSize);
374 RAND_bytes(value.data(), randSize);
375 }
376
IsValueEqual(const DistributedDB::Value & read,const DistributedDB::Value & origin)377 bool DistributedDBToolsUnitTest::IsValueEqual(const DistributedDB::Value &read, const DistributedDB::Value &origin)
378 {
379 if (read != origin) {
380 DBCommon::PrintHexVector(read, __LINE__, "read");
381 DBCommon::PrintHexVector(origin, __LINE__, "origin");
382 return false;
383 }
384
385 return true;
386 }
387
IsEntryEqual(const DistributedDB::Entry & entryOrg,const DistributedDB::Entry & entryRet)388 bool DistributedDBToolsUnitTest::IsEntryEqual(const DistributedDB::Entry &entryOrg,
389 const DistributedDB::Entry &entryRet)
390 {
391 if (entryOrg.key != entryRet.key) {
392 LOGD("key not equal, entryOrg key size is [%zu], entryRet key size is [%zu]", entryOrg.key.size(),
393 entryRet.key.size());
394 return false;
395 }
396
397 if (entryOrg.value != entryRet.value) {
398 LOGD("value not equal, entryOrg value size is [%zu], entryRet value size is [%zu]", entryOrg.value.size(),
399 entryRet.value.size());
400 return false;
401 }
402
403 return true;
404 }
405
IsEntriesEqual(const std::vector<DistributedDB::Entry> & entriesOrg,const std::vector<DistributedDB::Entry> & entriesRet,bool needSort)406 bool DistributedDBToolsUnitTest::IsEntriesEqual(const std::vector<DistributedDB::Entry> &entriesOrg,
407 const std::vector<DistributedDB::Entry> &entriesRet, bool needSort)
408 {
409 LOGD("entriesOrg size is [%zu], entriesRet size is [%zu]", entriesOrg.size(),
410 entriesRet.size());
411
412 if (entriesOrg.size() != entriesRet.size()) {
413 return false;
414 }
415 std::vector<DistributedDB::Entry> entries1 = entriesOrg;
416 std::vector<DistributedDB::Entry> entries2 = entriesRet;
417
418 if (needSort) {
419 sort(entries1.begin(), entries1.end(), CompareEntry);
420 sort(entries2.begin(), entries2.end(), CompareEntry);
421 }
422
423 for (size_t i = 0; i < entries1.size(); i++) {
424 if (entries1[i].key != entries2[i].key) {
425 LOGE("IsEntriesEqual failed, key of index[%zu] not match", i);
426 return false;
427 }
428 if (entries1[i].value != entries2[i].value) {
429 LOGE("IsEntriesEqual failed, value of index[%zu] not match", i);
430 return false;
431 }
432 }
433
434 return true;
435 }
436
CheckObserverResult(const std::vector<DistributedDB::Entry> & orgEntries,const std::list<DistributedDB::Entry> & resultLst)437 bool DistributedDBToolsUnitTest::CheckObserverResult(const std::vector<DistributedDB::Entry> &orgEntries,
438 const std::list<DistributedDB::Entry> &resultLst)
439 {
440 LOGD("orgEntries.size() is [%zu], resultLst.size() is [%zu]", orgEntries.size(),
441 resultLst.size());
442
443 if (orgEntries.size() != resultLst.size()) {
444 return false;
445 }
446
447 int index = 0;
448 for (const auto &entry : resultLst) {
449 if (entry.key != orgEntries[index].key) {
450 LOGE("CheckObserverResult failed, key of index[%d] not match", index);
451 return false;
452 }
453 if (entry.value != orgEntries[index].value) {
454 LOGE("CheckObserverResult failed, value of index[%d] not match", index);
455 return false;
456 }
457 index++;
458 }
459
460 return true;
461 }
462
IsEntryExist(const DistributedDB::Entry & entry,const std::vector<DistributedDB::Entry> & entries)463 bool DistributedDBToolsUnitTest::IsEntryExist(const DistributedDB::Entry &entry,
464 const std::vector<DistributedDB::Entry> &entries)
465 {
466 std::set<std::vector<uint8_t>> sets;
467 for (const auto &iter : entries) {
468 sets.insert(iter.key);
469 }
470
471 if (entries.size() != sets.size()) {
472 return false;
473 }
474 sets.clear();
475 bool isFound = false;
476 for (const auto &iter : entries) {
477 if (entry.key == iter.key) {
478 if (entry.value == iter.value) {
479 isFound = true;
480 }
481 break;
482 }
483 }
484 return isFound;
485 }
486
IsItemValueExist(const DistributedDB::DataItem & item,const std::vector<DistributedDB::DataItem> & items)487 bool DistributedDBToolsUnitTest::IsItemValueExist(const DistributedDB::DataItem &item,
488 const std::vector<DistributedDB::DataItem> &items)
489 {
490 std::set<Key> sets;
491 for (const auto &iter : items) {
492 sets.insert(iter.key);
493 }
494
495 if (items.size() != sets.size()) {
496 return false;
497 }
498 sets.clear();
499 bool isFound = false;
500 for (const auto &iter : items) {
501 if (item.key == iter.key) {
502 if (item.value == iter.value) {
503 isFound = true;
504 }
505 break;
506 }
507 }
508 return isFound;
509 }
510
IsKvEntryExist(const DistributedDB::Entry & entry,const std::vector<DistributedDB::Entry> & entries)511 bool DistributedDBToolsUnitTest::IsKvEntryExist(const DistributedDB::Entry &entry,
512 const std::vector<DistributedDB::Entry> &entries)
513 {
514 std::set<std::vector<uint8_t>> sets;
515 for (const auto &iter : entries) {
516 sets.insert(iter.key);
517 }
518
519 if (entries.size() != sets.size()) {
520 return false;
521 }
522 sets.clear();
523 bool isFound = false;
524 for (const auto &iter : entries) {
525 if (entry.key == iter.key) {
526 if (entry.value == iter.value) {
527 isFound = true;
528 }
529 break;
530 }
531 }
532
533 return isFound;
534 }
535
ModifyDatabaseFile(const std::string & fileDir,uint64_t modifyPos,uint32_t modifyCnt,uint32_t value)536 int DistributedDBToolsUnitTest::ModifyDatabaseFile(const std::string &fileDir, uint64_t modifyPos,
537 uint32_t modifyCnt, uint32_t value)
538 {
539 LOGI("Modify database file:%s", fileDir.c_str());
540 std::fstream dataFile(fileDir, std::fstream::binary | std::fstream::out | std::fstream::in);
541 if (!dataFile.is_open()) {
542 LOGD("Open the database file failed");
543 return -E_UNEXPECTED_DATA;
544 }
545
546 if (!dataFile.seekg(0, std::fstream::end)) {
547 return -E_UNEXPECTED_DATA;
548 }
549
550 uint64_t fileSize;
551 std::ios::pos_type pos = dataFile.tellg();
552 if (pos < 0) {
553 return -E_UNEXPECTED_DATA;
554 } else {
555 fileSize = static_cast<uint64_t>(pos);
556 if (fileSize < 1024) { // the least page size is 1024 bytes.
557 LOGE("Invalid database file:%" PRIu64 ".", fileSize);
558 return -E_UNEXPECTED_DATA;
559 }
560 }
561
562 if (fileSize <= modifyPos) {
563 return E_OK;
564 }
565
566 if (!dataFile.seekp(modifyPos)) {
567 return -E_UNEXPECTED_DATA;
568 }
569 for (uint32_t i = 0; i < modifyCnt; i++) {
570 if (!dataFile.write(reinterpret_cast<char *>(&value), sizeof(uint32_t))) {
571 return -E_UNEXPECTED_DATA;
572 }
573 }
574
575 dataFile.flush();
576 return E_OK;
577 }
578
GetSyncDataTest(const SyncInputArg & syncInputArg,SQLiteSingleVerNaturalStore * store,std::vector<DataItem> & dataItems,ContinueToken & continueStmtToken)579 int DistributedDBToolsUnitTest::GetSyncDataTest(const SyncInputArg &syncInputArg, SQLiteSingleVerNaturalStore *store,
580 std::vector<DataItem> &dataItems, ContinueToken &continueStmtToken)
581 {
582 std::vector<SingleVerKvEntry *> entries;
583 DataSizeSpecInfo syncDataSizeInfo = {syncInputArg.blockSize_, DBConstant::MAX_HPMODE_PACK_ITEM_SIZE};
584 int errCode = store->GetSyncData(syncInputArg.begin_, syncInputArg.end_, entries,
585 continueStmtToken, syncDataSizeInfo);
586
587 ConvertSingleVerEntryToItems(entries, dataItems);
588 return errCode;
589 }
590
GetSyncDataNextTest(SQLiteSingleVerNaturalStore * store,uint32_t blockSize,std::vector<DataItem> & dataItems,ContinueToken & continueStmtToken)591 int DistributedDBToolsUnitTest::GetSyncDataNextTest(SQLiteSingleVerNaturalStore *store, uint32_t blockSize,
592 std::vector<DataItem> &dataItems, ContinueToken &continueStmtToken)
593 {
594 std::vector<SingleVerKvEntry *> entries;
595 DataSizeSpecInfo syncDataSizeInfo = {blockSize, DBConstant::MAX_HPMODE_PACK_ITEM_SIZE};
596 int errCode = store->GetSyncDataNext(entries, continueStmtToken, syncDataSizeInfo);
597
598 ConvertSingleVerEntryToItems(entries, dataItems);
599 return errCode;
600 }
601
PutSyncDataTest(SQLiteSingleVerNaturalStore * store,const std::vector<DataItem> & dataItems,const std::string & deviceName)602 int DistributedDBToolsUnitTest::PutSyncDataTest(SQLiteSingleVerNaturalStore *store,
603 const std::vector<DataItem> &dataItems, const std::string &deviceName)
604 {
605 QueryObject query(Query::Select());
606 return PutSyncDataTest(store, dataItems, deviceName, query);
607 }
608
PutSyncDataTest(SQLiteSingleVerNaturalStore * store,const std::vector<DataItem> & dataItems,const std::string & deviceName,const QueryObject & query)609 int DistributedDBToolsUnitTest::PutSyncDataTest(SQLiteSingleVerNaturalStore *store,
610 const std::vector<DataItem> &dataItems, const std::string &deviceName, const QueryObject &query)
611 {
612 std::vector<SingleVerKvEntry *> entries;
613 std::vector<DistributedDB::DataItem> items = dataItems;
614 for (auto &item : items) {
615 auto *entry = new (std::nothrow) GenericSingleVerKvEntry();
616 if (entry == nullptr) {
617 ReleaseSingleVerEntry(entries);
618 return -E_OUT_OF_MEMORY;
619 }
620 entry->SetEntryData(std::move(item));
621 entry->SetWriteTimestamp(entry->GetTimestamp());
622 entries.push_back(entry);
623 }
624
625 int errCode = store->PutSyncDataWithQuery(query, entries, deviceName);
626 ReleaseSingleVerEntry(entries);
627 return errCode;
628 }
629
ConvertItemsToSingleVerEntry(const std::vector<DistributedDB::DataItem> & dataItems,std::vector<DistributedDB::SingleVerKvEntry * > & entries)630 int DistributedDBToolsUnitTest::ConvertItemsToSingleVerEntry(const std::vector<DistributedDB::DataItem> &dataItems,
631 std::vector<DistributedDB::SingleVerKvEntry *> &entries)
632 {
633 std::vector<DistributedDB::DataItem> items = dataItems;
634 for (auto &item : items) {
635 GenericSingleVerKvEntry *entry = new (std::nothrow) GenericSingleVerKvEntry();
636 if (entry == nullptr) {
637 ReleaseSingleVerEntry(entries);
638 return -E_OUT_OF_MEMORY;
639 }
640 entry->SetEntryData(std::move(item));
641 entries.push_back(entry);
642 }
643 return E_OK;
644 }
645
ConvertSingleVerEntryToItems(std::vector<DistributedDB::SingleVerKvEntry * > & entries,std::vector<DistributedDB::DataItem> & dataItems)646 void DistributedDBToolsUnitTest::ConvertSingleVerEntryToItems(std::vector<DistributedDB::SingleVerKvEntry *> &entries,
647 std::vector<DistributedDB::DataItem> &dataItems)
648 {
649 for (auto &itemEntry : entries) {
650 GenericSingleVerKvEntry *entry = reinterpret_cast<GenericSingleVerKvEntry *>(itemEntry);
651 if (entry != nullptr) {
652 DataItem item;
653 item.origDev = entry->GetOrigDevice();
654 item.flag = entry->GetFlag();
655 item.timestamp = entry->GetTimestamp();
656 entry->GetKey(item.key);
657 entry->GetValue(item.value);
658 dataItems.push_back(item);
659 // clear vector entry
660 delete itemEntry;
661 itemEntry = nullptr;
662 }
663 }
664 entries.clear();
665 }
666
ReleaseSingleVerEntry(std::vector<DistributedDB::SingleVerKvEntry * > & entries)667 void DistributedDBToolsUnitTest::ReleaseSingleVerEntry(std::vector<DistributedDB::SingleVerKvEntry *> &entries)
668 {
669 for (auto &item : entries) {
670 delete item;
671 item = nullptr;
672 }
673 entries.clear();
674 }
675
CalcHash(const std::vector<uint8_t> & value,std::vector<uint8_t> & hashValue)676 void DistributedDBToolsUnitTest::CalcHash(const std::vector<uint8_t> &value, std::vector<uint8_t> &hashValue)
677 {
678 ValueHashCalc hashCalc;
679 hashCalc.Initialize();
680 hashCalc.Update(value);
681 hashCalc.GetResult(hashValue);
682 }
683
Dump()684 void DistributedDBToolsUnitTest::Dump()
685 {
686 constexpr const char *rightDumpParam = "--database";
687 constexpr const char *ignoreDumpParam = "ignore-param";
688 const std::u16string u16DumpRightParam =
689 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(rightDumpParam);
690 const std::u16string u16DumpIgnoreParam =
691 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> {}.from_bytes(ignoreDumpParam);
692 std::vector<std::u16string> params = {
693 u16DumpRightParam,
694 u16DumpIgnoreParam
695 };
696 // print to std::cout
697 RuntimeConfig::Dump(0, params);
698 }
699
GetKvNbStoreDirectory(const std::string & identifier,const std::string & dbFilePath,const std::string & dbDir)700 std::string DistributedDBToolsUnitTest::GetKvNbStoreDirectory(const std::string &identifier,
701 const std::string &dbFilePath, const std::string &dbDir)
702 {
703 std::string identifierName = DBCommon::TransferStringToHex(identifier);
704 return dbDir + "/" + identifierName + "/" + dbFilePath;
705 }
706
BlockSync(RelationalStoreDelegate & delegate,const Query & query,DistributedDB::SyncMode syncMode,DistributedDB::DBStatus exceptStatus,const std::vector<std::string> & devices)707 void DistributedDBToolsUnitTest::BlockSync(RelationalStoreDelegate &delegate, const Query &query,
708 DistributedDB::SyncMode syncMode, DistributedDB::DBStatus exceptStatus,
709 const std::vector<std::string> &devices)
710 {
711 std::map<std::string, std::vector<TableStatus>> statusMap;
712 SyncStatusCallback callBack = [&statusMap](
713 const std::map<std::string, std::vector<TableStatus>> &devicesMap) {
714 statusMap = devicesMap;
715 };
716 DBStatus callStatus = delegate.Sync(devices, syncMode, query, callBack, true);
717 EXPECT_EQ(callStatus, OK);
718 QueryExpression queryExpression = GetQueryInfo::GetQueryExpression(query);
719 std::vector<std::string> syncTables;
720 if (queryExpression.IsUseFromTables()) {
721 syncTables = queryExpression.GetTables();
722 } else {
723 syncTables = {queryExpression.GetTableName()};
724 }
725 for (const auto &tablesRes : statusMap) {
726 ASSERT_EQ(tablesRes.second.size(), syncTables.size());
727 for (uint32_t i = 0; i < syncTables.size(); i++) {
728 EXPECT_EQ(tablesRes.second[i].status, exceptStatus);
729 EXPECT_EQ(tablesRes.second[i].tableName, syncTables[i]);
730 }
731 }
732 }
733
KvStoreObserverUnitTest()734 KvStoreObserverUnitTest::KvStoreObserverUnitTest() : callCount_(0), isCleared_(false)
735 {}
736
OnChange(const KvStoreChangedData & data)737 void KvStoreObserverUnitTest::OnChange(const KvStoreChangedData& data)
738 {
739 callCount_++;
740 inserted_ = data.GetEntriesInserted();
741 updated_ = data.GetEntriesUpdated();
742 deleted_ = data.GetEntriesDeleted();
743 isCleared_ = data.IsCleared();
744 LOGD("Onchangedata :%zu -- %zu -- %zu -- %d", inserted_.size(), updated_.size(), deleted_.size(), isCleared_);
745 LOGD("Onchange() called success!");
746 }
747
OnChange(const DistributedDB::StoreChangedData & data)748 void KvStoreObserverUnitTest::OnChange(const DistributedDB::StoreChangedData &data)
749 {
750 (void)data;
751 KvStoreObserver::OnChange(data);
752 }
753
OnChange(DistributedDB::StoreObserver::StoreChangedInfo && data)754 void KvStoreObserverUnitTest::OnChange(DistributedDB::StoreObserver::StoreChangedInfo &&data)
755 {
756 (void)data;
757 KvStoreObserver::OnChange(std::move(data));
758 }
759
OnChange(DistributedDB::Origin origin,const std::string & originalId,DistributedDB::ChangedData && data)760 void KvStoreObserverUnitTest::OnChange(DistributedDB::Origin origin, const std::string &originalId,
761 DistributedDB::ChangedData &&data)
762 {
763 (void)origin;
764 (void)originalId;
765 (void)data;
766 KvStoreObserver::OnChange(origin, originalId, std::move(data));
767 }
768
ResetToZero()769 void KvStoreObserverUnitTest::ResetToZero()
770 {
771 callCount_ = 0;
772 isCleared_ = false;
773 inserted_.clear();
774 updated_.clear();
775 deleted_.clear();
776 }
777
GetCallCount() const778 unsigned long KvStoreObserverUnitTest::GetCallCount() const
779 {
780 return callCount_;
781 }
782
GetEntriesInserted() const783 const std::list<Entry> &KvStoreObserverUnitTest::GetEntriesInserted() const
784 {
785 return inserted_;
786 }
787
GetEntriesUpdated() const788 const std::list<Entry> &KvStoreObserverUnitTest::GetEntriesUpdated() const
789 {
790 return updated_;
791 }
792
GetEntriesDeleted() const793 const std::list<Entry> &KvStoreObserverUnitTest::GetEntriesDeleted() const
794 {
795 return deleted_;
796 }
797
IsCleared() const798 bool KvStoreObserverUnitTest::IsCleared() const
799 {
800 return isCleared_;
801 }
802
RelationalStoreObserverUnitTest()803 RelationalStoreObserverUnitTest::RelationalStoreObserverUnitTest() : callCount_(0)
804 {
805 }
806
GetCallCount() const807 unsigned long RelationalStoreObserverUnitTest::GetCallCount() const
808 {
809 return callCount_;
810 }
811
GetCloudCallCount() const812 unsigned long RelationalStoreObserverUnitTest::GetCloudCallCount() const
813 {
814 return cloudCallCount_;
815 }
816
OnChange(const StoreChangedData & data)817 void RelationalStoreObserverUnitTest::OnChange(const StoreChangedData &data)
818 {
819 callCount_++;
820 changeDevice_ = data.GetDataChangeDevice();
821 data.GetStoreProperty(storeProperty_);
822 LOGD("Onchangedata : %s", changeDevice_.c_str());
823 LOGD("Onchange() called success!");
824 }
825
OnChange(DistributedDB::Origin origin,const std::string & originalId,DistributedDB::ChangedData && data)826 void RelationalStoreObserverUnitTest::OnChange(
827 DistributedDB::Origin origin, const std::string &originalId, DistributedDB::ChangedData &&data)
828 {
829 cloudCallCount_++;
830 savedChangedData_[data.tableName] = data;
831 lastOrigin_ = origin;
832 LOGD("cloud sync Onchangedata, tableName = %s", data.tableName.c_str());
833 }
834
GetCallbackDetailsType() const835 uint32_t RelationalStoreObserverUnitTest::GetCallbackDetailsType() const
836 {
837 return detailsType_;
838 }
839
SetCallbackDetailsType(uint32_t type)840 void RelationalStoreObserverUnitTest::SetCallbackDetailsType(uint32_t type)
841 {
842 detailsType_ = type;
843 }
844
SetExpectedResult(const DistributedDB::ChangedData & changedData)845 void RelationalStoreObserverUnitTest::SetExpectedResult(const DistributedDB::ChangedData &changedData)
846 {
847 expectedChangedData_[changedData.tableName] = changedData;
848 }
849
IsPrimaryKeyEq(DistributedDB::Type & input,DistributedDB::Type & expected)850 static bool IsPrimaryKeyEq(DistributedDB::Type &input, DistributedDB::Type &expected)
851 {
852 if (input.index() != expected.index()) {
853 return false;
854 }
855 switch (expected.index()) {
856 case TYPE_INDEX<int64_t>:
857 if (std::get<int64_t>(input) != std::get<int64_t>(expected)) {
858 return false;
859 }
860 break;
861 case TYPE_INDEX<std::string>:
862 if (std::get<std::string>(input) != std::get<std::string>(expected)) {
863 return false;
864 }
865 break;
866 case TYPE_INDEX<bool>:
867 if (std::get<bool>(input) != std::get<bool>(expected)) {
868 return false;
869 }
870 break;
871 case TYPE_INDEX<double>:
872 case TYPE_INDEX<Bytes>:
873 case TYPE_INDEX<Asset>:
874 case TYPE_INDEX<Assets>:
875 LOGE("NOT HANDLE THIS SITUATION");
876 return false;
877 default: {
878 break;
879 }
880 }
881 return true;
882 }
883
IsPrimaryDataEq(uint64_t type,DistributedDB::ChangedData & input,DistributedDB::ChangedData & expected)884 static bool IsPrimaryDataEq(
885 uint64_t type, DistributedDB::ChangedData &input, DistributedDB::ChangedData &expected)
886 {
887 for (size_t m = 0; m < input.primaryData[type].size(); m++) {
888 if (m >= expected.primaryData[type].size()) {
889 LOGE("Actual primary data's size is more than the expected!");
890 return false;
891 }
892 if (input.primaryData[type][m].size() != expected.primaryData[type][m].size()) {
893 LOGE("Primary data fields' size is not equal!");
894 return false;
895 }
896 for (size_t k = 0; k < input.primaryData[type][m].size(); k++) {
897 if (!IsPrimaryKeyEq(input.primaryData[type][m][k], expected.primaryData[type][m][k])) {
898 return false;
899 }
900 }
901 }
902 return true;
903 }
904
IsAllTypePrimaryDataEq(DistributedDB::ChangedData & input,DistributedDB::ChangedData & expected)905 static bool IsAllTypePrimaryDataEq(DistributedDB::ChangedData &input, DistributedDB::ChangedData &expected)
906 {
907 for (uint64_t type = ChangeType::OP_INSERT; type < ChangeType::OP_BUTT; ++type) {
908 if (!IsPrimaryDataEq(type, input, expected)) {
909 return false;
910 }
911 }
912 return true;
913 }
914
isChangedDataEq(DistributedDB::ChangedData & input,DistributedDB::ChangedData & expected)915 static bool isChangedDataEq(DistributedDB::ChangedData &input, DistributedDB::ChangedData &expected)
916 {
917 if (input.tableName != expected.tableName) {
918 return false;
919 }
920 if (input.properties.isTrackedDataChange != expected.properties.isTrackedDataChange) {
921 return false;
922 }
923 if (input.field.size() != expected.field.size()) {
924 return false;
925 }
926 for (size_t i = 0; i < input.field.size(); i++) {
927 if (!DBCommon::CaseInsensitiveCompare(input.field[i], expected.field[i])) {
928 return false;
929 }
930 }
931 return IsAllTypePrimaryDataEq(input, expected);
932 }
933
IsAllChangedDataEq()934 bool RelationalStoreObserverUnitTest::IsAllChangedDataEq()
935 {
936 for (auto iter = expectedChangedData_.begin(); iter != expectedChangedData_.end(); ++iter) {
937 auto iterInSavedChangedData = savedChangedData_.find(iter->first);
938 if (iterInSavedChangedData == savedChangedData_.end()) {
939 return false;
940 }
941 if (!isChangedDataEq(iterInSavedChangedData->second, iter->second)) {
942 return false;
943 }
944 }
945 return true;
946 }
947
ClearChangedData()948 void RelationalStoreObserverUnitTest::ClearChangedData()
949 {
950 expectedChangedData_.clear();
951 savedChangedData_.clear();
952 }
953
ResetToZero()954 void RelationalStoreObserverUnitTest::ResetToZero()
955 {
956 callCount_ = 0;
957 changeDevice_.clear();
958 storeProperty_ = {};
959 }
960
ResetCloudSyncToZero()961 void RelationalStoreObserverUnitTest::ResetCloudSyncToZero()
962 {
963 cloudCallCount_ = 0u;
964 savedChangedData_.clear();
965 }
966
GetDataChangeDevice() const967 const std::string RelationalStoreObserverUnitTest::GetDataChangeDevice() const
968 {
969 return changeDevice_;
970 }
971
GetStoreProperty() const972 DistributedDB::StoreProperty RelationalStoreObserverUnitTest::GetStoreProperty() const
973 {
974 return storeProperty_;
975 }
976
GetSavedChangedData() const977 std::unordered_map<std::string, DistributedDB::ChangedData> RelationalStoreObserverUnitTest::GetSavedChangedData() const
978 {
979 return savedChangedData_;
980 }
981
SyncTest(KvStoreNbDelegate * delegate,const std::vector<std::string> & devices,SyncMode mode,std::map<std::string,DBStatus> & statuses,const Query & query)982 DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate,
983 const std::vector<std::string>& devices, SyncMode mode,
984 std::map<std::string, DBStatus>& statuses, const Query &query)
985 {
986 statuses.clear();
987 DBStatus callStatus = delegate->Sync(devices, mode,
988 [&statuses, this](const std::map<std::string, DBStatus>& statusMap) {
989 statuses = statusMap;
990 std::unique_lock<std::mutex> innerlock(this->syncLock_);
991 this->syncCondVar_.notify_one();
992 }, query, false);
993
994 std::unique_lock<std::mutex> lock(syncLock_);
995 syncCondVar_.wait(lock, [callStatus, &statuses]() {
996 if (callStatus != OK) {
997 return true;
998 }
999 return !statuses.empty();
1000 });
1001 return callStatus;
1002 }
1003
SyncTest(KvStoreNbDelegate * delegate,const std::vector<std::string> & devices,SyncMode mode,std::map<std::string,DBStatus> & statuses,bool wait)1004 DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate,
1005 const std::vector<std::string>& devices, SyncMode mode,
1006 std::map<std::string, DBStatus>& statuses, bool wait)
1007 {
1008 statuses.clear();
1009 DBStatus callStatus = delegate->Sync(devices, mode,
1010 [&statuses, this](const std::map<std::string, DBStatus>& statusMap) {
1011 statuses = statusMap;
1012 std::unique_lock<std::mutex> innerlock(this->syncLock_);
1013 this->syncCondVar_.notify_one();
1014 }, wait);
1015 if (!wait) {
1016 std::unique_lock<std::mutex> lock(syncLock_);
1017 syncCondVar_.wait(lock, [callStatus, &statuses]() {
1018 if (callStatus != OK) {
1019 return true;
1020 }
1021 if (statuses.size() != 0) {
1022 return true;
1023 }
1024 return false;
1025 });
1026 }
1027 return callStatus;
1028 }
1029
WaitUntilReady(DBStatus status,const std::map<std::string,DeviceSyncProcess> & syncProcessMap)1030 static bool WaitUntilReady(DBStatus status, const std::map<std::string, DeviceSyncProcess> &syncProcessMap)
1031 {
1032 if (status != OK) {
1033 return true;
1034 }
1035 if (syncProcessMap.empty()) {
1036 return false;
1037 }
1038 auto item = std::find_if(syncProcessMap.begin(), syncProcessMap.end(), [](const auto &entry) {
1039 return entry.second.process < ProcessStatus::FINISHED;
1040 });
1041 if (item != syncProcessMap.end()) {
1042 return false;
1043 }
1044 return true;
1045 }
1046
SyncTest(KvStoreNbDelegate * delegate,DeviceSyncOption option,std::map<std::string,DeviceSyncProcess> & syncProcessMap)1047 DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate *delegate, DeviceSyncOption option,
1048 std::map<std::string, DeviceSyncProcess> &syncProcessMap)
1049 {
1050 syncProcessMap.clear();
1051 DeviceSyncProcessCallback onProcess =
1052 [&syncProcessMap, this](const std::map<std::string, DeviceSyncProcess> &processMap) {
1053 syncProcessMap = processMap;
1054 std::unique_lock<std::mutex> innerlock(this->syncLock_);
1055 this->syncCondVar_.notify_one();
1056 };
1057 DBStatus status = delegate->Sync(option, onProcess);
1058
1059 if (!option.isWait) {
1060 std::unique_lock<std::mutex> lock(this->syncLock_);
1061 this->syncCondVar_.wait(lock, [status, &syncProcessMap]() {
1062 return WaitUntilReady(status, syncProcessMap);
1063 });
1064 }
1065 std::unique_lock<std::mutex> lock(this->syncLock_);
1066 this->syncCondVar_.wait(lock, [status, &syncProcessMap]() {
1067 if (status != OK) {
1068 return true;
1069 }
1070 if (syncProcessMap.empty()) {
1071 return false;
1072 }
1073 for (const auto &entry : syncProcessMap) {
1074 if (entry.second.process < ProcessStatus::FINISHED) {
1075 return false;
1076 }
1077 }
1078 return true;
1079 });
1080 return status;
1081 }
1082
CorruptCallBack(const std::string & appId,const std::string & userId,const std::string & storeId)1083 void KvStoreCorruptInfo::CorruptCallBack(const std::string &appId, const std::string &userId,
1084 const std::string &storeId)
1085 {
1086 DatabaseInfo databaseInfo;
1087 databaseInfo.appId = appId;
1088 databaseInfo.userId = userId;
1089 databaseInfo.storeId = storeId;
1090 LOGD("appId :%s, userId:%s, storeId:%s", appId.c_str(), userId.c_str(), storeId.c_str());
1091 databaseInfoVect_.push_back(databaseInfo);
1092 }
1093
GetDatabaseInfoSize() const1094 size_t KvStoreCorruptInfo::GetDatabaseInfoSize() const
1095 {
1096 return databaseInfoVect_.size();
1097 }
1098
IsDataBaseCorrupted(const std::string & appId,const std::string & userId,const std::string & storeId) const1099 bool KvStoreCorruptInfo::IsDataBaseCorrupted(const std::string &appId, const std::string &userId,
1100 const std::string &storeId) const
1101 {
1102 for (const auto &item : databaseInfoVect_) {
1103 if (item.appId == appId &&
1104 item.userId == userId &&
1105 item.storeId == storeId) {
1106 return true;
1107 }
1108 }
1109 return false;
1110 }
1111
Reset()1112 void KvStoreCorruptInfo::Reset()
1113 {
1114 databaseInfoVect_.clear();
1115 }
1116
GetRandInt(const int randMin,const int randMax)1117 int DistributedDBToolsUnitTest::GetRandInt(const int randMin, const int randMax)
1118 {
1119 std::random_device randDev;
1120 std::mt19937 genRand(randDev());
1121 std::uniform_int_distribution<int> disRand(randMin, randMax);
1122 return disRand(genRand);
1123 }
1124
GetRandInt64(const int64_t randMin,const int64_t randMax)1125 int64_t DistributedDBToolsUnitTest::GetRandInt64(const int64_t randMin, const int64_t randMax)
1126 {
1127 std::random_device randDev;
1128 std::mt19937_64 genRand(randDev());
1129 std::uniform_int_distribution<int64_t> disRand(randMin, randMax);
1130 return disRand(genRand);
1131 }
1132
PrintTestCaseInfo()1133 void DistributedDBToolsUnitTest::PrintTestCaseInfo()
1134 {
1135 testing::UnitTest *test = testing::UnitTest::GetInstance();
1136 ASSERT_NE(test, nullptr);
1137 const testing::TestInfo *testInfo = test->current_test_info();
1138 ASSERT_NE(testInfo, nullptr);
1139 LOGI("Start unit test: %s.%s", testInfo->test_case_name(), testInfo->name());
1140 }
1141
BuildMessage(const DataSyncMessageInfo & messageInfo,DistributedDB::Message * & message)1142 int DistributedDBToolsUnitTest::BuildMessage(const DataSyncMessageInfo &messageInfo,
1143 DistributedDB::Message *&message)
1144 {
1145 auto packet = new (std::nothrow) DataRequestPacket;
1146 if (packet == nullptr) {
1147 return -E_OUT_OF_MEMORY;
1148 }
1149 message = new (std::nothrow) Message(messageInfo.messageId_);
1150 if (message == nullptr) {
1151 delete packet;
1152 packet = nullptr;
1153 return -E_OUT_OF_MEMORY;
1154 }
1155 packet->SetBasicInfo(messageInfo.sendCode_, messageInfo.version_, messageInfo.mode_);
1156 packet->SetWaterMark(messageInfo.localMark_, messageInfo.peerMark_, messageInfo.deleteMark_);
1157 std::vector<uint64_t> reserved {messageInfo.packetId_};
1158 packet->SetReserved(reserved);
1159 message->SetMessageType(messageInfo.messageType_);
1160 message->SetSessionId(messageInfo.sessionId_);
1161 message->SetSequenceId(messageInfo.sequenceId_);
1162 message->SetExternalObject(packet);
1163 return E_OK;
1164 }
1165
CreateDataBase(const std::string & dbUri)1166 sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri)
1167 {
1168 LOGD("Create database: %s", dbUri.c_str());
1169 sqlite3 *db = nullptr;
1170 if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) {
1171 LOGE("Open database [%s] failed. %d", dbUri.c_str(), r);
1172 if (db != nullptr) {
1173 (void)sqlite3_close_v2(db);
1174 db = nullptr;
1175 }
1176 }
1177 return db;
1178 }
1179
ExecSql(sqlite3 * db,const std::string & sql)1180 int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql)
1181 {
1182 if (db == nullptr || sql.empty()) {
1183 return -E_INVALID_ARGS;
1184 }
1185 char *errMsg = nullptr;
1186 int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg);
1187 if (errCode != SQLITE_OK && errMsg != nullptr) {
1188 LOGE("Execute sql failed. %d err: %s", errCode, errMsg);
1189 }
1190 sqlite3_free(errMsg);
1191 return errCode;
1192 }
1193
ExecSql(sqlite3 * db,const std::string & sql,const std::function<int (sqlite3_stmt *)> & bindCallback,const std::function<int (sqlite3_stmt *)> & resultCallback)1194 int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql,
1195 const std::function<int (sqlite3_stmt *)> &bindCallback, const std::function<int (sqlite3_stmt *)> &resultCallback)
1196 {
1197 if (db == nullptr || sql.empty()) {
1198 return -E_INVALID_ARGS;
1199 }
1200
1201 bool bindFinish = true;
1202 sqlite3_stmt *stmt = nullptr;
1203 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1204 if (errCode != E_OK) {
1205 goto END;
1206 }
1207
1208 do {
1209 if (bindCallback) {
1210 errCode = bindCallback(stmt);
1211 if (errCode != E_OK && errCode != -E_UNFINISHED) {
1212 goto END;
1213 }
1214 bindFinish = (errCode != -E_UNFINISHED); // continue bind if unfinished
1215 }
1216
1217 while (true) {
1218 errCode = SQLiteUtils::StepWithRetry(stmt);
1219 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1220 errCode = E_OK; // Step finished
1221 break;
1222 } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1223 goto END; // Step return error
1224 }
1225 if (resultCallback == nullptr) {
1226 continue;
1227 }
1228 errCode = resultCallback(stmt);
1229 if (errCode != E_OK) {
1230 goto END;
1231 }
1232 }
1233 SQLiteUtils::ResetStatement(stmt, false, errCode);
1234 } while (!bindFinish);
1235
1236 END:
1237 SQLiteUtils::ResetStatement(stmt, true, errCode);
1238 return errCode;
1239 }
1240
CreateDeviceTable(sqlite3 * db,const std::string & table,const std::string & device)1241 void RelationalTestUtils::CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device)
1242 {
1243 ASSERT_NE(db, nullptr);
1244 std::string deviceTable = DBCommon::GetDistributedTableName(device, table);
1245 TableInfo baseTbl;
1246 ASSERT_EQ(SQLiteUtils::AnalysisSchema(db, table, baseTbl), E_OK);
1247 EXPECT_EQ(SQLiteUtils::CreateSameStuTable(db, baseTbl, deviceTable), E_OK);
1248 EXPECT_EQ(SQLiteUtils::CloneIndexes(db, table, deviceTable), E_OK);
1249 }
1250
CheckSqlResult(sqlite3 * db,const std::string & sql,bool & result)1251 int RelationalTestUtils::CheckSqlResult(sqlite3 *db, const std::string &sql, bool &result)
1252 {
1253 if (db == nullptr || sql.empty()) {
1254 return -E_INVALID_ARGS;
1255 }
1256 sqlite3_stmt *stmt = nullptr;
1257 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1258 if (errCode != E_OK) {
1259 goto END;
1260 }
1261
1262 errCode = SQLiteUtils::StepWithRetry(stmt);
1263 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1264 result = true;
1265 errCode = E_OK;
1266 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1267 result = false;
1268 errCode = E_OK;
1269 }
1270 END:
1271 SQLiteUtils::ResetStatement(stmt, true, errCode);
1272 return errCode;
1273 }
1274
CheckTableRecords(sqlite3 * db,const std::string & table)1275 int RelationalTestUtils::CheckTableRecords(sqlite3 *db, const std::string &table)
1276 {
1277 if (db == nullptr || table.empty()) {
1278 return -E_INVALID_ARGS;
1279 }
1280 int count = -1;
1281 std::string sql = "select count(1) from " + table + ";";
1282
1283 sqlite3_stmt *stmt = nullptr;
1284 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1285 if (errCode != E_OK) {
1286 goto END;
1287 }
1288
1289 errCode = SQLiteUtils::StepWithRetry(stmt);
1290 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1291 count = sqlite3_column_int(stmt, 0);
1292 }
1293 END:
1294 SQLiteUtils::ResetStatement(stmt, true, errCode);
1295 return count;
1296 }
1297
GetMetaData(sqlite3 * db,const DistributedDB::Key & key,DistributedDB::Value & value)1298 int RelationalTestUtils::GetMetaData(sqlite3 *db, const DistributedDB::Key &key, DistributedDB::Value &value)
1299 {
1300 if (db == nullptr) {
1301 return -E_INVALID_ARGS;
1302 }
1303
1304 std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key = ?;";
1305 sqlite3_stmt *stmt = nullptr;
1306 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1307 if (errCode != E_OK) {
1308 goto END;
1309 }
1310 errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key);
1311 if (errCode != E_OK) {
1312 goto END;
1313 }
1314
1315 errCode = SQLiteUtils::StepWithRetry(stmt);
1316 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1317 errCode = SQLiteUtils::GetColumnBlobValue(stmt, 0, value);
1318 }
1319 END:
1320 SQLiteUtils::ResetStatement(stmt, true, errCode);
1321 return errCode;
1322 }
1323
SetMetaData(sqlite3 * db,const DistributedDB::Key & key,const DistributedDB::Value & value)1324 int RelationalTestUtils::SetMetaData(sqlite3 *db, const DistributedDB::Key &key, const DistributedDB::Value &value)
1325 {
1326 if (db == nullptr) {
1327 return -E_INVALID_ARGS;
1328 }
1329
1330 std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) +
1331 "metadata VALUES (?, ?);";
1332 sqlite3_stmt *stmt = nullptr;
1333 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1334 if (errCode != E_OK) {
1335 goto END;
1336 }
1337 errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key);
1338 if (errCode != E_OK) {
1339 goto END;
1340 }
1341 errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, value); // 2: bind index
1342 if (errCode != E_OK) {
1343 goto END;
1344 }
1345
1346 errCode = SQLiteUtils::StepWithRetry(stmt);
1347 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1348 errCode = E_OK;
1349 }
1350 END:
1351 SQLiteUtils::ResetStatement(stmt, true, errCode);
1352 return SQLiteUtils::MapSQLiteErrno(errCode);
1353 }
1354
CloudBlockSync(const DistributedDB::Query & query,DistributedDB::RelationalStoreDelegate * delegate,DistributedDB::DBStatus expect,DistributedDB::DBStatus callbackExpect)1355 void RelationalTestUtils::CloudBlockSync(const DistributedDB::Query &query,
1356 DistributedDB::RelationalStoreDelegate *delegate, DistributedDB::DBStatus expect,
1357 DistributedDB::DBStatus callbackExpect)
1358 {
1359 DistributedDB::CloudSyncOption option;
1360 option.devices = { "CLOUD" };
1361 option.mode = SYNC_MODE_CLOUD_MERGE;
1362 option.query = query;
1363 option.waitTime = DBConstant::MAX_TIMEOUT;
1364 CloudBlockSync(option, delegate, expect, callbackExpect);
1365 }
1366
CloudBlockSync(const DistributedDB::CloudSyncOption & option,DistributedDB::RelationalStoreDelegate * delegate,DistributedDB::DBStatus expect,DistributedDB::DBStatus callbackExpect)1367 void RelationalTestUtils::CloudBlockSync(const DistributedDB::CloudSyncOption &option,
1368 DistributedDB::RelationalStoreDelegate *delegate,
1369 DistributedDB::DBStatus expect, DistributedDB::DBStatus callbackExpect)
1370 {
1371 ASSERT_NE(delegate, nullptr);
1372 std::mutex dataMutex;
1373 std::condition_variable cv;
1374 bool finish = false;
1375 auto callback = [callbackExpect, &cv, &dataMutex, &finish](const std::map<std::string, SyncProcess> &process) {
1376 for (const auto &item: process) {
1377 if (item.second.process == DistributedDB::FINISHED) {
1378 {
1379 std::lock_guard<std::mutex> autoLock(dataMutex);
1380 finish = true;
1381 }
1382 EXPECT_EQ(item.second.errCode, callbackExpect);
1383 cv.notify_one();
1384 }
1385 }
1386 };
1387 ASSERT_EQ(delegate->Sync(option, callback), expect);
1388 if (expect != DistributedDB::DBStatus::OK) {
1389 return;
1390 }
1391 std::unique_lock<std::mutex> uniqueLock(dataMutex);
1392 cv.wait(uniqueLock, [&finish]() {
1393 return finish;
1394 });
1395 }
1396
SelectData(sqlite3 * db,const DistributedDB::TableSchema & schema,std::vector<DistributedDB::VBucket> & data)1397 int RelationalTestUtils::SelectData(sqlite3 *db, const DistributedDB::TableSchema &schema,
1398 std::vector<DistributedDB::VBucket> &data)
1399 {
1400 LOGD("[RelationalTestUtils] Begin select data");
1401 int errCode = E_OK;
1402 std::string selectSql = "SELECT ";
1403 for (const auto &field : schema.fields) {
1404 selectSql += field.colName + ",";
1405 }
1406 selectSql.pop_back();
1407 selectSql += " FROM " + schema.name;
1408 sqlite3_stmt *statement = nullptr;
1409 errCode = SQLiteUtils::GetStatement(db, selectSql, statement);
1410 if (errCode != E_OK) {
1411 LOGE("[RelationalTestUtils] Prepare statement failed %d", errCode);
1412 return errCode;
1413 }
1414 do {
1415 errCode = SQLiteUtils::StepWithRetry(statement, false);
1416 errCode = (errCode == -SQLITE_ROW) ? E_OK :
1417 (errCode == -SQLITE_DONE) ? -E_FINISHED : errCode;
1418 if (errCode != E_OK) {
1419 break;
1420 }
1421 VBucket rowData;
1422 for (size_t index = 0; index < schema.fields.size(); ++index) {
1423 Type colValue;
1424 int ret = SQLiteRelationalUtils::GetCloudValueByType(statement, schema.fields[index].type, index, colValue);
1425 if (ret != E_OK) {
1426 LOGE("[RelationalTestUtils] Get col value failed %d", ret);
1427 break;
1428 }
1429 rowData[schema.fields[index].colName] = colValue;
1430 }
1431 data.push_back(rowData);
1432 } while (errCode == E_OK);
1433 if (errCode == -E_FINISHED) {
1434 errCode = E_OK;
1435 }
1436 int err = E_OK;
1437 SQLiteUtils::ResetStatement(statement, true, err);
1438 LOGW("[RelationalTestUtils] Select data finished errCode %d", errCode);
1439 return errCode != E_OK ? errCode : err;
1440 }
1441
GetAssets(const DistributedDB::Type & value,const std::shared_ptr<DistributedDB::ICloudDataTranslate> & translate,bool isAsset)1442 DistributedDB::Assets RelationalTestUtils::GetAssets(const DistributedDB::Type &value,
1443 const std::shared_ptr<DistributedDB::ICloudDataTranslate> &translate, bool isAsset)
1444 {
1445 DistributedDB::Assets assets;
1446 if (value.index() == TYPE_INDEX<Assets>) {
1447 auto tmp = std::get<Assets>(value);
1448 assets.insert(assets.end(), tmp.begin(), tmp.end());
1449 } else if (value.index() == TYPE_INDEX<Asset>) {
1450 assets.push_back(std::get<Asset>(value));
1451 } else if (value.index() == TYPE_INDEX<Bytes> && translate != nullptr) {
1452 if (isAsset) {
1453 auto tmpAsset = translate->BlobToAsset(std::get<Bytes>(value));
1454 assets.push_back(tmpAsset);
1455 } else {
1456 auto tmpAssets = translate->BlobToAssets(std::get<Bytes>(value));
1457 assets.insert(assets.end(), tmpAssets.begin(), tmpAssets.end());
1458 }
1459 }
1460 return assets;
1461 }
1462
InsertCloudRecord(int64_t begin,int64_t count,const std::string & tableName,const std::shared_ptr<DistributedDB::VirtualCloudDb> & cloudDbPtr,int32_t assetCount)1463 DistributedDB::DBStatus RelationalTestUtils::InsertCloudRecord(int64_t begin, int64_t count,
1464 const std::string &tableName, const std::shared_ptr<DistributedDB::VirtualCloudDb> &cloudDbPtr, int32_t assetCount)
1465 {
1466 if (cloudDbPtr == nullptr) {
1467 LOGE("[RelationalTestUtils] Not support insert cloud with null");
1468 return DistributedDB::DBStatus::DB_ERROR;
1469 }
1470 std::vector<VBucket> record;
1471 std::vector<VBucket> extend;
1472 Timestamp now = DistributedDB::TimeHelper::GetSysCurrentTime();
1473 for (int64_t i = begin; i < (begin + count); ++i) {
1474 VBucket data;
1475 data.insert_or_assign("id", std::to_string(i));
1476 data.insert_or_assign("name", "Cloud" + std::to_string(i));
1477 Assets assets;
1478 std::string assetNameBegin = "Phone" + std::to_string(i);
1479 for (int j = 1; j <= assetCount; ++j) {
1480 Asset asset;
1481 asset.name = assetNameBegin + "_" + std::to_string(j);
1482 asset.status = AssetStatus::INSERT;
1483 asset.hash = "DEC";
1484 asset.assetId = std::to_string(j);
1485 assets.push_back(asset);
1486 }
1487 data.insert_or_assign("assets", assets);
1488 record.push_back(data);
1489 VBucket log;
1490 log.insert_or_assign(DistributedDB::CloudDbConstant::CREATE_FIELD, static_cast<int64_t>(
1491 now / DistributedDB::CloudDbConstant::TEN_THOUSAND));
1492 log.insert_or_assign(DistributedDB::CloudDbConstant::MODIFY_FIELD, static_cast<int64_t>(
1493 now / DistributedDB::CloudDbConstant::TEN_THOUSAND));
1494 log.insert_or_assign(DistributedDB::CloudDbConstant::DELETE_FIELD, false);
1495 extend.push_back(log);
1496 }
1497 return cloudDbPtr->BatchInsert(tableName, std::move(record), extend);
1498 }
1499
GetAllAssets(sqlite3 * db,const DistributedDB::TableSchema & schema,const std::shared_ptr<DistributedDB::ICloudDataTranslate> & translate)1500 std::vector<DistributedDB::Assets> RelationalTestUtils::GetAllAssets(sqlite3 *db,
1501 const DistributedDB::TableSchema &schema, const std::shared_ptr<DistributedDB::ICloudDataTranslate> &translate)
1502 {
1503 std::vector<DistributedDB::Assets> res;
1504 if (db == nullptr || translate == nullptr) {
1505 LOGW("[RelationalTestUtils] DB or translate is null");
1506 return res;
1507 }
1508 std::vector<VBucket> allData;
1509 EXPECT_EQ(RelationalTestUtils::SelectData(db, schema, allData), E_OK);
1510 std::map<std::string, int32_t> assetFields;
1511 for (const auto &field : schema.fields) {
1512 if (field.type != TYPE_INDEX<Asset> && field.type != TYPE_INDEX<Assets>) {
1513 continue;
1514 }
1515 assetFields[field.colName] = field.type;
1516 }
1517 for (const auto &oneRow : allData) {
1518 Assets assets;
1519 for (const auto &[col, data] : oneRow) {
1520 if (assetFields.find(col) == assetFields.end()) {
1521 continue;
1522 }
1523 auto tmpAssets = GetAssets(data, translate, (assetFields[col] == TYPE_INDEX<Asset>));
1524 assets.insert(assets.end(), tmpAssets.begin(), tmpAssets.end());
1525 }
1526 res.push_back(assets);
1527 }
1528 return res;
1529 }
1530
GetRecordLog(sqlite3 * db,const std::string & tableName,std::vector<DistributedDB::VBucket> & records)1531 int RelationalTestUtils::GetRecordLog(sqlite3 *db, const std::string &tableName,
1532 std::vector<DistributedDB::VBucket> &records)
1533 {
1534 DistributedDB::TableSchema schema;
1535 schema.name = DBCommon::GetLogTableName(tableName);
1536 Field field;
1537 field.type = TYPE_INDEX<int64_t>;
1538 field.colName = "data_key";
1539 schema.fields.push_back(field);
1540 field.colName = "flag";
1541 schema.fields.push_back(field);
1542 field.colName = "cursor";
1543 schema.fields.push_back(field);
1544 field.colName = "cloud_gid";
1545 field.type = TYPE_INDEX<std::string>;
1546 schema.fields.push_back(field);
1547 return SelectData(db, schema, records);
1548 }
1549
DeleteRecord(sqlite3 * db,const std::string & tableName,const std::vector<std::map<std::string,std::string>> & conditions)1550 int RelationalTestUtils::DeleteRecord(sqlite3 *db, const std::string &tableName,
1551 const std::vector<std::map<std::string, std::string>> &conditions)
1552 {
1553 if (db == nullptr || tableName.empty()) {
1554 LOGE("[RelationalTestUtils] db is null or table is empty");
1555 return -E_INVALID_ARGS;
1556 }
1557 int errCode = E_OK;
1558 for (const auto &condition : conditions) {
1559 std::string deleteSql = "DELETE FROM " + tableName + " WHERE ";
1560 int count = 0;
1561 for (const auto &[col, value] : condition) {
1562 if (count > 0) {
1563 deleteSql += " AND ";
1564 }
1565 deleteSql += col + "=" + value;
1566 count++;
1567 }
1568 LOGD("[RelationalTestUtils] Sql is %s", deleteSql.c_str());
1569 errCode = ExecSql(db, deleteSql);
1570 if (errCode != E_OK) {
1571 return errCode;
1572 }
1573 }
1574 return errCode;
1575 }
1576
IsExistEmptyHashAsset(sqlite3 * db,const DistributedDB::TableSchema & schema)1577 bool RelationalTestUtils::IsExistEmptyHashAsset(sqlite3 *db, const DistributedDB::TableSchema &schema)
1578 {
1579 if (db == nullptr) {
1580 return false;
1581 }
1582 std::vector<Field> assetCol;
1583 for (const auto &field : schema.fields) {
1584 if (field.type == TYPE_INDEX<Asset> || field.type == TYPE_INDEX<Assets>) {
1585 assetCol.push_back(field);
1586 }
1587 }
1588 if (assetCol.empty()) {
1589 return false;
1590 }
1591 std::string sql = "SELECT ";
1592 for (const auto &field : assetCol) {
1593 sql += field.colName + ",";
1594 }
1595 sql.pop_back();
1596 sql += " FROM " + schema.name;
1597 sqlite3_stmt *stmt = nullptr;
1598 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1599 if (errCode != E_OK) {
1600 return false;
1601 }
1602 ResFinalizer finalizer([stmt]() {
1603 sqlite3_stmt *statement = stmt;
1604 int ret = E_OK;
1605 SQLiteUtils::ResetStatement(statement, true, ret);
1606 });
1607 VirtualCloudDataTranslate translate;
1608 while (sqlite3_step(stmt) == SQLITE_ROW) {
1609 for (int index = 0; index < static_cast<int>(assetCol.size()); index++) {
1610 Value value;
1611 (void)SQLiteUtils::GetColumnBlobValue(stmt, index, value);
1612 Assets assets;
1613 if (assetCol[index].type == TYPE_INDEX<Asset>) {
1614 assets.push_back(translate.BlobToAsset(value));
1615 } else {
1616 assets = translate.BlobToAssets(value);
1617 }
1618 if (IsExistEmptyHashAsset(assets)) {
1619 return true;
1620 }
1621 }
1622 }
1623 return false;
1624 }
1625
IsExistEmptyHashAsset(const DistributedDB::Assets & assets)1626 bool RelationalTestUtils::IsExistEmptyHashAsset(const DistributedDB::Assets &assets)
1627 {
1628 return std::any_of(assets.begin(), assets.end(), [](const Asset &asset) {
1629 return asset.hash.empty();
1630 });
1631 }
1632
IsSupport()1633 bool DBInfoHandleTest::IsSupport()
1634 {
1635 std::lock_guard<std::mutex> autoLock(supportMutex_);
1636 return localIsSupport_;
1637 }
1638
IsNeedAutoSync(const std::string & userId,const std::string & appId,const std::string & storeId,const DeviceInfos & devInfo)1639 bool DBInfoHandleTest::IsNeedAutoSync(const std::string &userId, const std::string &appId, const std::string &storeId,
1640 const DeviceInfos &devInfo)
1641 {
1642 std::lock_guard<std::mutex> autoLock(autoSyncMutex_);
1643 return isNeedAutoSync_;
1644 }
1645
SetLocalIsSupport(bool isSupport)1646 void DBInfoHandleTest::SetLocalIsSupport(bool isSupport)
1647 {
1648 std::lock_guard<std::mutex> autoLock(supportMutex_);
1649 localIsSupport_ = isSupport;
1650 }
1651
SetNeedAutoSync(bool needAutoSync)1652 void DBInfoHandleTest::SetNeedAutoSync(bool needAutoSync)
1653 {
1654 std::lock_guard<std::mutex> autoLock(autoSyncMutex_);
1655 isNeedAutoSync_ = needAutoSync;
1656 }
1657
GetRDBStorageHook(const std::string & userId,const std::string & appId,const std::string & storeId,const std::string & dbPath)1658 DistributedDB::ICloudSyncStorageHook *RelationalTestUtils::GetRDBStorageHook(const std::string &userId,
1659 const std::string &appId, const std::string &storeId, const std::string &dbPath)
1660 {
1661 RelationalDBProperties properties;
1662 CloudDBSyncUtilsTest::InitStoreProp(dbPath, appId, userId, storeId, properties);
1663 int errCode = E_OK;
1664 auto store = RelationalStoreInstance::GetDataBase(properties, errCode);
1665 if (store == nullptr) {
1666 return nullptr;
1667 }
1668 auto engine = static_cast<SQLiteRelationalStore *>(store)->GetStorageEngine();
1669 return static_cast<ICloudSyncStorageHook *>(engine);
1670 }
1671
IsAssetChange(const std::string & table) const1672 bool RelationalStoreObserverUnitTest::IsAssetChange(const std::string &table) const
1673 {
1674 auto changeData = savedChangedData_.find(table);
1675 if (changeData == savedChangedData_.end()) {
1676 return false;
1677 }
1678 return changeData->second.type == ChangedDataType::ASSET;
1679 }
1680
GetLastOrigin() const1681 DistributedDB::Origin RelationalStoreObserverUnitTest::GetLastOrigin() const
1682 {
1683 return lastOrigin_;
1684 }
1685 } // namespace DistributedDBUnitTest
1686