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