• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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