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 #include "distributeddb_nb_test_tools.h"
16 #include <fstream>
17 
18 #if defined(RUNNING_ON_LINUX)
19 #include <unistd.h>
20 #elif defined RUNNING_ON_WIN
21 #include <windows.h>
22 #endif
23 
24 #ifndef USING_SQLITE_SYMBOLS
25 #include "sqlite3.h"
26 #else
27 #include "sqlite3sym.h"
28 #endif
29 using namespace std;
30 using namespace std::placeholders;
31 using namespace DistributedDB;
32 using namespace DistributedDBDataGenerator;
33 
Callback(DBStatus status,KvStoreNbDelegate * kvStoreNbDelegate)34 void DelegateMgrNbCallback::Callback(DBStatus status, KvStoreNbDelegate *kvStoreNbDelegate)
35 {
36     this->status_ = status;
37     this->kvStoreNbDelegate_ = kvStoreNbDelegate;
38     MST_LOG("DelegateMgrNbCallback status:%d, kvStoreNbDelegate_null: %d", status, (kvStoreNbDelegate == nullptr));
39 }
40 
GetStatus()41 DBStatus DelegateMgrNbCallback::GetStatus()
42 {
43     return status_;
44 }
45 
GetKvStore()46 KvStoreNbDelegate *DelegateMgrNbCallback::GetKvStore()
47 {
48     return kvStoreNbDelegate_;
49 }
50 
GetNbDelegateSuccess(KvStoreDelegateManager * & outManager,const DBParameters & param,const Option & optionParam,const string & dbPath)51 KvStoreNbDelegate* DistributedDBNbTestTools::GetNbDelegateSuccess(KvStoreDelegateManager *&outManager,
52     const DBParameters &param, const Option &optionParam, const string &dbPath)
53 {
54     MST_LOG("GetNbDelegate isMemoryDb= %d, isEncryptedDb= %d", optionParam.isMemoryDb,
55         optionParam.isEncryptedDb);
56     SetDir(dbPath);
57     if (param.storeId.empty() || param.appId.empty() || param.userId.empty()) {
58         return nullptr;
59     }
60 
61     // define a Callback to hold the KvStoreNbDelegate and status.
62     DelegateMgrNbCallback delegateMgrCallback;
63     function<void(DBStatus, KvStoreNbDelegate*)> function
64         = bind(&DelegateMgrNbCallback::Callback, &delegateMgrCallback, _1, _2);
65 
66     // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg.
67     if (outManager != nullptr) {
68         delete outManager;
69         outManager = nullptr;
70     }
71     KvStoreDelegateManager *manager = new (std::nothrow) KvStoreDelegateManager(param.appId, param.userId);
72     if (manager == nullptr) {
73         return nullptr;
74     }
75     DBStatus status = manager->SetKvStoreConfig({ .dataDir = dbPath});
76     if (status != DBStatus::OK) {
77         MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status);
78         delete manager;
79         manager = nullptr;
80         return nullptr;
81     }
82 
83     KvStoreNbDelegate::Option option = TransferNbOptionType(optionParam);
84     // get kv store, then the Callback will save the status and delegate.
85     manager->GetKvStore(param.storeId, option, function);
86     status = delegateMgrCallback.GetStatus();
87     if (status != DBStatus::OK) {
88         MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), status);
89         delete manager;
90         manager = nullptr;
91         return nullptr;
92     }
93     const KvStoreNbDelegate* delegate = const_cast<KvStoreNbDelegate *>(delegateMgrCallback.GetKvStore());
94     if (delegate == nullptr) {
95         MST_LOG("%s GetKvStore failed! delegate nullptr.", TAG.c_str());
96         delete manager;
97         manager = nullptr;
98         return nullptr;
99     }
100 
101     MST_LOG("%s GetKvStore success: %s %s %s %d", TAG.c_str(),
102         param.storeId.c_str(), param.appId.c_str(), param.userId.c_str(), option.createIfNecessary);
103     outManager = manager;
104     return const_cast<KvStoreNbDelegate *>(delegate);
105 }
106 
GetNbDelegateStatus(KvStoreDelegateManager * & outManager,DBStatus & statusReturn,const DBParameters & param,const Option & optionParam)107 KvStoreNbDelegate* DistributedDBNbTestTools::GetNbDelegateStatus(KvStoreDelegateManager *&outManager,
108     DBStatus &statusReturn, const DBParameters &param, const Option &optionParam)
109 {
110     MST_LOG("GetNbDelegate isMemoryDb= %d, isEncryptedDb= %d", optionParam.isMemoryDb,
111         optionParam.isEncryptedDb);
112     SetDir(DistributedDBConstant::NB_DIRECTOR);
113     if (param.storeId.empty() || param.appId.empty() || param.userId.empty()) {
114         return nullptr;
115     }
116 
117     // define a Callback to hold the KvStoreNbDelegate and status.
118     DelegateMgrNbCallback delegateMgrCallback;
119     function<void(DBStatus, KvStoreNbDelegate*)> function
120         = bind(&DelegateMgrNbCallback::Callback, &delegateMgrCallback, _1, _2);
121 
122     // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg.
123     if (outManager != nullptr) {
124         delete outManager;
125         outManager = nullptr;
126     }
127     KvStoreDelegateManager *manager1 = new (std::nothrow) KvStoreDelegateManager(param.appId, param.userId);
128     if (manager1 == nullptr) {
129         return nullptr;
130     }
131     statusReturn = manager1->SetKvStoreConfig({ .dataDir = DistributedDBConstant::NB_DIRECTOR });
132     if (statusReturn != DBStatus::OK) {
133         MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), statusReturn);
134         delete manager1;
135         manager1 = nullptr;
136         return nullptr;
137     }
138 
139     KvStoreNbDelegate::Option option = TransferNbOptionType(optionParam);
140     // get kv store, then the Callback will save the status and delegate.
141     manager1->GetKvStore(param.storeId, option, function);
142     statusReturn = delegateMgrCallback.GetStatus();
143     if (statusReturn != DBStatus::OK) {
144         MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), statusReturn);
145         delete manager1;
146         manager1 = nullptr;
147         return nullptr;
148     }
149     const KvStoreNbDelegate* delegate = const_cast<KvStoreNbDelegate *>(delegateMgrCallback.GetKvStore());
150     if (delegate == nullptr) {
151         MST_LOG("%s GetKvStore failed! delegate nullptr.", TAG.c_str());
152         delete manager1;
153         manager1 = nullptr;
154         return nullptr;
155     }
156 
157     MST_LOG("%s GetKvStore success: %s %s %s %d", TAG.c_str(),
158         param.storeId.c_str(), param.appId.c_str(), param.userId.c_str(), option.createIfNecessary);
159     outManager = manager1;
160     return const_cast<KvStoreNbDelegate *>(delegate);
161 }
162 
GetNbDelegateStoresSuccess(KvStoreDelegateManager * & outManager,vector<KvStoreNbDelegate * > & outDelegateVec,const vector<string> & storeIds,const string & appId,const string & userId,const Option & optionParam)163 DBStatus DistributedDBNbTestTools::GetNbDelegateStoresSuccess(KvStoreDelegateManager *&outManager,
164     vector<KvStoreNbDelegate *> &outDelegateVec,
165     const vector<string> &storeIds, const string &appId, const string &userId, const Option &optionParam)
166 {
167     SetDir(DistributedDBConstant::NB_DIRECTOR);
168     unsigned long opCnt;
169     DBStatus status = DBStatus::OK;
170     for (opCnt = 0; opCnt < storeIds.size(); ++opCnt) {
171         if (storeIds[opCnt].empty() || appId.empty() || userId.empty()) {
172             return INVALID_ARGS;
173         }
174     }
175 
176     // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg.
177     KvStoreDelegateManager *manager = new (std::nothrow) KvStoreDelegateManager(appId, userId);
178     if (manager == nullptr) {
179         return DBStatus::DB_ERROR;
180     }
181     outDelegateVec.clear();
182     KvStoreNbDelegate::Option option = TransferNbOptionType(optionParam);
183     for (opCnt = 0; opCnt < storeIds.size(); ++opCnt) {
184         // define a Callback to hold the KvStoreNbDelegate and status.
185         DelegateMgrNbCallback delegateMgrCallback;
186         function<void(DBStatus, KvStoreNbDelegate*)> function
187             = bind(&DelegateMgrNbCallback::Callback, &delegateMgrCallback, _1, _2);
188 
189         status = manager->SetKvStoreConfig(DistributedDBConstant::CONFIG);
190         if (status != DBStatus::OK) {
191             MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status);
192             goto END;
193         }
194 
195         // get kv store, then the Callback will save the status and delegate.
196         manager->GetKvStore(storeIds[opCnt], option, function);
197         status = delegateMgrCallback.GetStatus();
198         if (status != DBStatus::OK) {
199             MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), status);
200             goto END;
201         }
202         const KvStoreNbDelegate *delegate = const_cast<KvStoreNbDelegate *>(delegateMgrCallback.GetKvStore());
203         if (delegate == nullptr) {
204             MST_LOG("%s GetKvStore failed! delegate nullptr.", TAG.c_str());
205             goto END;
206         }
207         outDelegateVec.push_back(const_cast<KvStoreNbDelegate *>(delegate));
208     }
209     outManager = manager;
210     return OK;
211 END:
212     delete manager;
213     manager = nullptr;
214     return status;
215 }
216 
TransferNbOptionType(const Option & optionParam)217 KvStoreNbDelegate::Option DistributedDBNbTestTools::TransferNbOptionType(const Option &optionParam)
218 {
219     KvStoreNbDelegate::Option option;
220     option.createIfNecessary = optionParam.createIfNecessary;
221     option.isMemoryDb = optionParam.isMemoryDb;
222     option.isEncryptedDb = optionParam.isEncryptedDb;
223     option.cipher = optionParam.cipher;
224 #ifdef RELEASE_MODE_V2
225     option.schema = optionParam.schema;
226 #endif // endif of RELEASE_MODE_V2
227     (void)option.passwd.SetValue(optionParam.passwd.data(), optionParam.passwd.size());
228 #ifdef RELEASE_MODE_V3
229     option.secOption.securityLabel = optionParam.secOption.securityLabel;
230     option.secOption.securityFlag = optionParam.secOption.securityFlag;
231     option.observer = optionParam.observer;
232     option.key = optionParam.key;
233     option.mode = optionParam.mode;
234     option.conflictType = optionParam.conflictType;
235     option.notifier = optionParam.notifier;
236     option.conflictResolvePolicy = optionParam.conflictResolvePolicy;
237     option.isNeedIntegrityCheck = optionParam.isNeedIntegrityCheck;
238     option.isNeedRmCorruptedDb = optionParam.isNeedRmCorruptedDb;
239     option.isNeedCompressOnSync = optionParam.isNeedCompressOnSync;
240     option.compressionRate = optionParam.compressionRate;
241 #endif // end of RELEASE_MODE_V3
242     return option;
243 }
244 
245 // this static method is to compare if the two Value has the same data.
isValueEquals(const DistributedDB::Value & v1,const DistributedDB::Value & v2)246 bool DistributedDBNbTestTools::isValueEquals(const DistributedDB::Value &v1, const DistributedDB::Value &v2)
247 {
248     // just return false if the sizes are not the same.
249     if (v1.size() != v2.size()) {
250         return false;
251     }
252 
253     // compare two Values char by char.
254     return v1 == v2;
255 }
256 
Get(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key,DistributedDB::Value & value)257 DistributedDB::DBStatus DistributedDBNbTestTools::Get(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
258     const DistributedDB::Key &key, DistributedDB::Value &value)
259 {
260     return kvStoreNbDelegate.Get(key, value);
261 }
262 
GetEntries(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & keyPrefix,std::vector<DistributedDB::Entry> & entries)263 DistributedDB::DBStatus DistributedDBNbTestTools::GetEntries(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
264     const DistributedDB::Key &keyPrefix, std::vector<DistributedDB::Entry> &entries)
265 {
266     return kvStoreNbDelegate.GetEntries(keyPrefix, entries);
267 }
268 
Put(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key,const DistributedDB::Value & value,bool isNeedRetry,int waitTime)269 DistributedDB::DBStatus DistributedDBNbTestTools::Put(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
270     const DistributedDB::Key &key, const DistributedDB::Value &value, bool isNeedRetry, int waitTime)
271 {
272     if (isNeedRetry) {
273         DBStatus status = kvStoreNbDelegate.Put(key, value);
274         if (status != OK && waitTime-- > 0) {
275             MST_LOG("put records status: %d, and retry!", status);
276             return DistributedDBNbTestTools::Put(kvStoreNbDelegate, key, value, isNeedRetry, waitTime);
277         } else {
278             return status;
279         }
280     }
281     return kvStoreNbDelegate.Put(key, value);
282 }
283 
PutBatch(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const std::vector<DistributedDB::Entry> & entries,bool isNeedRetry)284 DistributedDB::DBStatus DistributedDBNbTestTools::PutBatch(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
285     const std::vector<DistributedDB::Entry> &entries, bool isNeedRetry)
286 {
287 #ifdef RELEASE_MODE_V2
288     DistributedDB::DBStatus status;
289     for (int cnt = 0; cnt < static_cast<int>(entries.size()); cnt += 128) { // 128 is the max records of deleteBatch.
290         auto last = std::min(static_cast<int>(entries.size()), cnt + 128); // 128 is the max records of deleteBatch.
291         std::vector<DistributedDB::Entry> entriesBatch(entries.begin() + cnt, entries.begin() + last);
292 
293         int retryTimes = 1000;
294         do {
295             status = kvStoreNbDelegate.PutBatch(entriesBatch);
296             if (status == OK) {
297                 break;
298             } else if (status != BUSY && status != OK) {
299                 return status;
300             }
301         } while (isNeedRetry && retryTimes-- > 0);
302     }
303     return status;
304 #else
305     MST_LOG("[DistributedDBNbTestTools::PutBatch] is NeedRetry is %d", isNeedRetry);
306     DBStatus status;
307     for (const auto &iter : entries) {
308         status = kvStoreNbDelegate.Put(iter.key, iter.value);
309         if (status != OK) {
310             return status;
311         }
312     }
313     return DBStatus::OK;
314 #endif // endif of RELEASE_MODE_V2
315 }
316 
Delete(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key)317 DistributedDB::DBStatus DistributedDBNbTestTools::Delete(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
318     const DistributedDB::Key &key)
319 {
320     return kvStoreNbDelegate.Delete(key);
321 }
322 
DeleteBatch(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const std::vector<DistributedDB::Key> & keys,bool isNeedRetry)323 DistributedDB::DBStatus DistributedDBNbTestTools::DeleteBatch(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
324     const std::vector<DistributedDB::Key> &keys, bool isNeedRetry)
325 {
326 #ifdef RELEASE_MODE_V2
327     DistributedDB::DBStatus status;
328     for (int cnt = 0; cnt < static_cast<int>(keys.size()); cnt = cnt + 128) { // 128 is the max records of deleteBatch.
329         auto last = std::min(static_cast<int>(keys.size()), cnt + 128); // 128 is the max records of deleteBatch.
330         std::vector<DistributedDB::Key> keysBatch(keys.begin() + cnt, keys.begin() + last);
331 
332         int retryTimes = 1000;
333         do {
334             status = kvStoreNbDelegate.DeleteBatch(keysBatch);
335             if (status == OK) {
336                 break;
337             } else if (status != BUSY && status != OK) {
338                 return status;
339             }
340         } while (isNeedRetry && retryTimes-- > 0);
341     }
342     return status;
343 #else
344     MST_LOG("[DistributedDBNbTestTools::DeleteBatch] is NeedRetry is %d", isNeedRetry);
345     DBStatus status;
346     for (const auto &iter : keys) {
347         status = kvStoreNbDelegate.Delete(iter);
348         if (status != OK) {
349             return status;
350         }
351     }
352     return DBStatus::OK;
353 #endif // endif of RELEASE_MODE_V2
354 }
355 
GetLocal(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key,DistributedDB::Value & value)356 DistributedDB::DBStatus DistributedDBNbTestTools::GetLocal(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
357     const DistributedDB::Key &key, DistributedDB::Value &value)
358 {
359     return kvStoreNbDelegate.GetLocal(key, value);
360 }
361 
PutLocal(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key,const DistributedDB::Value & value,bool isNeedRetry,int waitTime)362 DistributedDB::DBStatus DistributedDBNbTestTools::PutLocal(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
363     const DistributedDB::Key &key, const DistributedDB::Value &value, bool isNeedRetry, int waitTime)
364 {
365     if (isNeedRetry) {
366         DBStatus status = kvStoreNbDelegate.PutLocal(key, value);
367         if (status != OK && waitTime-- > 0) {
368             MST_LOG("PutLocal records status: %d, and retry!", status);
369             return DistributedDBNbTestTools::PutLocal(kvStoreNbDelegate, key, value, isNeedRetry, waitTime);
370         } else {
371             return status;
372         }
373     }
374     return kvStoreNbDelegate.PutLocal(key, value);
375 }
376 
PutLocalBatch(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const std::vector<DistributedDB::Entry> & entries)377 DistributedDB::DBStatus DistributedDBNbTestTools::PutLocalBatch(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
378     const std::vector<DistributedDB::Entry> &entries)
379 {
380 #ifdef RELEASE_MODE_V3
381     int cnt = 0;
382     std::vector<DistributedDB::Entry> entriesBatch;
383     DistributedDB::DBStatus status;
384     for (const auto &iter : entries) {
385         entriesBatch.push_back(iter);
386         cnt++;
387         if (cnt % BATCH_RECORDS == 0 || cnt == static_cast<int>(entries.size())) {
388             status = kvStoreNbDelegate.PutLocalBatch(entriesBatch);
389             if (status != DBStatus::OK) {
390                 return status;
391             }
392             entriesBatch.clear();
393         }
394     }
395     return DBStatus::OK;
396 #else
397     DistributedDB::DBStatus status;
398     for (auto entry : entries) {
399         status = kvStoreNbDelegate.PutLocal(entry.key, entry.value);
400         if (status != DBStatus::OK) {
401             return status;
402         }
403     }
404     return DBStatus::OK;
405 #endif
406 }
407 
DeleteLocal(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key)408 DistributedDB::DBStatus DistributedDBNbTestTools::DeleteLocal(
409     DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate, const DistributedDB::Key &key)
410 {
411     return kvStoreNbDelegate.DeleteLocal(key);
412 }
413 
DeleteLocalBatch(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const std::vector<DistributedDB::Key> & keys)414 DistributedDB::DBStatus DistributedDBNbTestTools::DeleteLocalBatch(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
415     const std::vector<DistributedDB::Key> &keys)
416 {
417 #ifdef RELEASE_MODE_V3
418     int cnt = 0;
419     std::vector<DistributedDB::Key> keysBatch;
420     DistributedDB::DBStatus status;
421     for (const auto &iter : keys) {
422         keysBatch.push_back(iter);
423         cnt++;
424         if (cnt % BATCH_RECORDS == 0 || cnt == static_cast<int>(keys.size())) {
425             status = kvStoreNbDelegate.DeleteLocalBatch(keysBatch);
426             if (status != DBStatus::OK) {
427                 return status;
428             }
429             keysBatch.clear();
430         }
431     }
432     return DBStatus::OK;
433 #else
434     DistributedDB::DBStatus status;
435     for (auto key : keys) {
436         status = kvStoreNbDelegate.DeleteLocal(key);
437         if (status != DBStatus::OK) {
438             return status;
439         }
440     }
441     return DBStatus::OK;
442 #endif
443 }
444 
RegisterObserver(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::Key & key,unsigned int mode,DistributedDB::KvStoreObserver * observer)445 DistributedDB::DBStatus DistributedDBNbTestTools::RegisterObserver(DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate,
446     const DistributedDB::Key &key, unsigned int mode, DistributedDB::KvStoreObserver *observer)
447 {
448     return kvStoreNbDelegate.RegisterObserver(key, mode, observer);
449 }
450 
UnRegisterObserver(DistributedDB::KvStoreNbDelegate & kvStoreNbDelegate,const DistributedDB::KvStoreObserver * observer)451 DistributedDB::DBStatus DistributedDBNbTestTools::UnRegisterObserver(
452     DistributedDB::KvStoreNbDelegate &kvStoreNbDelegate, const DistributedDB::KvStoreObserver *observer)
453 {
454     return kvStoreNbDelegate.UnRegisterObserver(observer);
455 }
456 
CloseNbAndRelease(KvStoreDelegateManager * & manager,KvStoreNbDelegate * & delegate)457 bool DistributedDBNbTestTools::CloseNbAndRelease(KvStoreDelegateManager *&manager, KvStoreNbDelegate *&delegate)
458 {
459     bool result = true;
460     if (delegate != nullptr && manager != nullptr) {
461         result = (manager->CloseKvStore(delegate) == OK);
462         delegate = nullptr;
463         delete manager;
464         manager = nullptr;
465     } else {
466         MST_LOG("Close Failed");
467         return false;
468     }
469     return result;
470 }
471 
EndCaseDeleteDB(DistributedDB::KvStoreDelegateManager * & manager,DistributedDB::KvStoreNbDelegate * & nbDelegate,const std::string base,bool isMemoryDb)472 bool EndCaseDeleteDB(DistributedDB::KvStoreDelegateManager *&manager,
473     DistributedDB::KvStoreNbDelegate *&nbDelegate, const std::string base, bool isMemoryDb)
474 {
475     bool isResult = true;
476     isResult = (manager->CloseKvStore(nbDelegate) == OK);
477     MST_LOG("CloseKvStore result:%d", isResult);
478     nbDelegate = nullptr;
479 
480     if (!isMemoryDb) {
481         isResult = isResult && (manager->DeleteKvStore(base) == OK);
482     }
483     MST_LOG("DeleteKvStore result:%d", isResult);
484     delete manager;
485     manager = nullptr;
486     return isResult;
487 }
488 
NotifyCallBack(const DistributedDB::KvStoreNbConflictData & data,std::vector<ConflictData> * & conflictData)489 void ConflictNbCallback::NotifyCallBack(const DistributedDB::KvStoreNbConflictData &data,
490     std::vector<ConflictData> *&conflictData)
491 {
492     MST_LOG("[ConflictCallback] Calling CallBack...");
493     Key key;
494     Value oldValue;
495     Value newValue;
496     data.GetKey(key);
497     data.GetValue(KvStoreNbConflictData::ValueType::OLD_VALUE, oldValue);
498     data.GetValue(KvStoreNbConflictData::ValueType::NEW_VALUE, newValue);
499     conflictData->push_back({data.GetType(), key, oldValue, newValue,
500         data.IsDeleted(KvStoreNbConflictData::ValueType::OLD_VALUE),
501         data.IsDeleted(KvStoreNbConflictData::ValueType::NEW_VALUE),
502         data.IsNative(KvStoreNbConflictData::ValueType::OLD_VALUE),
503         data.IsNative(KvStoreNbConflictData::ValueType::NEW_VALUE)});
504 }
505 
ModifyDatabaseFile(const std::string & fileDir)506 bool DistributedDBNbTestTools::ModifyDatabaseFile(const std::string &fileDir)
507 {
508     MST_LOG("Modify file:%s", fileDir.c_str());
509     std::fstream dataFile(fileDir, std::fstream::binary | std::fstream::out | std::fstream::in);
510     if (!dataFile.is_open()) {
511         MST_LOG("Open the database file failed");
512         return false;
513     }
514 
515     if (!dataFile.seekg(0, std::fstream::end)) {
516         return false;
517     }
518 
519     uint64_t fileSize;
520     std::ios::pos_type pos = dataFile.tellg();
521     if (pos < 0) {
522         return false;
523     } else {
524         fileSize = static_cast<uint64_t>(pos);
525         if (fileSize < 1024) { // the least page size is 1024 bytes.
526             MST_LOG("Invalid database file:%lld.", static_cast<long long>(fileSize));
527             return false;
528         }
529     }
530 
531     uint32_t currentCount = 0x1F1F1F1F; // add the random value to corrupt the head.
532     if (!dataFile.seekp(0)) {
533         return false;
534     }
535     for (uint32_t i = 0; i < pos / sizeof(uint32_t); i++) {
536         if (!dataFile.write(reinterpret_cast<char *>(&currentCount), sizeof(uint32_t))) {
537             return false;
538         }
539     }
540     dataFile.flush();
541     dataFile.close();
542     return true;
543 }
GetKvNbStoreDirectory(const DBParameters & param,const std::string & dbFilePath,const std::string & dbDir)544 std::string DistributedDBNbTestTools::GetKvNbStoreDirectory(const DBParameters &param, const std::string &dbFilePath,
545     const std::string &dbDir)
546 {
547     std::string identifier = param.userId + "-" + param.appId + "-" + param.storeId;
548     std::string identifierName = TransferStringToHashHexString(identifier);
549     std::string filePath = dbDir + identifierName + "/" + dbFilePath;
550     return filePath;
551 }
MoveToNextFromBegin(KvStoreResultSet & resultSet,const vector<DistributedDB::Entry> & entries,int recordCnt)552 bool DistributedDBNbTestTools::MoveToNextFromBegin(KvStoreResultSet &resultSet,
553     const vector<DistributedDB::Entry> &entries, int recordCnt)
554 {
555     bool result = (static_cast<int>(entries.size()) >= recordCnt);
556     if (!result) {
557         MST_LOG("entries.size()) < recordCnt!!!");
558         return result;
559     }
560     Entry entry;
561     int positionGot;
562     for (int position = -1; position < recordCnt; ++position) { // the first pos after getentries is -1.
563         bool expectRes = resultSet.MoveToNext();
564         if (position < (recordCnt - 1)) {
565             result = result && expectRes;
566         } else {
567             result = result && (!expectRes);
568         }
569         if (!result) {
570             MST_LOG("resultSet.MoveToNext() doesn't meet expectations!!!");
571             break;
572         }
573         positionGot = position + 1;
574         result = result && (resultSet.GetPosition() == positionGot);
575         if (!result) {
576             MST_LOG("resultSet.GetPosition() != positionGot!!!");
577             break;
578         }
579         if (position < (recordCnt - 1)) {
580             result = result && (resultSet.GetEntry(entry) == OK);
581             if (!result) {
582                 MST_LOG("resultSet.GetEntry() != OK");
583                 break;
584             }
585             result = result && (entry.key == entries[positionGot].key) && (entry.value == entries[positionGot].value);
586             if (!result) {
587                 MST_LOG("entry != entries[positionGot]");
588                 break;
589             }
590         } else {
591             result = result && (resultSet.GetEntry(entry) == NOT_FOUND);
592         }
593     }
594     return result;
595 }
596 
GetResourceDir()597 std::string DistributedDBNbTestTools::GetResourceDir()
598 {
599     std::string dir;
600     bool result = GetCurrentDir(dir);
601     if (!result) {
602         MST_LOG("[GetResourceDir] FAILED!");
603         return "";
604     }
605 #ifdef DB_DEBUG_ENV
606     dir = dir + "resource/";
607 #endif
608     return dir;
609 }
610 
GetCurrentDir(std::string & dir)611 bool DistributedDBNbTestTools::GetCurrentDir(std::string &dir)
612 {
613     static const int maxFileLength = 1024;
614     dir = "";
615     char buffer[maxFileLength] = {0};
616 #if defined(RUNNING_ON_LINUX)
617     int length = readlink("/proc/self/exe", buffer, maxFileLength);
618 #elif defined RUNNING_ON_WIN
619     int length = -1;
620     if (_getcwd(buffer, maxFileLength) != nullptr) {
621         length = strlen(buffer);
622     }
623 #endif
624     if (length < 0 || length >= maxFileLength) {
625         MST_LOG("read directory err length:%d", length);
626         return false;
627     }
628     MST_LOG("DIR = %s", buffer);
629     dir = buffer;
630     if (dir.rfind("/") != std::string::npos) {
631         dir.erase(dir.rfind("/") + 1);
632     }
633     if ((access(dir.c_str(), F_OK)) != E_OK) {
634         return false;
635     }
636     return true;
637 }
CheckNbNoRecord(KvStoreNbDelegate * & delegate,const Key & key,bool bIsLocalQuery)638 bool DistributedDBNbTestTools::CheckNbNoRecord(KvStoreNbDelegate *&delegate, const Key &key, bool bIsLocalQuery)
639 {
640     Value realValue;
641     bool result = true;
642     DBStatus status;
643     if (!bIsLocalQuery) {
644         status = delegate->Get(key, realValue);
645     } else {
646         status = delegate->GetLocal(key, realValue);
647     }
648     result = result && (status == NOT_FOUND);
649     if (!result) {
650         MST_LOG("[DistributedDBNbTestTools] bIsLocalQuery:%d, status: %d, realValue.size() is: %zd",
651             bIsLocalQuery, status, realValue.size());
652         return result;
653     }
654     return (realValue.size() == 0);
655 }
656 
CheckNbRecord(KvStoreNbDelegate * & delegate,const Key & key,const Value & value,bool bIsLocalQuery)657 bool DistributedDBNbTestTools::CheckNbRecord(KvStoreNbDelegate *&delegate,
658     const Key &key, const Value &value, bool bIsLocalQuery)
659 {
660     Value realValue;
661     bool result = true;
662     if (!bIsLocalQuery) {
663         if (value.empty()) {
664             return (delegate->Get(key, realValue) == NOT_FOUND);
665         } else {
666             result = result && (delegate->Get(key, realValue) == OK);
667         }
668     } else {
669         if (value.empty()) {
670             return (delegate->GetLocal(key, realValue) == NOT_FOUND);
671         } else {
672             result = result && (delegate->GetLocal(key, realValue) == OK);
673         }
674     }
675 
676     if (!result) {
677         MST_LOG("[DistributedDBNbTestTools] Get Record failed");
678         return result;
679     }
680     result = result && (realValue == value);
681     if (!result) {
682         string realString(realValue.begin(), realValue.end());
683         MST_LOG("[DistributedDBNbTestTools] check the value(LocalQuery:%d) failed, and the realGetValue is %s",
684             bIsLocalQuery, realString.c_str());
685         return result;
686     }
687     return result;
688 }
CorruptNewCallBack(const std::string & appId,const std::string & userId,const std::string & storeId,DistributedDB::KvStoreDelegateManager * & manager,CallBackParam & pathResult)689 void KvStoreNbCorruptInfo::CorruptNewCallBack(const std::string &appId, const std::string &userId,
690     const std::string &storeId, DistributedDB::KvStoreDelegateManager *&manager, CallBackParam &pathResult)
691 {
692     MST_LOG("Begin to recover the corrupt DB.");
693     manager->DeleteKvStore(storeId);
694     delete manager;
695     manager = nullptr;
696     DBParameters param(storeId, appId, userId);
697     KvStoreNbDelegate *delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(manager, param, g_option);
698     if (manager == nullptr || delegate == nullptr) {
699         MST_LOG("[KvStoreNbCorruptInfo::CorruptNewCallBack] Get delegate or manager failed!");
700         pathResult.result = false;
701         return;
702     } else {
703         if (delegate->Import(pathResult.path, NULL_PASSWD) != OK) {
704             MST_LOG("[KvStoreNbCorruptInfo::CorruptNewCallBack] Import failed!");
705             pathResult.result = false;
706         }
707         if (manager->CloseKvStore(delegate) != OK) {
708             MST_LOG("[KvStoreNbCorruptInfo::CorruptNewCallBack] CloseKvStore(delegate) failed!");
709             pathResult.result = false;
710         }
711     }
712     delegate = nullptr;
713     delete manager;
714     manager = nullptr;
715 }
716 
CorruptCallBackOfImport(const std::string & appId,const std::string & userId,const std::string & storeId,DistributedDB::KvStoreNbDelegate * & delegate,CallBackParam & pathResult)717 void KvStoreNbCorruptInfo::CorruptCallBackOfImport(const std::string &appId, const std::string &userId,
718     const std::string &storeId, DistributedDB::KvStoreNbDelegate *&delegate, CallBackParam &pathResult)
719 {
720     MST_LOG("Begin to Import the recover db files.");
721     MST_LOG("The corrupt Db is %s, %s, %s", appId.c_str(), userId.c_str(), storeId.c_str());
722     CipherPassword password;
723     (void)password.SetValue(FILE_PASSWD_VECTOR_1.data(), FILE_PASSWD_VECTOR_1.size());
724     if (delegate->Import(pathResult.path, password) != OK) {
725         MST_LOG("[KvStoreNbCorruptInfo::CorruptCallBackOfImport] Import failed!");
726         pathResult.result = false;
727     }
728 }
729 
CorruptCallBackOfExport(const std::string & appId,const std::string & userId,const std::string & storeId,DistributedDB::KvStoreNbDelegate * & delegate,CallBackParam & pathResult)730 void KvStoreNbCorruptInfo::CorruptCallBackOfExport(const std::string &appId, const std::string &userId,
731     const std::string &storeId, DistributedDB::KvStoreNbDelegate *&delegate, CallBackParam &pathResult)
732 {
733     MST_LOG("The corrupt Db is %s, %s, %s", appId.c_str(), userId.c_str(), storeId.c_str());
734     MST_LOG("Begin to Export the DB data.");
735     if (delegate->Export(pathResult.path, NULL_PASSWD) != INVALID_PASSWD_OR_CORRUPTED_DB) {
736         MST_LOG("[KvStoreNbCorruptInfo::CorruptCallBackOfExport] Export failed!");
737         pathResult.result = false;
738     }
739 }
740