• 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 #ifndef DISTRIBUTEDDB_TOOLS_UNIT_TEST_H
17 #define DISTRIBUTEDDB_TOOLS_UNIT_TEST_H
18 
19 #include <algorithm>
20 #include <condition_variable>
21 #include <dirent.h>
22 #include <mutex>
23 #include <string>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <unordered_map>
28 #include <vector>
29 
30 #include "cloud/virtual_cloud_db.h"
31 #include "db_info_handle.h"
32 #include "db_types.h"
33 #include "kv_store_changed_data.h"
34 #include "kv_store_delegate_impl.h"
35 #include "kv_store_delegate_manager.h"
36 #include "kv_store_nb_delegate.h"
37 #include "kv_store_observer.h"
38 #include "kv_store_snapshot_delegate_impl.h"
39 #include "log_print.h"
40 #include "message.h"
41 #include "query.h"
42 #include "relational_store_delegate.h"
43 #include "relational_store_sqlite_ext.h"
44 #include "store_observer.h"
45 #include "store_changed_data.h"
46 #include "single_ver_kv_entry.h"
47 #include "sqlite_single_ver_natural_store.h"
48 #include "sqlite_utils.h"
49 #include "sync_types.h"
50 #include "store_types.h"
51 #include "types_export.h"
52 
53 namespace DistributedDBUnitTest {
54 struct DatabaseInfo {
55     std::string appId{};
56     std::string userId{};
57     std::string storeId{};
58     std::string dir{};
59     int dbUserVersion = 0;
60 };
61 
62 struct SyncInputArg {
63     uint64_t begin_{};
64     uint64_t end_{};
65     uint32_t blockSize_{};
SyncInputArgSyncInputArg66     SyncInputArg(uint64_t begin, uint64_t end, uint32_t blockSize)
67         : begin_(begin), end_(end), blockSize_(blockSize)
68     {}
69 };
70 
71 struct DataSyncMessageInfo {
72     int messageId_ = DistributedDB::INVALID_MESSAGE_ID;
73     uint16_t messageType_ = DistributedDB::TYPE_INVALID;
74     uint32_t sequenceId_ = 0;
75     uint32_t sessionId_ = 0;
76     int sendCode_ = DistributedDB::E_OK;
77     uint32_t version_ = 0;
78     int32_t mode_ = DistributedDB::PUSH;
79     DistributedDB::WaterMark localMark_ = 0;
80     DistributedDB::WaterMark peerMark_ = 0;
81     DistributedDB::WaterMark deleteMark_ = 0;
82     uint64_t packetId_ = 0;
83 };
84 
85 class DistributedDBToolsUnitTest final {
86 public:
DistributedDBToolsUnitTest()87     DistributedDBToolsUnitTest() {}
~DistributedDBToolsUnitTest()88     ~DistributedDBToolsUnitTest() {}
89 
90     DistributedDBToolsUnitTest(const DistributedDBToolsUnitTest&) = delete;
91     DistributedDBToolsUnitTest& operator=(const DistributedDBToolsUnitTest&) = delete;
92     DistributedDBToolsUnitTest(DistributedDBToolsUnitTest&&) = delete;
93     DistributedDBToolsUnitTest& operator=(DistributedDBToolsUnitTest&&) = delete;
94 
95     // compare whether two vectors are equal.
96     template<typename T>
CompareVector(const std::vector<T> & vec1,const std::vector<T> & vec2)97     static bool CompareVector(const std::vector<T>& vec1, const std::vector<T>& vec2)
98     {
99         if (vec1.size() != vec2.size()) {
100             return false;
101         }
102         for (size_t i = 0; i < vec2.size(); i++) {
103             if (vec1[i] != vec2[i]) {
104                 return false;
105             }
106         }
107         return true;
108     }
109 
110     // compare whether two vectors are equal.
111     template<typename T>
CompareVectorN(const std::vector<T> & vec1,const std::vector<T> & vec2,uint32_t n)112     static bool CompareVectorN(const std::vector<T>& vec1, const std::vector<T>& vec2, uint32_t n)
113     {
114         if (n > std::min(vec1.size(), vec2.size())) {
115             return false;
116         }
117         for (uint32_t i = 0; i < n; i++) {
118             if (vec1[i] != vec2[i]) {
119                 return false;
120             }
121         }
122         return true;
123     }
124     // init the test directory of dir.
125     static void TestDirInit(std::string &dir);
126 
127     // remove the test db files in the test directory of dir.
128     static int RemoveTestDbFiles(const std::string &dir);
129 
130 #ifndef OMIT_MULTI_VER
131     // callback function for get a KvStoreDelegate pointer.
132     static void KvStoreDelegateCallback(DistributedDB::DBStatus, DistributedDB::KvStoreDelegate*,
133         DistributedDB::DBStatus &, DistributedDB::KvStoreDelegate *&);
134 
135     // callback function for get a KvStoreSnapshotDelegate pointer.
136     static void SnapshotDelegateCallback(DistributedDB::DBStatus, DistributedDB::KvStoreSnapshotDelegate*,
137         DistributedDB::DBStatus &, DistributedDB::KvStoreSnapshotDelegate *&);
138 #endif
139 
140     // callback function for get a KvStoreDelegate pointer.
141     static void KvStoreNbDelegateCallback(DistributedDB::DBStatus, DistributedDB::KvStoreNbDelegate*,
142         DistributedDB::DBStatus &, DistributedDB::KvStoreNbDelegate *&);
143 
144     // callback function for get the value.
145     static void ValueCallback(
146         DistributedDB::DBStatus, const DistributedDB::Value &, DistributedDB::DBStatus &, DistributedDB::Value &);
147 
148     // callback function for get an entry vector.
149     static void EntryVectorCallback(DistributedDB::DBStatus, const std::vector<DistributedDB::Entry> &,
150         DistributedDB::DBStatus &, unsigned long &, std::vector<DistributedDB::Entry> &);
151 
152     // sync test helper
153     DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate,
154         const std::vector<std::string>& devices, DistributedDB::SyncMode mode,
155         std::map<std::string, DistributedDB::DBStatus>& statuses, bool wait = false);
156 
157     // sync test helper
158     DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate,
159         const std::vector<std::string>& devices, DistributedDB::SyncMode mode,
160         std::map<std::string, DistributedDB::DBStatus>& statuses, const DistributedDB::Query &query);
161 
162     DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate,
163         const DistributedDB::DeviceSyncOption& option, std::map<std::string, DistributedDB::DBStatus>& statuses);
164 
165     DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate,
166         DistributedDB::DeviceSyncOption option,
167         std::map<std::string, DistributedDB::DeviceSyncProcess> &syncProcessMap);
168 
169     static void GetRandomKeyValue(std::vector<uint8_t> &value, uint32_t defaultSize = 0);
170 
171     static bool IsValueEqual(const DistributedDB::Value &read, const DistributedDB::Value &origin);
172 
173     static bool IsEntryEqual(const DistributedDB::Entry &entryOrg, const DistributedDB::Entry &entryRet);
174 
175     static bool IsEntriesEqual(const std::vector<DistributedDB::Entry> &entriesOrg,
176         const std::vector<DistributedDB::Entry> &entriesRet, bool needSort = false);
177 
178     static bool CheckObserverResult(const std::vector<DistributedDB::Entry> &orgEntries,
179         const std::list<DistributedDB::Entry> &resultLst);
180 
181     static bool IsItemValueExist(const DistributedDB::DataItem &item,
182         const std::vector<DistributedDB::DataItem> &items);
183 
184     static bool IsEntryExist(const DistributedDB::Entry &entry,
185         const std::vector<DistributedDB::Entry> &entries);
186 
187     static bool IsKvEntryExist(const DistributedDB::Entry &entry,
188         const std::vector<DistributedDB::Entry> &entries);
189 
190     static void CalcHash(const std::vector<uint8_t> &value, std::vector<uint8_t> &hashValue);
191 
192     static int CreateMockSingleDb(DatabaseInfo &dbInfo, DistributedDB::OpenDbProperties &properties);
193 
194     static int CreateMockMultiDb(DatabaseInfo &dbInfo, DistributedDB::OpenDbProperties &properties);
195 
196     static int ModifyDatabaseFile(const std::string &fileDir, uint64_t modifyPos = 0,
197         uint32_t modifyCnt = 256, uint32_t value = 0x1F1F1F1F);
198 
199     static int GetSyncDataTest(const SyncInputArg &syncInputArg, DistributedDB::SQLiteSingleVerNaturalStore *store,
200         std::vector<DistributedDB::DataItem> &dataItems, DistributedDB::ContinueToken &continueStmtToken);
201 
202     static int GetSyncDataNextTest(DistributedDB::SQLiteSingleVerNaturalStore *store, uint32_t blockSize,
203         std::vector<DistributedDB::DataItem> &dataItems, DistributedDB::ContinueToken &continueStmtToken);
204 
205     static int PutSyncDataTest(DistributedDB::SQLiteSingleVerNaturalStore *store,
206         const std::vector<DistributedDB::DataItem> &dataItems, const std::string &deviceName);
207 
208     static int PutSyncDataTest(DistributedDB::SQLiteSingleVerNaturalStore *store,
209         const std::vector<DistributedDB::DataItem> &dataItems, const std::string &deviceName,
210         const DistributedDB::QueryObject &query);
211 
212     static int ConvertItemsToSingleVerEntry(const std::vector<DistributedDB::DataItem> &dataItems,
213         std::vector<DistributedDB::SingleVerKvEntry *> &entries);
214 
215     static void ConvertSingleVerEntryToItems(std::vector<DistributedDB::SingleVerKvEntry *> &entries,
216         std::vector<DistributedDB::DataItem> &dataItems);
217 
218     static void ReleaseSingleVerEntry(std::vector<DistributedDB::SingleVerKvEntry *> &entries);
219 
220     static std::vector<uint8_t> GetRandPrefixKey(const std::vector<uint8_t> &prefixKey, uint32_t size);
221 
222     static int GetCurrentDir(std::string& dir);
223 
224     static int GetResourceDir(std::string& dir);
225 
226     static int GetRandInt(const int randMin, const int randMax);
227     static int64_t GetRandInt64(const int64_t randMin, const int64_t randMax);
228 
229     static void PrintTestCaseInfo();
230 
231     static int BuildMessage(const DataSyncMessageInfo &messageInfo, DistributedDB::Message *&message);
232 
233     static void Dump();
234 
235     static std::string GetKvNbStoreDirectory(const std::string &identifier, const std::string &dbFilePath,
236         const std::string &dbDir);
237 
238     static void BlockSync(DistributedDB::RelationalStoreDelegate &delegate, const DistributedDB::Query &query,
239         DistributedDB::SyncMode syncMode, DistributedDB::DBStatus exceptStatus,
240         const std::vector<std::string> &devices);
241 
242     static void BlockSync(DistributedDB::KvStoreNbDelegate *delegate, DistributedDB::DBStatus expectDBStatus,
243         DistributedDB::CloudSyncOption option, DistributedDB::DBStatus expectSyncResult = DistributedDB::DBStatus::OK);
244 private:
245     static int OpenMockMultiDb(DatabaseInfo &dbInfo, DistributedDB::OpenDbProperties &properties);
246 
247     std::mutex syncLock_ {};
248     std::condition_variable syncCondVar_ {};
249 };
250 
251 class KvStoreObserverUnitTest : public DistributedDB::KvStoreObserver {
252 public:
253     KvStoreObserverUnitTest();
254     ~KvStoreObserverUnitTest() override = default;
255 
256     KvStoreObserverUnitTest(const KvStoreObserverUnitTest&) = delete;
257     KvStoreObserverUnitTest& operator=(const KvStoreObserverUnitTest&) = delete;
258     KvStoreObserverUnitTest(KvStoreObserverUnitTest&&) = delete;
259     KvStoreObserverUnitTest& operator=(KvStoreObserverUnitTest&&) = delete;
260 
261     // callback function will be called when the db data is changed.
262     void OnChange(const DistributedDB::KvStoreChangedData&) override;
263 
264     void OnChange(const DistributedDB::StoreChangedData &data) override;
265 
266     void OnChange(DistributedDB::Origin origin, const std::string &originalId,
267         DistributedDB::ChangedData &&data) override;
268 
269     void OnChange(StoreChangedInfo &&data) override;
270 
271     // reset the callCount_ to zero.
272     void ResetToZero();
273 
274     // get callback results.
275     unsigned long GetCallCount() const;
276     const std::list<DistributedDB::Entry> &GetEntriesInserted() const;
277     const std::list<DistributedDB::Entry> &GetEntriesUpdated() const;
278     const std::list<DistributedDB::Entry> &GetEntriesDeleted() const;
279     bool IsCleared() const;
280     std::unordered_map<std::string, DistributedDB::ChangedData> GetChangedData() const;
281 private:
282     unsigned long callCount_;
283     bool isCleared_;
284     std::list<DistributedDB::Entry> inserted_;
285     std::list<DistributedDB::Entry> updated_;
286     std::list<DistributedDB::Entry> deleted_;
287     std::unordered_map<std::string, DistributedDB::ChangedData> changedData_;
288 };
289 
290 class RelationalStoreObserverUnitTest : public DistributedDB::StoreObserver {
291 public:
292     RelationalStoreObserverUnitTest();
~RelationalStoreObserverUnitTest()293     ~RelationalStoreObserverUnitTest() {}
294 
295     RelationalStoreObserverUnitTest(const RelationalStoreObserverUnitTest&) = delete;
296     RelationalStoreObserverUnitTest& operator=(const RelationalStoreObserverUnitTest&) = delete;
297     RelationalStoreObserverUnitTest(RelationalStoreObserverUnitTest&&) = delete;
298     RelationalStoreObserverUnitTest& operator=(RelationalStoreObserverUnitTest&&) = delete;
299 
300     // callback function will be called when the db data is changed.
301     void OnChange(const DistributedDB::StoreChangedData &data);
302 
303     void OnChange(DistributedDB::Origin origin, const std::string &originalId, DistributedDB::ChangedData &&data);
304 
305     uint32_t GetCallbackDetailsType() const;
306     void SetCallbackDetailsType(uint32_t type);
307 
308     void SetExpectedResult(const DistributedDB::ChangedData &changedData);
309 
310     bool IsAllChangedDataEq();
311 
312     void ClearChangedData();
313 
314     // reset the callCount_ to zero.
315     void ResetToZero();
316     void ResetCloudSyncToZero();
317 
318     // get callback results.
319     unsigned long GetCallCount() const;
320     unsigned long GetCloudCallCount() const;
321     const std::string GetDataChangeDevice() const;
322     DistributedDB::StoreProperty GetStoreProperty() const;
323     std::unordered_map<std::string, DistributedDB::ChangedData> GetSavedChangedData() const;
324 
325     bool IsAssetChange(const std::string &table) const;
326 
327     DistributedDB::Origin GetLastOrigin() const;
328 private:
329     unsigned long callCount_;
330     unsigned long cloudCallCount_ = 0;
331     std::string changeDevice_;
332     DistributedDB::StoreProperty storeProperty_;
333     std::unordered_map<std::string, DistributedDB::ChangedData> expectedChangedData_;
334     std::unordered_map<std::string, DistributedDB::ChangedData> savedChangedData_;
335     uint32_t detailsType_ = static_cast<uint32_t>(DistributedDB::CallbackDetailsType::DEFAULT);
336     DistributedDB::Origin lastOrigin_ = DistributedDB::ORIGIN_REMOTE;
337 };
338 
339 class KvStoreCorruptInfo {
340 public:
KvStoreCorruptInfo()341     KvStoreCorruptInfo() {}
~KvStoreCorruptInfo()342     ~KvStoreCorruptInfo() {}
343 
344     KvStoreCorruptInfo(const KvStoreCorruptInfo&) = delete;
345     KvStoreCorruptInfo& operator=(const KvStoreCorruptInfo&) = delete;
346     KvStoreCorruptInfo(KvStoreCorruptInfo&&) = delete;
347     KvStoreCorruptInfo& operator=(KvStoreCorruptInfo&&) = delete;
348 
349     // callback function will be called when the db data is changed.
350     void CorruptCallBack(const std::string &appId, const std::string &userId, const std::string &storeId);
351     size_t GetDatabaseInfoSize() const;
352     bool IsDataBaseCorrupted(const std::string &appId, const std::string &userId, const std::string &storeId) const;
353     void Reset();
354 private:
355     std::vector<DatabaseInfo> databaseInfoVect_;
356 };
357 
358 class RelationalTestUtils {
359 public:
360     static sqlite3 *CreateDataBase(const std::string &dbUri);
361     static int ExecSql(sqlite3 *db, const std::string &sql);
362     static int ExecSql(sqlite3 *db, const std::string &sql, const std::function<int (sqlite3_stmt *)> &bindCallback,
363         const std::function<int (sqlite3_stmt *)> &resultCallback);
364     static void CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device);
365     static int CheckSqlResult(sqlite3 *db, const std::string &sql, bool &result);
366     static int CheckTableRecords(sqlite3 *db, const std::string &table);
367     static int GetMetaData(sqlite3 *db, const DistributedDB::Key &key, DistributedDB::Value &value);
368     static int SetMetaData(sqlite3 *db, const DistributedDB::Key &key, const DistributedDB::Value &value);
369     static void CloudBlockSync(const DistributedDB::Query &query, DistributedDB::RelationalStoreDelegate *delegate,
370         DistributedDB::DBStatus expect = DistributedDB::DBStatus::OK,
371         DistributedDB::DBStatus callbackExpect = DistributedDB::DBStatus::OK);
372     static int SelectData(sqlite3 *db, const DistributedDB::TableSchema &schema,
373         std::vector<DistributedDB::VBucket> &data);
374     static DistributedDB::Assets GetAssets(const DistributedDB::Type &value,
375         const std::shared_ptr<DistributedDB::ICloudDataTranslate> &translate, bool isAsset = false);
376     static DistributedDB::DBStatus InsertCloudRecord(int64_t begin, int64_t count, const std::string &tableName,
377         const std::shared_ptr<DistributedDB::VirtualCloudDb> &cloudDbPtr, int32_t assetCount = 1);
378     static std::vector<DistributedDB::Assets> GetAllAssets(sqlite3 *db, const DistributedDB::TableSchema &schema,
379         const std::shared_ptr<DistributedDB::ICloudDataTranslate> &translate);
380     static int GetRecordLog(sqlite3 *db, const std::string &tableName, std::vector<DistributedDB::VBucket> &records);
381     static int DeleteRecord(sqlite3 *db, const std::string &tableName,
382         const std::vector<std::map<std::string, std::string>> &conditions);
383     static void CloudBlockSync(const DistributedDB::CloudSyncOption &option,
384         DistributedDB::RelationalStoreDelegate *delegate,
385         DistributedDB::DBStatus expect = DistributedDB::DBStatus::OK,
386         DistributedDB::DBStatus callbackExpect = DistributedDB::DBStatus::OK);
387     static bool IsExistEmptyHashAsset(sqlite3 *db, const DistributedDB::TableSchema &schema);
388     static bool IsExistEmptyHashAsset(const DistributedDB::Assets &assets);
389     static DistributedDB::ICloudSyncStorageHook *GetRDBStorageHook(const std::string &userId,
390         const std::string &appId, const std::string &storeId, const std::string &dbPath);
391     static void CheckIndexCount(sqlite3 *db, const std::string &table, size_t expect);
392     static std::pair<int, uint64_t> GetMaxTimestamp(sqlite3 *db, const std::string &oriTable);
393 };
394 
395 class DBInfoHandleTest : public DistributedDB::DBInfoHandle {
396 public:
397     ~DBInfoHandleTest() override = default;
398 
399     bool IsSupport() override;
400 
401     bool IsNeedAutoSync(const std::string &userId, const std::string &appId, const std::string &storeId,
402         const DistributedDB::DeviceInfos &devInfo) override;
403 
404     void SetLocalIsSupport(bool isSupport);
405 
406     void SetNeedAutoSync(bool needAutoSync);
407 private:
408     std::mutex supportMutex_;
409     bool localIsSupport_ = true;
410     std::mutex autoSyncMutex_;
411     bool isNeedAutoSync_ = true;
412 };
413 } // namespace DistributedDBUnitTest
414 
415 #endif // DISTRIBUTEDDB_TOOLS_UNIT_TEST_H
416