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