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