• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include <gtest/gtest.h>
17 
18 #include "cloud/cloud_db_constant.h"
19 #include "db_base64_utils.h"
20 #include "distributeddb_data_generate_unit_test.h"
21 #include "distributeddb_tools_unit_test.h"
22 #include "kv_virtual_device.h"
23 #include "kv_store_nb_delegate.h"
24 #include "kv_store_nb_delegate_impl.h"
25 #include "platform_specific.h"
26 #include "process_system_api_adapter_impl.h"
27 #include "virtual_communicator_aggregator.h"
28 #include "virtual_cloud_db.h"
29 #include "sqlite_utils.h"
30 using namespace testing::ext;
31 using namespace DistributedDB;
32 using namespace DistributedDBUnitTest;
33 using namespace std;
34 
35 namespace {
36 static std::string HWM_HEAD = "naturalbase_cloud_meta_sync_data_";
37 string g_testDir;
38 KvStoreDelegateManager g_mgr(APP_ID, USER_ID);
39 CloudSyncOption g_CloudSyncoption;
40 const std::string USER_ID_2 = "user2";
41 const std::string USER_ID_3 = "user3";
42 const Key KEY_1 = {'k', '1'};
43 const Key KEY_2 = {'k', '2'};
44 const Key KEY_3 = {'k', '3'};
45 const Value VALUE_1 = {'v', '1'};
46 const Value VALUE_2 = {'v', '2'};
47 const Value VALUE_3 = {'v', '3'};
48 class DistributedDBCloudKvStoreTest : public testing::Test {
49 public:
50     static void SetUpTestCase();
51     static void TearDownTestCase();
52     void SetUp();
53     void TearDown();
54     void InsertRecord(int num);
55     void SetDeviceId(const Key &key, const std::string &deviceId);
56     void SetFlag(const Key &key, LogInfoFlag flag);
57     int CheckFlag(const Key &key, LogInfoFlag flag);
58     int CheckLogTable(const std::string &deviceId);
59     int CheckWaterMark(const std::string &key);
60     int ChangeUserId(const std::string &deviceId, const std::string &wantUserId);
61     int ChangeHashKey(const std::string &deviceId);
62 protected:
63     DBStatus GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId, KvStoreNbDelegate::Option option,
64         bool invalidSchema = false);
65     void CloseKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId);
66     void BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option,
67         DBStatus expectSyncResult = OK);
68     void SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option);
69     bool CheckUserSyncInfo(const vector<std::string> users, const vector<DBStatus> userStatus,
70         const vector<Info> userExpectInfo);
71     static DataBaseSchema GetDataBaseSchema(bool invalidSchema);
72     std::shared_ptr<VirtualCloudDb> virtualCloudDb_ = nullptr;
73     std::shared_ptr<VirtualCloudDb> virtualCloudDb2_ = nullptr;
74     KvStoreConfig config_;
75     KvStoreNbDelegate* kvDelegatePtrS1_ = nullptr;
76     KvStoreNbDelegate* kvDelegatePtrS2_ = nullptr;
77     SyncProcess lastProcess_;
78     std::map<std::string, SyncProcess> lastSyncProcess_;
79     VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr;
80     KvVirtualDevice *deviceB_ = nullptr;
81 };
82 
SetUpTestCase()83 void DistributedDBCloudKvStoreTest::SetUpTestCase()
84 {
85     DistributedDBToolsUnitTest::TestDirInit(g_testDir);
86     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
87         LOGE("rm test db files error!");
88     }
89     RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo();
90     g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
91     g_CloudSyncoption.users.push_back(USER_ID);
92     g_CloudSyncoption.devices.push_back("cloud");
93 
94     string dir = g_testDir + "/single_ver";
95     DIR* dirTmp = opendir(dir.c_str());
96     if (dirTmp == nullptr) {
97         OS::MakeDBDirectory(dir);
98     } else {
99         closedir(dirTmp);
100     }
101 }
102 
TearDownTestCase()103 void DistributedDBCloudKvStoreTest::TearDownTestCase()
104 {
105     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
106         LOGE("rm test db files error!");
107     }
108 }
109 
SetUp()110 void DistributedDBCloudKvStoreTest::SetUp()
111 {
112     DistributedDBToolsUnitTest::PrintTestCaseInfo();
113     config_.dataDir = g_testDir;
114     /**
115      * @tc.setup: create virtual device B and C, and get a KvStoreNbDelegate as deviceA
116      */
117     virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
118     virtualCloudDb2_ = std::make_shared<VirtualCloudDb>();
119     g_mgr.SetKvStoreConfig(config_);
120     KvStoreNbDelegate::Option option1;
121     ASSERT_EQ(GetKvStore(kvDelegatePtrS1_, STORE_ID_1, option1), OK);
122     // set aggregator after get store1, only store2 can sync with p2p
123     communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator();
124     ASSERT_TRUE(communicatorAggregator_ != nullptr);
125     RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_);
126     KvStoreNbDelegate::Option option2;
127     ASSERT_EQ(GetKvStore(kvDelegatePtrS2_, STORE_ID_2, option2), OK);
128 
129     deviceB_ = new (std::nothrow) KvVirtualDevice("DEVICE_B");
130     ASSERT_TRUE(deviceB_ != nullptr);
131     auto syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface();
132     ASSERT_TRUE(syncInterfaceB != nullptr);
133     ASSERT_EQ(deviceB_->Initialize(communicatorAggregator_, syncInterfaceB), E_OK);
134 }
135 
TearDown()136 void DistributedDBCloudKvStoreTest::TearDown()
137 {
138     CloseKvStore(kvDelegatePtrS1_, STORE_ID_1);
139     CloseKvStore(kvDelegatePtrS2_, STORE_ID_2);
140     virtualCloudDb_ = nullptr;
141     virtualCloudDb2_ = nullptr;
142     if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) {
143         LOGE("rm test db files error!");
144     }
145 
146     if (deviceB_ != nullptr) {
147         delete deviceB_;
148         deviceB_ = nullptr;
149     }
150 
151     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
152     communicatorAggregator_ = nullptr;
153     RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr);
154 }
155 
BlockSync(KvStoreNbDelegate * delegate,DBStatus expectDBStatus,CloudSyncOption option,DBStatus expectSyncResult)156 void DistributedDBCloudKvStoreTest::BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus,
157     CloudSyncOption option, DBStatus expectSyncResult)
158 {
159     if (delegate == nullptr) {
160         return;
161     }
162     std::mutex dataMutex;
163     std::condition_variable cv;
164     bool finish = false;
165     SyncProcess last;
166     auto callback = [expectDBStatus, &last, &cv, &dataMutex, &finish, &option](const std::map<std::string,
167         SyncProcess> &process) {
168         size_t notifyCnt = 0;
169         for (const auto &item: process) {
170             LOGD("user = %s, status = %d", item.first.c_str(), item.second.process);
171             if (item.second.process != DistributedDB::FINISHED) {
172                 continue;
173             }
174             EXPECT_EQ(item.second.errCode, expectDBStatus);
175             {
176                 std::lock_guard<std::mutex> autoLock(dataMutex);
177                 notifyCnt++;
178                 std::set<std::string> userSet(option.users.begin(), option.users.end());
179                 if (notifyCnt == userSet.size()) {
180                     finish = true;
181                     last = item.second;
182                     cv.notify_one();
183                 }
184             }
185         }
186     };
187     auto actualRet = delegate->Sync(option, callback);
188     EXPECT_EQ(actualRet, expectSyncResult);
189     if (actualRet == OK) {
190         std::unique_lock<std::mutex> uniqueLock(dataMutex);
191         cv.wait(uniqueLock, [&finish]() {
192             return finish;
193         });
194     }
195     lastProcess_ = last;
196 }
197 
GetDataBaseSchema(bool invalidSchema)198 DataBaseSchema DistributedDBCloudKvStoreTest::GetDataBaseSchema(bool invalidSchema)
199 {
200     DataBaseSchema schema;
201     TableSchema tableSchema;
202     tableSchema.name = invalidSchema ? "invalid_schema_name" : CloudDbConstant::CLOUD_KV_TABLE_NAME;
203     Field field;
204     field.colName = CloudDbConstant::CLOUD_KV_FIELD_KEY;
205     field.type = TYPE_INDEX<std::string>;
206     field.primary = true;
207     tableSchema.fields.push_back(field);
208     field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE;
209     field.primary = false;
210     tableSchema.fields.push_back(field);
211     field.colName = CloudDbConstant::CLOUD_KV_FIELD_ORI_DEVICE;
212     tableSchema.fields.push_back(field);
213     field.colName = CloudDbConstant::CLOUD_KV_FIELD_VALUE;
214     tableSchema.fields.push_back(field);
215     field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME;
216     field.type = TYPE_INDEX<int64_t>;
217     tableSchema.fields.push_back(field);
218     schema.tables.push_back(tableSchema);
219     return schema;
220 }
221 
222 
GetKvStore(KvStoreNbDelegate * & delegate,const std::string & storeId,KvStoreNbDelegate::Option option,bool invalidSchema)223 DBStatus DistributedDBCloudKvStoreTest::GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId,
224     KvStoreNbDelegate::Option option, bool invalidSchema)
225 {
226     DBStatus openRet = OK;
227     g_mgr.GetKvStore(storeId, option, [&openRet, &delegate](DBStatus status, KvStoreNbDelegate *openDelegate) {
228         openRet = status;
229         delegate = openDelegate;
230     });
231     EXPECT_EQ(openRet, OK);
232     EXPECT_NE(delegate, nullptr);
233 
234     std::map<std::string, std::shared_ptr<ICloudDb>> cloudDbs;
235     cloudDbs[USER_ID] = virtualCloudDb_;
236     cloudDbs[USER_ID_2] = virtualCloudDb2_;
237     delegate->SetCloudDB(cloudDbs);
238     std::map<std::string, DataBaseSchema> schemas;
239     schemas[USER_ID] = GetDataBaseSchema(invalidSchema);
240     schemas[USER_ID_2] = GetDataBaseSchema(invalidSchema);
241     return delegate->SetCloudDbSchema(schemas);
242 }
243 
CloseKvStore(KvStoreNbDelegate * & delegate,const std::string & storeId)244 void DistributedDBCloudKvStoreTest::CloseKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId)
245 {
246     if (delegate != nullptr) {
247         ASSERT_EQ(g_mgr.CloseKvStore(delegate), OK);
248         delegate = nullptr;
249         DBStatus status = g_mgr.DeleteKvStore(storeId);
250         LOGD("delete kv store status %d store %s", status, storeId.c_str());
251         ASSERT_EQ(status, OK);
252     }
253 }
254 
SyncAndGetProcessInfo(KvStoreNbDelegate * delegate,CloudSyncOption option)255 void DistributedDBCloudKvStoreTest::SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option)
256 {
257     if (delegate == nullptr) {
258         return;
259     }
260     std::mutex dataMutex;
261     std::condition_variable cv;
262     bool isFinish = false;
263     vector<std::map<std::string, SyncProcess>> lists;
264     auto callback = [&cv, &dataMutex, &isFinish, &option, &lists](const std::map<std::string, SyncProcess> &process) {
265         size_t notifyCnt = 0;
266         for (const auto &item: process) {
267             LOGD("user = %s, status = %d", item.first.c_str(), item.second.process);
268             if (item.second.process != DistributedDB::FINISHED) {
269                 continue;
270             }
271             {
272                 std::lock_guard<std::mutex> autoLock(dataMutex);
273                 notifyCnt++;
274                 std::set<std::string> userSet(option.users.begin(), option.users.end());
275                 if (notifyCnt == userSet.size()) {
276                     isFinish = true;
277                     cv.notify_one();
278                 }
279                 lists.push_back(process);
280             }
281         }
282     };
283     auto ret = delegate->Sync(option, callback);
284     EXPECT_EQ(ret, OK);
285     if (ret == OK) {
286         std::unique_lock<std::mutex> uniqueLock(dataMutex);
287         cv.wait(uniqueLock, [&isFinish]() {
288             return isFinish;
289         });
290     }
291     lastSyncProcess_ = lists.back();
292 }
293 
CheckUserSyncInfo(const vector<std::string> users,const vector<DBStatus> userStatus,const vector<Info> userExpectInfo)294 bool DistributedDBCloudKvStoreTest::CheckUserSyncInfo(const vector<std::string> users,
295     const vector<DBStatus> userStatus, const vector<Info> userExpectInfo)
296 {
297     uint32_t idx = 0;
298     for (auto &it: lastSyncProcess_) {
299         if ((idx >= users.size()) || (idx >= userStatus.size()) || (idx >= userExpectInfo.size())) {
300             return false;
301         }
302         string user = it.first;
303         if (user.compare(0, user.length(), users[idx]) != 0) {
304             return false;
305         }
306         SyncProcess actualSyncProcess = it.second;
307         EXPECT_EQ(actualSyncProcess.process, FINISHED);
308         EXPECT_EQ(actualSyncProcess.errCode, userStatus[idx]);
309         for (const auto &table : actualSyncProcess.tableProcess) {
310             EXPECT_EQ(table.second.upLoadInfo.total, userExpectInfo[idx].total);
311             EXPECT_EQ(table.second.upLoadInfo.successCount, userExpectInfo[idx].successCount);
312             EXPECT_EQ(table.second.upLoadInfo.insertCount, userExpectInfo[idx].insertCount);
313             EXPECT_EQ(table.second.upLoadInfo.failCount, userExpectInfo[idx].failCount);
314         }
315         idx++;
316     }
317     return true;
318 }
319 
320 /**
321  * @tc.name: SyncOptionCheck001
322  * @tc.desc: Test sync without user.
323  * @tc.type: FUNC
324  * @tc.require:
325  * @tc.author: liaoyonghuang
326  */
327 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck001, TestSize.Level0)
328 {
329     /**
330      * @tc.steps:step1. Device 1 inserts a piece of data.
331      * @tc.expected: step1 OK.
332      */
333     Key key = {'k'};
334     Value value = {'v'};
335     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
336     /**
337      * @tc.steps:step2. Set option without user, and attempt to sync
338      * @tc.expected: step2 return INVALID_ARGS.
339      */
340     CloudSyncOption option;
341     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
342     option.devices.push_back("cloud");
343     BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS);
344     /**
345      * @tc.steps:step3. Device 2 sync and attempt to get data.
346      * @tc.expected: step3 sync OK but data NOT_FOUND.
347      */
348     BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption);
349     Value actualValue;
350     EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND);
351 }
352 
353 /**
354  * @tc.name: SyncOptionCheck002
355  * @tc.desc: Test sync with invalid waitTime.
356  * @tc.type: FUNC
357  * @tc.require:
358  * @tc.author: liaoyonghuang
359  */
360 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck002, TestSize.Level0)
361 {
362     /**
363      * @tc.steps:step1. Device 1 inserts a piece of data.
364      * @tc.expected: step1 OK.
365      */
366     Key key = {'k'};
367     Value value = {'v'};
368     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
369     /**
370      * @tc.steps:step2. Set invalid waitTime of sync option and sync.
371      * @tc.expected: step2 return INVALID_ARGS.
372      */
373     CloudSyncOption option;
374     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
375     option.users.push_back(USER_ID);
376     option.devices.push_back("cloud");
377     option.waitTime = -2; // -2 is invalid waitTime.
378     BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS);
379     /**
380      * @tc.steps:step3. Device 2 sync and attempt to get data.
381      * @tc.expected: step3 sync OK but data NOT_FOUND.
382      */
383     BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption);
384     Value actualValue;
385     EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND);
386 }
387 
388 /**
389  * @tc.name: SyncOptionCheck003
390  * @tc.desc: Test sync with users which have not been sync to cloud.
391  * @tc.type: FUNC
392  * @tc.require:
393  * @tc.author: liaoyonghuang
394  */
395 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck003, TestSize.Level0)
396 {
397     /**
398      * @tc.steps:step1. Device 1 inserts a piece of data.
399      * @tc.expected: step1 OK.
400      */
401     Key key = {'k'};
402     Value value = {'v'};
403     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
404     /**
405      * @tc.steps:step2. Set user1 and user3 to option and sync.
406      * @tc.expected: step2 return INVALID_ARGS.
407      */
408     CloudSyncOption option;
409     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
410     option.users.push_back(USER_ID);
411     option.users.push_back(USER_ID_3);
412     option.devices.push_back("cloud");
413     BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS);
414     /**
415      * @tc.steps:step3. Device 2 sync and attempt to get data.
416      * @tc.expected: step3 sync OK but data NOT_FOUND.
417      */
418     BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption);
419     Value actualValue;
420     EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND);
421 }
422 
423 /**
424  * @tc.name: SyncOptionCheck004
425  * @tc.desc: Test sync with user when schema is not same.
426  * @tc.type: FUNC
427  * @tc.require:
428  * @tc.author: caihaoting
429  */
430 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck004, TestSize.Level0)
431 {
432     /**
433      * @tc.steps:step1. Device 1 inserts a piece of data.
434      * @tc.expected: step1 OK.
435      */
436     Key key = {'k'};
437     Value value = {'v'};
438     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
439     /**
440      * @tc.steps:step2. Set user1 to option and user2 to schema and sync.
441      * @tc.expected: step2 return SCHEMA_MISMATCH.
442      */
443     CloudSyncOption option;
444     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
445     option.users.push_back(USER_ID);
446     option.devices.push_back("cloud");
447     std::map<std::string, DataBaseSchema> schemas;
448     schemas[USER_ID_2] = GetDataBaseSchema(false);
449     kvDelegatePtrS1_->SetCloudDbSchema(schemas);
450     BlockSync(kvDelegatePtrS1_, OK, option, SCHEMA_MISMATCH);
451 }
452 
453 /**
454  * @tc.name: SyncOptionCheck005
455  * @tc.desc: Testing registration of observer exceeded the upper limit.
456  * @tc.type: FUNC
457  * @tc.require:
458  * @tc.author: liaoyonghuang
459  */
460 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck005, TestSize.Level0)
461 {
462     /**
463      * @tc.steps:step1. Register MAX_OBSERVER_COUNT observers.
464      * @tc.expected: step1 OK.
465      */
466     std::vector<KvStoreObserverUnitTest *> observerList;
467     for (int i = 0; i < DBConstant::MAX_OBSERVER_COUNT; i++) {
468         auto *observer = new (std::nothrow) KvStoreObserverUnitTest;
469         observerList.push_back(observer);
470         EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, observer), OK);
471     }
472     /**
473      * @tc.steps:step2. Register one more observer.
474      * @tc.expected: step2 Registration failed, return OVER_MAX_LIMITS.
475      */
476     auto *overMaxObserver = new (std::nothrow) KvStoreObserverUnitTest;
477     EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, overMaxObserver), OVER_MAX_LIMITS);
478     /**
479      * @tc.steps:step3. UnRegister all observers.
480      * @tc.expected: step3 OK.
481      */
482     EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(overMaxObserver), NOT_FOUND);
483     delete overMaxObserver;
484     overMaxObserver = nullptr;
485     for (auto &observer : observerList) {
486         EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(observer), OK);
487         delete observer;
488         observer = nullptr;
489     }
490 }
491 
492 /**
493  * @tc.name: SyncOptionCheck006
494  * @tc.desc: Test sync with schema db
495  * @tc.type: FUNC
496  * @tc.require:
497  * @tc.author: zhangqiquan
498  */
499 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck006, TestSize.Level0)
500 {
501     KvStoreNbDelegate::Option option;
502     option.schema = "{\"SCHEMA_VERSION\":\"1.0\","
503         "\"SCHEMA_MODE\":\"STRICT\","
504         "\"SCHEMA_DEFINE\":{"
505         "\"field_name1\":\"BOOL\","
506         "\"field_name2\":\"INTEGER, NOT NULL\""
507         "},"
508         "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2\"]}";
509     KvStoreNbDelegate *kvDelegatePtr = nullptr;
510     ASSERT_EQ(GetKvStore(kvDelegatePtr, STORE_ID_4, option), OK);
511     ASSERT_NE(kvDelegatePtr, nullptr);
512     BlockSync(kvDelegatePtr, NOT_SUPPORT, g_CloudSyncoption, NOT_SUPPORT);
513     EXPECT_EQ(g_mgr.CloseKvStore(kvDelegatePtr), OK);
514 }
515 
516 /**
517  * @tc.name: SyncOptionCheck007
518  * @tc.desc: Test sync with repetitive user.
519  * @tc.type: FUNC
520  * @tc.require:
521  * @tc.author: liaoyonghuang
522  */
523 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck007, TestSize.Level0)
524 {
525     /**
526      * @tc.steps:step1. Device 1 inserts a piece of data.
527      * @tc.expected: step1 OK.
528      */
529     Key key = {'k'};
530     Value value = {'v'};
531     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
532     /**
533      * @tc.steps:step2. Set user1 2 times to option sync.
534      * @tc.expected: step2 return OK.
535      */
536     CloudSyncOption option;
537     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
538     option.users.push_back(USER_ID);
539     option.users.push_back(USER_ID);
540     option.devices.push_back("cloud");
541     BlockSync(kvDelegatePtrS1_, OK, option, OK);
542 }
543 
544 /**
545  * @tc.name: SyncOptionCheck008
546  * @tc.desc: Test kc sync with query .
547  * @tc.type: FUNC
548  * @tc.require:
549  * @tc.author: luoguo
550  */
551 HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck008, TestSize.Level0)
552 {
553     /**
554      * @tc.steps:step1. Device 1 inserts a piece of data.
555      * @tc.expected: step1 OK.
556      */
557     Key key = {'k'};
558     Value value = {'v'};
559     ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
560     /**
561      * @tc.steps:step2. Set query to option sync.
562      * @tc.expected: step2 return OK.
563      */
564     std::set<Key> keys;
565     CloudSyncOption option;
566     option.query = Query::Select().InKeys(keys);
567     option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
568     option.users.push_back(USER_ID);
569     option.users.push_back(USER_ID);
570     option.devices.push_back("cloud");
571     BlockSync(kvDelegatePtrS1_, OK, option, OK);
572 }
573 
SetFlag(const Key & key,LogInfoFlag flag)574 void DistributedDBCloudKvStoreTest::SetFlag(const Key &key, LogInfoFlag flag)
575 {
576     sqlite3 *db_;
577     uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
578     std::string fileUrl = g_testDir + "/" \
579         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
580     ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr) == SQLITE_OK);
581     int errCode = E_OK;
582     std::string sql = "UPDATE sync_data SET flag=? WHERE Key=?";
583     sqlite3_stmt *statement = nullptr;
584     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
585     if (errCode != E_OK) {
586         SQLiteUtils::ResetStatement(statement, true, errCode);
587     }
588     ASSERT_EQ(errCode, E_OK);
589     errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, static_cast<int64_t>(flag)); // 1st arg.
590     ASSERT_EQ(errCode, E_OK);
591     errCode = SQLiteUtils::BindBlobToStatement(statement, 2, key, true); // 2nd arg.
592     ASSERT_EQ(errCode, E_OK);
593     if (errCode != E_OK) {
594         SQLiteUtils::ResetStatement(statement, true, errCode);
595     }
596     EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
597     SQLiteUtils::ResetStatement(statement, true, errCode);
598     EXPECT_EQ(errCode, E_OK);
599     sqlite3_close_v2(db_);
600 }
601 
CheckFlag(const Key & key,LogInfoFlag flag)602 int DistributedDBCloudKvStoreTest::CheckFlag(const Key &key, LogInfoFlag flag)
603 {
604     sqlite3 *db_;
605     uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
606     std::string fileUrl = g_testDir + "/" \
607         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
608     int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr);
609     if (errCode != E_OK) {
610         return NOT_FOUND;
611     }
612     std::string sql = "SELECT * FROM sync_data WHERE Key =? AND (flag=?)";
613     sqlite3_stmt *statement = nullptr;
614     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
615     if (errCode != E_OK) {
616         SQLiteUtils::ResetStatement(statement, true, errCode);
617         return NOT_FOUND;
618     }
619     std::vector<uint8_t> keyVec(key.begin(), key.end());
620     errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // 1st arg.
621     if (errCode != E_OK) {
622         SQLiteUtils::ResetStatement(statement, true, errCode);
623         return NOT_FOUND;
624     }
625     errCode = SQLiteUtils::BindInt64ToStatement(statement, 2, static_cast<int64_t>(flag)); // 2nd arg.
626     if (errCode != E_OK) {
627         SQLiteUtils::ResetStatement(statement, true, errCode);
628         return NOT_FOUND;
629     }
630     errCode = SQLiteUtils::StepWithRetry(statement);
631     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
632         SQLiteUtils::ResetStatement(statement, true, errCode);
633         sqlite3_close_v2(db_);
634         return NOT_FOUND; // cant find.
635     }
636     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
637         SQLiteUtils::ResetStatement(statement, true, errCode);
638         sqlite3_close_v2(db_);
639         return OK;
640     }
641     SQLiteUtils::ResetStatement(statement, true, errCode);
642     EXPECT_EQ(errCode, E_OK);
643     sqlite3_close_v2(db_);
644     return NOT_FOUND;
645 }
646 
CheckWaterMark(const std::string & user)647 int DistributedDBCloudKvStoreTest::CheckWaterMark(const std::string &user)
648 {
649     sqlite3 *db_;
650     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
651     std::string fileUrl = g_testDir + "/" \
652         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
653     int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr);
654     if (errCode != E_OK) {
655         return NOT_FOUND;
656     }
657     std::string sql;
658     if (user.empty()) {
659         sql = "SELECT * FROM meta_data WHERE KEY LIKE 'naturalbase_cloud_meta_sync_data_%'";
660     } else {
661         sql = "SELECT * FROM meta_data WHERE KEY =?;";
662     }
663     sqlite3_stmt *statement = nullptr;
664     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
665     if (errCode != E_OK) {
666         SQLiteUtils::ResetStatement(statement, true, errCode);
667         return NOT_FOUND;
668     }
669     if (!user.empty()) {
670         std::string waterMarkKey = HWM_HEAD + user;
671         std::vector<uint8_t> keyVec(waterMarkKey.begin(), waterMarkKey.end());
672         errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // only one arg.
673         if (errCode != E_OK) {
674             SQLiteUtils::ResetStatement(statement, true, errCode);
675             return NOT_FOUND;
676         }
677     }
678     errCode = SQLiteUtils::StepWithRetry(statement);
679     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
680         SQLiteUtils::ResetStatement(statement, true, errCode);
681         sqlite3_close_v2(db_);
682         return NOT_FOUND; // cant find.
683     }
684     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
685         SQLiteUtils::ResetStatement(statement, true, errCode);
686         sqlite3_close_v2(db_);
687         return OK;
688     }
689     SQLiteUtils::ResetStatement(statement, true, errCode);
690     EXPECT_EQ(errCode, E_OK);
691     sqlite3_close_v2(db_);
692     return NOT_FOUND;
693 }
694 
SetDeviceId(const Key & key,const std::string & deviceId)695 void DistributedDBCloudKvStoreTest::SetDeviceId(const Key &key, const std::string &deviceId)
696 {
697     sqlite3 *db_;
698     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
699     std::string fileUrl = g_testDir + "/" \
700         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
701     ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr) == SQLITE_OK);
702     int errCode = E_OK;
703     std::string sql = "UPDATE sync_data SET device=? WHERE Key=?";
704     sqlite3_stmt *statement = nullptr;
705     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
706     if (errCode != E_OK) {
707         SQLiteUtils::ResetStatement(statement, true, errCode);
708     }
709     ASSERT_EQ(errCode, E_OK);
710     std::string hashDevice = DBCommon::TransferHashString(deviceId);
711     std::vector<uint8_t> deviceIdVec(hashDevice.begin(), hashDevice.end());
712     int bindIndex = 1;
713     errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg.
714     ASSERT_EQ(errCode, E_OK);
715     if (errCode != E_OK) {
716         SQLiteUtils::ResetStatement(statement, true, errCode);
717     }
718     bindIndex++;
719     errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, key, true); // only one arg.
720     if (errCode != E_OK) {
721         SQLiteUtils::ResetStatement(statement, true, errCode);
722     }
723     EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
724     SQLiteUtils::ResetStatement(statement, true, errCode);
725     EXPECT_EQ(errCode, E_OK);
726     sqlite3_close_v2(db_);
727 }
728 
CheckLogTable(const std::string & deviceId)729 int DistributedDBCloudKvStoreTest::CheckLogTable(const std::string &deviceId)
730 {
731     sqlite3 *db_;
732     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
733     std::string fileUrl = g_testDir + "/" \
734         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
735     int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr);
736     if (errCode != E_OK) {
737         return NOT_FOUND;
738     }
739     std::string sql = "SELECT * FROM naturalbase_kv_aux_sync_data_log WHERE hash_key IN" \
740         "(SELECT hash_key FROM sync_data WHERE device =?);";
741     sqlite3_stmt *statement = nullptr;
742     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
743     if (errCode != E_OK) {
744         SQLiteUtils::ResetStatement(statement, true, errCode);
745         return NOT_FOUND;
746     }
747     std::string hashDevice = DBCommon::TransferHashString(deviceId);
748     std::vector<uint8_t> deviceIdVec(hashDevice.begin(), hashDevice.end());
749     errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg.
750     if (errCode != E_OK) {
751         SQLiteUtils::ResetStatement(statement, true, errCode);
752         return NOT_FOUND;
753     }
754     errCode = SQLiteUtils::StepWithRetry(statement);
755     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
756         SQLiteUtils::ResetStatement(statement, true, errCode);
757         sqlite3_close_v2(db_);
758         return NOT_FOUND; // cant find.
759     }
760     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
761         SQLiteUtils::ResetStatement(statement, true, errCode);
762         sqlite3_close_v2(db_);
763         return OK;
764     }
765     SQLiteUtils::ResetStatement(statement, true, errCode);
766     EXPECT_EQ(errCode, E_OK);
767     sqlite3_close_v2(db_);
768     return NOT_FOUND;
769 }
770 
ChangeUserId(const std::string & deviceId,const std::string & wantUserId)771 int DistributedDBCloudKvStoreTest::ChangeUserId(const std::string &deviceId, const std::string &wantUserId)
772 {
773     sqlite3 *db_;
774     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
775     std::string fileUrl = g_testDir + "/" \
776         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
777     int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr);
778     if (errCode != E_OK) {
779         return INVALID_ARGS;
780     }
781     std::string sql = "UPDATE naturalbase_kv_aux_sync_data_log SET userid =? WHERE hash_key IN" \
782         "(SELECT hash_key FROM sync_data WHERE device =? AND (flag=0x100));";
783     sqlite3_stmt *statement = nullptr;
784     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
785     if (errCode != E_OK) {
786         SQLiteUtils::ResetStatement(statement, true, errCode);
787         return INVALID_ARGS;
788     }
789     int bindIndex = 1;
790     errCode = SQLiteUtils::BindTextToStatement(statement, bindIndex, wantUserId); // only one arg.
791     if (errCode != E_OK) {
792         SQLiteUtils::ResetStatement(statement, true, errCode);
793         return INVALID_ARGS;
794     }
795     bindIndex++;
796     std::string hashDevice = DBCommon::TransferHashString(deviceId);
797     std::vector<uint8_t> deviceIdVec(hashDevice.begin(), hashDevice.end());
798     errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg.
799     if (errCode != E_OK) {
800         SQLiteUtils::ResetStatement(statement, true, errCode);
801         return INVALID_ARGS;
802     }
803     EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
804     SQLiteUtils::ResetStatement(statement, true, errCode);
805     EXPECT_EQ(errCode, E_OK);
806     sqlite3_close_v2(db_);
807     return INVALID_ARGS;
808 }
809 
ChangeHashKey(const std::string & deviceId)810 int DistributedDBCloudKvStoreTest::ChangeHashKey(const std::string &deviceId)
811 {
812     sqlite3 *db_;
813     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
814     std::string fileUrl = g_testDir + "/" \
815         "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db";
816     int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr);
817     if (errCode != E_OK) {
818         return INVALID_ARGS;
819     }
820     std::string updataLogTableSql = "UPDATE naturalbase_kv_aux_sync_data_log SET hash_Key ='99';";
821     sqlite3_stmt *statement = nullptr;
822     errCode = SQLiteUtils::GetStatement(db_, updataLogTableSql, statement);
823     if (errCode != E_OK) {
824         SQLiteUtils::ResetStatement(statement, true, errCode);
825         return INVALID_ARGS;
826     }
827     errCode = SQLiteUtils::StepWithRetry(statement);
828     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
829         SQLiteUtils::ResetStatement(statement, true, errCode);
830     }
831 
832     std::string sql = "UPDATE sync_data SET hash_Key ='99' WHERE device =? AND (flag=0x100);";
833     errCode = SQLiteUtils::GetStatement(db_, sql, statement);
834     if (errCode != E_OK) {
835         SQLiteUtils::ResetStatement(statement, true, errCode);
836         return INVALID_ARGS;
837     }
838     std::string hashDevice = DBCommon::TransferHashString(deviceId);
839     std::vector<uint8_t> deviceIdVec(hashDevice.begin(), hashDevice.end());
840     errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg.
841     if (errCode != E_OK) {
842         SQLiteUtils::ResetStatement(statement, true, errCode);
843         sqlite3_close_v2(db_);
844         return OK; // cant find.
845     }
846     EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE));
847     SQLiteUtils::ResetStatement(statement, true, errCode);
848     EXPECT_EQ(errCode, E_OK);
849     sqlite3_close_v2(db_);
850     return INVALID_ARGS;
851 }
852 
InsertRecord(int num)853 void DistributedDBCloudKvStoreTest::InsertRecord(int num)
854 {
855     for (int i = 0; i < num; i++) {
856         Key key;
857         key.push_back('k');
858         key.push_back('0' + i);
859         Value value;
860         value.push_back('k');
861         value.push_back('0' + i);
862         ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK);
863         BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption);
864         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
865         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
866     }
867 }
868 
869 /**
870  * @tc.name: RemoveDeviceTest001
871  * @tc.desc: remove all log table record with empty deviceId and FLAG_ONLY flag
872  * @tc.type: FUNC
873  * @tc.require:
874  * @tc.author: mazhao
875  */
876 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest001, TestSize.Level0)
877 {
878     /**
879      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0),
880      * (Key:k2, device:2, userId:0)
881      * * @tc.expected: step1. insert successfully
882     */
883     int recordNum = 3;
884     InsertRecord(recordNum);
885     for (int i = 0; i < recordNum; i++) {
886         Key key;
887         key.push_back('k');
888         key.push_back('0' + i);
889         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
890         SetDeviceId(key, std::to_string(i));
891         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
892     }
893     /**
894      * @tc.steps: step2. Check three Log record whether exist or not;
895      * * @tc.expected: step2. record exist
896     */
897     for (int i = 0; i < recordNum; i++) {
898         Key key;
899         key.push_back('k');
900         key.push_back('0' + i);
901         Value actualValue;
902         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
903         std::string deviceId = std::to_string(i);
904         EXPECT_EQ(CheckLogTable(deviceId), OK);
905         EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK);
906         EXPECT_EQ(CheckWaterMark(""), OK);
907     }
908     /**
909      * @tc.steps: step3. remove log data with empty deviceId.
910      * * @tc.expected: step3. remove OK, there are not user record exist in log table.
911     */
912     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), OK);
913     for (int i = 0; i < recordNum; i++) {
914         Key key;
915         key.push_back('k');
916         key.push_back('0' + i);
917         Value actualValue;
918         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
919         std::string deviceId = std::to_string(i);
920         EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND);
921         EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_LOCAL), OK);
922         EXPECT_EQ(CheckWaterMark(""), NOT_FOUND);
923     }
924 }
925 
926 /**
927  * @tc.name: RemoveDeviceTest002
928  * @tc.desc: remove all record with empty deviceId and FLAG_AND_DATA flag
929  * @tc.type: FUNC
930  * @tc.require:
931  * @tc.author: mazhao
932  */
933 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest002, TestSize.Level0)
934 {
935     /**
936      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0),
937      * (Key:k2, device:2, userId:0)
938      * * @tc.expected: step1. insert successfully
939     */
940     int recordNum = 3;
941     InsertRecord(recordNum);
942     for (int i = 0; i < recordNum; i++) {
943         Key key;
944         key.push_back('k');
945         key.push_back('0' + i);
946         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
947         SetDeviceId(key, std::to_string(i));
948         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
949     }
950     /**
951      * @tc.steps: step2. Check three Log record whether exist or not;
952      * * @tc.expected: step2. record exist
953     */
954     for (int i = 0; i < recordNum; i++) {
955         Key key;
956         key.push_back('k');
957         key.push_back('0' + i);
958         Value actualValue;
959         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
960         std::string deviceId = std::to_string(i);
961         EXPECT_EQ(CheckLogTable(deviceId), OK);
962         EXPECT_EQ(CheckWaterMark(""), OK);
963     }
964     /**
965      * @tc.steps: step3. remove log data with empty deviceId.
966      * * @tc.expected: step3. remove OK, there are not user record exist in log table.
967     */
968     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_AND_DATA), OK);
969     for (int i = 0; i < recordNum; i++) {
970         Key key;
971         key.push_back('k');
972         key.push_back('0' + i);
973         Value actualValue;
974         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND);
975         std::string deviceId = std::to_string(i);
976         EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND);
977         EXPECT_EQ(CheckWaterMark(""), NOT_FOUND);
978     }
979 }
980 
981 /**
982  * @tc.name: RemoveDeviceTest003
983  * @tc.desc: remove record with deviceId
984  * @tc.type: FUNC
985  * @tc.require:
986  * @tc.author: mazhao
987  */
988 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest003, TestSize.Level0)
989 {
990     /**
991      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0),
992      * (Key:k2, device:2, userId:0)
993      * * @tc.expected: step1. insert successfully
994     */
995     int recordNum = 3;
996     InsertRecord(recordNum);
997     for (int i = 0; i < recordNum; i++) {
998         Key key;
999         key.push_back('k');
1000         key.push_back('0' + i);
1001         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
1002         SetDeviceId(key, std::to_string(i));
1003         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1004     }
1005     /**
1006      * @tc.steps: step2. Check three Log record whether exist or not;
1007      * * @tc.expected: step2. record exist
1008     */
1009     for (int i = 0; i < recordNum; i++) {
1010         Key key;
1011         key.push_back('k');
1012         key.push_back('0' + i);
1013         Value actualValue;
1014         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1015         std::string deviceId = std::to_string(i);
1016         EXPECT_EQ(CheckLogTable(deviceId), OK);
1017         EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag become 0x2;
1018         EXPECT_EQ(CheckWaterMark(""), OK);
1019     }
1020     /**
1021      * @tc.steps: step3. remove "2" deviceId log data with FLAG_AND_DATA, remove "1" with FLAG_ONLY.
1022      * * @tc.expected: step3. remove OK
1023     */
1024     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("1", ClearMode::FLAG_ONLY), OK);
1025     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("2", ClearMode::FLAG_AND_DATA), OK);
1026     Key key1({'k', '1'});
1027     std::string deviceId1 = "1";
1028     Value actualValue;
1029     EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK);
1030     EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND);
1031     EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2;
1032     Key key2({'k', '2'});
1033     std::string deviceId2 = "2";
1034     EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND);
1035     EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND);
1036     EXPECT_EQ(CheckWaterMark(""), NOT_FOUND);
1037 }
1038 
1039 /**
1040  * @tc.name: RemoveDeviceTest004
1041  * @tc.desc: remove all record with userId and empty deviceId.
1042  * @tc.type: FUNC
1043  * @tc.require:
1044  * @tc.author: mazhao
1045  */
1046 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest004, TestSize.Level0)
1047 {
1048     /**
1049      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1),
1050      * (Key:k2, device:2, userId:2)
1051      * * @tc.expected: step1. insert successfully
1052     */
1053     int recordNum = 3;
1054     std::string userHead = "user";
1055     InsertRecord(recordNum);
1056     for (int i = 0; i < recordNum; i++) {
1057         Key key;
1058         key.push_back('k');
1059         key.push_back('0' + i);
1060         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
1061         SetDeviceId(key, std::to_string(i));
1062         ChangeUserId(std::to_string(i), userHead + std::to_string(i));
1063         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1064         EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK);
1065     }
1066     EXPECT_EQ(CheckWaterMark(userHead + "0"), OK);
1067     /**
1068      * @tc.steps: step2. Check three Log record whether exist or not;
1069      * * @tc.expected: step2. record exist
1070     */
1071     for (int i = 0; i < recordNum; i++) {
1072         Key key;
1073         key.push_back('k');
1074         key.push_back('0' + i);
1075         Value actualValue;
1076         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1077         std::string deviceId = std::to_string(i);
1078         EXPECT_EQ(CheckLogTable(deviceId), OK);
1079     }
1080     /**
1081      * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user2" userid with FLAG_ONLY.
1082      * * @tc.expected: step3. remove OK
1083     */
1084     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user0", ClearMode::FLAG_ONLY), OK);
1085     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user2", ClearMode::FLAG_AND_DATA), OK);
1086     Key key0({'k', '0'});
1087     std::string deviceId1 = "0";
1088     Value actualValue;
1089     EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK);
1090     EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND);
1091     EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2;
1092     EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND);
1093     Key key2({'k', '2'});
1094     std::string deviceId2 = "2";
1095     EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND);
1096     EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND);
1097 }
1098 
1099 /**
1100  * @tc.name: RemoveDeviceTest005
1101  * @tc.desc: remove record with userId and deviceId.
1102  * @tc.type: FUNC
1103  * @tc.require:
1104  * @tc.author: mazhao
1105  */
1106 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest005, TestSize.Level0)
1107 {
1108     /**
1109      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1),
1110      * (Key:k2, device:2, userId:2)
1111      * * @tc.expected: step1. insert successfully
1112     */
1113     int recordNum = 3;
1114     InsertRecord(recordNum);
1115     std::string userHead = "user";
1116     for (int i = 0; i < recordNum; i++) {
1117         Key key;
1118         key.push_back('k');
1119         key.push_back('0' + i);
1120         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
1121         SetDeviceId(key, std::to_string(i));
1122         ChangeUserId(std::to_string(i), userHead + std::to_string(i));
1123         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1124     }
1125     EXPECT_EQ(CheckWaterMark(userHead + "0"), OK);
1126     /**
1127      * @tc.steps: step2. Check three Log record whether exist or not;
1128      * * @tc.expected: step2. record exist
1129     */
1130     for (int i = 0; i < recordNum; i++) {
1131         Key key;
1132         key.push_back('k');
1133         key.push_back('0' + i);
1134         Value actualValue;
1135         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1136         std::string deviceId = std::to_string(i);
1137         EXPECT_EQ(CheckLogTable(deviceId), OK);
1138         EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK);
1139     }
1140     /**
1141      * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user0" userid with FLAG_ONLY.
1142      * remove "user2" userid log data with dismatch deviceId, it cant not remove the data.
1143      * * @tc.expected: step3. remove OK
1144     */
1145     std::string deviceId0 = "0";
1146     std::string deviceId1 = "1";
1147     std::string deviceId2 = "2";
1148     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user0", ClearMode::FLAG_ONLY), OK);
1149     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK);
1150     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_AND_DATA), OK);
1151     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_ONLY), OK);
1152     Key key0({'k', '0'});
1153     Value actualValue;
1154     EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK);
1155     EXPECT_EQ(CheckLogTable(deviceId0), NOT_FOUND);
1156     EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2;
1157     EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND);
1158     Key key1({'k', '1'});
1159     EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND);
1160     EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND);
1161     Key key2({'k', '2'});;
1162     EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), OK);
1163     EXPECT_EQ(CheckLogTable(deviceId2), OK);
1164 }
1165 
1166 /**
1167  * @tc.name: RemoveDeviceTest006
1168  * @tc.desc: remove record with userId and deviceId, and there are same hashKey record in log table.
1169  * @tc.type: FUNC
1170  * @tc.require:
1171  * @tc.author: mazhao
1172  */
1173 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest006, TestSize.Level0)
1174 {
1175     /**
1176      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1),
1177      * (Key:k2, device:2, userId:2)
1178      * * @tc.expected: step1. insert successfully
1179     */
1180     int recordNum = 3;
1181     InsertRecord(recordNum);
1182     std::string userHead = "user";
1183     for (int i = 0; i < recordNum; i++) {
1184         Key key;
1185         key.push_back('k');
1186         key.push_back('0' + i);
1187         SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE);
1188         SetDeviceId(key, std::to_string(i));
1189         ChangeUserId(std::to_string(i), userHead + std::to_string(i));
1190         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1191     }
1192     /**
1193      * @tc.steps: step2. Check three Log record whether exist or not;
1194      * * @tc.expected: step2. record exist
1195     */
1196     for (int i = 0; i < recordNum; i++) {
1197         Key key;
1198         key.push_back('k');
1199         key.push_back('0' + i);
1200         Value actualValue;
1201         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1202         std::string deviceId = std::to_string(i);
1203         EXPECT_EQ(CheckLogTable(deviceId), OK);
1204     }
1205     /**
1206      * @tc.steps: step3. Make log table all users's hashKey become same hashKey '99', and the hashKey in syncTable
1207      *  where device is deviceId1 also become '99',remove data with FLAG_AND_DATA flag.
1208      * * @tc.expected: step3. remove OK
1209     */
1210     std::string deviceId1 = "1";
1211     std::string deviceId2 = "2";
1212     std::string deviceId0 = "0";
1213     DistributedDBCloudKvStoreTest::ChangeHashKey(deviceId1);
1214     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK);
1215     Key key1({'k', '1'});
1216     Value actualValue;
1217     // there are other users with same hash_key connect with this data in sync_data table, cant not remove the data.
1218     EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK);
1219     EXPECT_EQ(CheckLogTable(deviceId1), OK); // match user2 and user0;
1220     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user2", ClearMode::FLAG_AND_DATA), OK);
1221     EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK);
1222     EXPECT_EQ(CheckLogTable(deviceId1), OK); // only user0 match the hash_key that same as device1.
1223     EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag still 0x100;
1224     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user0", ClearMode::FLAG_AND_DATA), OK);
1225     // all log have been deleted, so data would also be deleted.
1226     EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND);
1227     EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND);
1228     EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND);
1229 }
1230 
1231 /**
1232  * @tc.name: RemoveDeviceTest007
1233  * @tc.desc: remove record with invalid deviceId and mode.
1234  * @tc.type: FUNC
1235  * @tc.require:
1236  * @tc.author: mazhao
1237  */
1238 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest007, TestSize.Level0)
1239 {
1240     /**
1241      * @tc.steps: step1. Test removeDeviceData with invalid length deviceId.
1242      * * @tc.expected:
1243     */
1244     std::string deviceId = std::string(128, 'a');
1245     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::FLAG_AND_DATA), OK);
1246     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::FLAG_AND_DATA), OK);
1247 
1248     std::string invaliDeviceId = std::string(129, 'a');
1249     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, ClearMode::FLAG_AND_DATA), INVALID_ARGS);
1250     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, "user1", ClearMode::FLAG_AND_DATA), INVALID_ARGS);
1251 
1252     /**
1253      * @tc.steps: step2. Test removeDeviceData with invalid mode.
1254      * * @tc.expected:
1255     */
1256     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT);
1257     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT);
1258 }
1259 
1260 /**
1261  * @tc.name: RemoveDeviceTest008
1262  * @tc.desc: remove record without mode.
1263  * @tc.type: FUNC
1264  * @tc.require:
1265  * @tc.author: liaoyonghuang
1266  */
1267 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest008, TestSize.Level0)
1268 {
1269     /**
1270      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1),
1271      * (Key:k2, device:2, userId:2)
1272      * * @tc.expected: step1. insert successfully
1273     */
1274     int recordNum = 3;
1275     InsertRecord(recordNum);
1276     for (int i = 0; i < recordNum; i++) {
1277         Key key;
1278         key.push_back('k');
1279         key.push_back('0' + i);
1280         SetFlag(key, LogInfoFlag::FLAG_CLOUD);
1281         SetDeviceId(key, std::to_string(i));
1282         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1283     }
1284 
1285     /**
1286      * @tc.steps: step2. Check three Log record whether exist or not;
1287      * * @tc.expected: step2. record exist
1288     */
1289     for (int i = 0; i < recordNum; i++) {
1290         Key key;
1291         key.push_back('k');
1292         key.push_back('0' + i);
1293         Value actualValue;
1294         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1295     }
1296     /**
1297      * @tc.steps: step3. Remove data without mode.
1298      * * @tc.expected: step3. remove OK, there are not user record exist in log table.
1299     */
1300     for (int i = 0; i < recordNum; i++) {
1301         EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i)), OK);
1302     }
1303     for (int i = 0; i < recordNum; i++) {
1304         Key key;
1305         key.push_back('k');
1306         key.push_back('0' + i);
1307         Value actualValue;
1308         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND);
1309     }
1310 }
1311 
1312 /**
1313  * @tc.name: RemoveDeviceTest009
1314  * @tc.desc: remove record without mode FLAG_AND_DATA.
1315  * @tc.type: FUNC
1316  * @tc.require:
1317  * @tc.author: liaoyonghuang
1318  */
1319 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest009, TestSize.Level0)
1320 {
1321     /**
1322      * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1),
1323      * (Key:k2, device:2, userId:2)
1324      * * @tc.expected: step1. insert successfully
1325     */
1326     int recordNum = 3;
1327     InsertRecord(recordNum);
1328     for (int i = 0; i < recordNum; i++) {
1329         Key key;
1330         key.push_back('k');
1331         key.push_back('0' + i);
1332         SetFlag(key, LogInfoFlag::FLAG_CLOUD);
1333         SetDeviceId(key, std::to_string(i));
1334         std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms
1335     }
1336 
1337     /**
1338      * @tc.steps: step2. Check three Log record whether exist or not;
1339      * * @tc.expected: step2. record exist
1340     */
1341     for (int i = 0; i < recordNum; i++) {
1342         Key key;
1343         key.push_back('k');
1344         key.push_back('0' + i);
1345         Value actualValue;
1346         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1347         std::string deviceId = std::to_string(i);
1348         EXPECT_EQ(CheckLogTable(deviceId), OK);
1349     }
1350     /**
1351      * @tc.steps: step3. Remove data without mode FLAG_AND_DATA.
1352      * * @tc.expected: step3. remove OK, there are not user record exist in log table.
1353     */
1354     for (int i = 0; i < recordNum; i++) {
1355         EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i), ClearMode::FLAG_AND_DATA), OK);
1356     }
1357     for (int i = 0; i < recordNum; i++) {
1358         Key key;
1359         key.push_back('k');
1360         key.push_back('0' + i);
1361         Value actualValue;
1362         EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1363         std::string deviceId = std::to_string(i);
1364         EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND);
1365     }
1366 }
1367 
1368 /**
1369  * @tc.name: RemoveDeviceTest010
1370  * @tc.desc: remove record with invalid mode.
1371  * @tc.type: FUNC
1372  * @tc.require:
1373  * @tc.author: zhangqiquan
1374  */
1375 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest010, TestSize.Level0)
1376 {
1377     std::string deviceId = std::string(128, 'a');
1378     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_ONLY), INVALID_ARGS);
1379     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::CLEAR_SHARED_TABLE), INVALID_ARGS);
1380     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_AND_DATA), INVALID_ARGS);
1381     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::DEFAULT), OK);
1382     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "", ClearMode::DEFAULT), OK);
1383     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::DEFAULT), OK);
1384 }
1385 
1386 /**
1387  * @tc.name: RemoveDeviceTest011
1388  * @tc.desc: remove record while conn is nullptr.
1389  * @tc.type: FUNC
1390  * @tc.require:
1391  * @tc.author: caihaoting
1392  */
1393 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest011, TestSize.Level0)
1394 {
1395     const KvStoreNbDelegate::Option option = {true, true};
1396     KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr;
1397     ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "RemoveDeviceTest011", option), OK);
1398     ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr);
1399     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegateInvalidPtrS1_);
1400     EXPECT_EQ(kvStoreImpl->Close(), OK);
1401     EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), DB_ERROR);
1402     EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", "", ClearMode::FLAG_ONLY), DB_ERROR);
1403     EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK);
1404 }
1405 
1406 /**
1407  * @tc.name: RemoveDeviceTest012
1408  * @tc.desc: Test remove all data from other device.
1409  * @tc.type: FUNC
1410  * @tc.require:
1411  * @tc.author: liaoyonghuang
1412  */
1413 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest012, TestSize.Level0)
1414 {
1415     /**
1416      * @tc.steps: step1. Insert three record, k0 from device sync, k1 from local write, k2 from cloud sync.
1417      * * @tc.expected: step1. insert successfully
1418     */
1419     int recordNum = 3;
1420     InsertRecord(recordNum);
1421     SetFlag({'k', '0'}, LogInfoFlag::FLAG_CLOUD);
1422     SetFlag({'k', '1'}, LogInfoFlag::FLAG_LOCAL);
1423     /**
1424      * @tc.steps: step2. Remove data from device sync and cloud sync, and remove log.
1425      * * @tc.expected: step2. All data and log are removed except data from local write.
1426     */
1427     EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(), OK);
1428     Value actualValue;
1429     Value expectValue = {'k', '1'};
1430     EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '1'}, actualValue), OK);
1431     EXPECT_EQ(actualValue, expectValue);
1432     EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '0'}, actualValue), NOT_FOUND);
1433     EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '2'}, actualValue), NOT_FOUND);
1434 }
1435 
1436 /**
1437  * @tc.name: RemoveDeviceTest013
1438  * @tc.desc: remove log record with FLAG_ONLY and empty deviceId.
1439  * @tc.type: FUNC
1440  * @tc.require:
1441  * @tc.author: wangxiangdong
1442  */
1443 HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest013, TestSize.Level0)
1444 {
1445     /**
1446      * @tc.steps: step1. Insert data
1447      * * @tc.expected: step1. insert successfully
1448     */
1449     Key k1 = {'k', '1'};
1450     Value v1 = {'v', '1'};
1451     deviceB_->PutData(k1, v1, 1u, 0); // 1 is current timestamp
1452     /**
1453      * @tc.steps: step2. sync between devices
1454      * * @tc.expected: step2. insert successfully
1455     */
1456     deviceB_->Sync(SyncMode::SYNC_MODE_PUSH_ONLY, true);
1457     Value actualValue;
1458     EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue), OK);
1459     EXPECT_EQ(actualValue, v1);
1460     ASSERT_EQ(kvDelegatePtrS1_->Put(k1, v1), OK);
1461     /**
1462      * @tc.steps: step3. sync with cloud
1463      * * @tc.expected: step3. OK
1464     */
1465     BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption);
1466     BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption);
1467     Value actualValue2;
1468     EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue2), OK);
1469     EXPECT_EQ(actualValue2, v1);
1470     EXPECT_EQ(kvDelegatePtrS2_->RemoveDeviceData("", ClearMode::FLAG_AND_DATA), OK);
1471     Value actualValue3;
1472     EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue3), NOT_FOUND);
1473     /**
1474      * @tc.steps: step4. sync between devices and check result
1475      * * @tc.expected: step4. OK
1476     */
1477     deviceB_->Sync(SyncMode::SYNC_MODE_PUSH_ONLY, true);
1478     Value actualValue4;
1479     EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue4), OK);
1480     EXPECT_EQ(actualValue4, v1);
1481 }
1482 
1483 /**
1484  * @tc.name: NormalSyncInvalid001
1485  * @tc.desc: Test normal push not sync and get cloud version.
1486  * @tc.type: FUNC
1487  * @tc.require:
1488  * @tc.author: caihaoting
1489  */
1490 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid001, TestSize.Level0)
1491 {
1492     Key key = {'k'};
1493     Value expectValue = {'v'};
1494     ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK);
__anone34464d90702(const std::string &origin) 1495     kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) {
1496         LOGW("origin is %s", origin.c_str());
1497         return origin + "1";
1498     });
1499     Value actualValue;
1500     EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK);
1501     EXPECT_EQ(actualValue, expectValue);
1502     kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr);
1503     auto result = kvDelegatePtrS1_->GetCloudVersion("");
1504     EXPECT_EQ(result.first, NOT_FOUND);
1505 }
1506 
1507 /**
1508  * @tc.name: NormalSyncInvalid002
1509  * @tc.desc: Test normal push sync and use invalidDevice to get cloud version.
1510  * @tc.type: FUNC
1511  * @tc.require:
1512  * @tc.author: caihaoting
1513  */
1514 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid002, TestSize.Level0)
1515 {
1516     Key key = {'k'};
1517     Value expectValue = {'v'};
1518     ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK);
__anone34464d90802(const std::string &origin) 1519     kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) {
1520         LOGW("origin is %s", origin.c_str());
1521         return origin + "1";
1522     });
1523     BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption);
1524     for (const auto &table : lastProcess_.tableProcess) {
1525         EXPECT_EQ(table.second.upLoadInfo.total, 1u);
1526         EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u);
1527     }
1528     BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption);
1529     for (const auto &table : lastProcess_.tableProcess) {
1530         EXPECT_EQ(table.second.downLoadInfo.total, 2u); // download 2 records
1531         EXPECT_EQ(table.second.downLoadInfo.insertCount, 2u); // download 2 records
1532     }
1533     Value actualValue;
1534     EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK);
1535     EXPECT_EQ(actualValue, expectValue);
1536     kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr);
1537     std::string invalidDevice = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0');
1538     auto result = kvDelegatePtrS2_->GetCloudVersion(invalidDevice);
1539     EXPECT_EQ(result.first, INVALID_ARGS);
1540 }
1541 
1542 /**
1543  * @tc.name: NormalSyncInvalid003
1544  * @tc.desc: Test normal push sync for add data while conn is nullptr.
1545  * @tc.type: FUNC
1546  * @tc.require:
1547  * @tc.author: caihaoting
1548  */
1549 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid003, TestSize.Level0)
1550 {
1551     const KvStoreNbDelegate::Option option = {true, true};
1552     KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr;
1553     ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "NormalSyncInvalid003", option), OK);
1554     ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr);
1555     Key key = {'k'};
1556     Value expectValue = {'v'};
1557     ASSERT_EQ(kvDelegateInvalidPtrS1_->Put(key, expectValue), OK);
__anone34464d90902(const std::string &origin) 1558     kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback([](const std::string &origin) {
1559         LOGW("origin is %s", origin.c_str());
1560         return origin + "1";
1561     });
1562     BlockSync(kvDelegateInvalidPtrS1_, OK, g_CloudSyncoption);
1563     for (const auto &table : lastProcess_.tableProcess) {
1564         EXPECT_EQ(table.second.upLoadInfo.total, 1u);
1565         EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u);
1566     }
1567     Value actualValue;
1568     EXPECT_EQ(kvDelegateInvalidPtrS1_->Get(key, actualValue), OK);
1569     EXPECT_EQ(actualValue, expectValue);
1570     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegateInvalidPtrS1_);
1571     EXPECT_EQ(kvStoreImpl->Close(), OK);
1572     kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback(nullptr);
1573     auto result = kvDelegateInvalidPtrS1_->GetCloudVersion("");
1574     EXPECT_EQ(result.first, DB_ERROR);
1575     EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK);
1576 }
1577 
1578 /**
1579  * @tc.name: NormalSyncInvalid004
1580  * @tc.desc: Test normal push sync use GetDeviceEntries while conn is nullptr.
1581  * @tc.type: FUNC
1582  * @tc.require:
1583  * @tc.author: caihaoting
1584  */
1585 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid004, TestSize.Level0)
1586 {
1587     const KvStoreNbDelegate::Option option = {true, true};
1588     KvStoreNbDelegate *kvDelegateInvalidPtrS2_ = nullptr;
1589     ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS2_, "NormalSyncInvalid004", option), OK);
1590     ASSERT_NE(kvDelegateInvalidPtrS2_, nullptr);
1591     /**
1592      * @tc.steps: step1. store1 put (k1,v1) store2 put (k2,v2)
1593      * @tc.expected: step1. both put ok
1594      */
1595     communicatorAggregator_->SetLocalDeviceId("DEVICES_A");
__anone34464d90a02(const std::string &origin) 1596     kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) {
1597         LOGW("origin is %s", origin.c_str());
1598         return origin + "1";
1599     });
__anone34464d90b02(const std::string &origin) 1600     kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback([](const std::string &origin) {
1601         LOGW("origin is %s", origin.c_str());
1602         return origin + "1";
1603     });
1604     Key key1 = {'k', '1'};
1605     Value expectValue1 = {'v', '1'};
1606     Key key2 = {'k', '2'};
1607     Value expectValue2 = {'v', '2'};
1608     ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK);
1609     ASSERT_EQ(kvDelegateInvalidPtrS2_->Put(key2, expectValue2), OK);
1610     /**
1611      * @tc.steps: step2. both store1 and store2 sync while conn is nullptr
1612      * @tc.expected: step2. both sync ok, and store2 got (k1,v1) store1 not exist (k2,v2)
1613      */
1614     BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption);
1615     LOGW("Store1 sync end");
1616     communicatorAggregator_->SetLocalDeviceId("DEVICES_B");
1617     BlockSync(kvDelegateInvalidPtrS2_, OK, g_CloudSyncoption);
1618     LOGW("Store2 sync end");
1619     Value actualValue;
1620     EXPECT_EQ(kvDelegateInvalidPtrS2_->Get(key1, actualValue), OK);
1621 
1622     /**
1623      * @tc.steps: step3. use GetDeviceEntries while conn is nullptr
1624      * @tc.expected: step3. DB_ERROR
1625      */
1626     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegateInvalidPtrS2_);
1627     EXPECT_EQ(kvStoreImpl->Close(), OK);
1628     std::vector<Entry> entries;
1629     EXPECT_EQ(kvDelegateInvalidPtrS2_->GetDeviceEntries(std::string("DEVICES_A"), entries), DB_ERROR);
1630     EXPECT_EQ(entries.size(), 0u); // 1 record
1631     communicatorAggregator_->SetLocalDeviceId("DEVICES_A");
1632     EXPECT_EQ(actualValue, expectValue1);
1633     EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND);
1634 
1635     kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr);
1636     kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback(nullptr);
1637     EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS2_), OK);
1638 }
1639 
1640 /**
1641  * @tc.name: NormalSyncInvalid005
1642  * @tc.desc: Test normal sync with invalid parm.
1643  * @tc.type: FUNC
1644  * @tc.require:
1645  * @tc.author: caihaoting
1646  */
1647 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid005, TestSize.Level0)
1648 {
1649     Key key = {'k'};
1650     Value expectValue = {'v'};
1651     ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK);
1652     auto devices = g_CloudSyncoption.devices;
1653     EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr), NOT_SUPPORT);
1654     Query query = Query::Select().Range({}, {});
1655     EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr, query, true), NOT_SUPPORT);
1656     auto mode = g_CloudSyncoption.mode;
1657     EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), NOT_SUPPORT);
1658     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegatePtrS1_);
1659     EXPECT_EQ(kvStoreImpl->Close(), OK);
1660     BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption, DB_ERROR);
1661     EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr), DB_ERROR);
1662     EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), DB_ERROR);
1663 }
1664 
1665 /**
1666  * @tc.name: NormalSyncInvalid006
1667  * @tc.desc: Test normal sync set cloudDB while cloudDB is empty and conn is nullptr.
1668  * @tc.type: FUNC
1669  * @tc.require:
1670  * @tc.author: caihaoting
1671  */
1672 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid006, TestSize.Level0)
1673 {
1674     /**
1675      * @tc.steps: step1. set cloudDB while cloudDB is empty
1676      * @tc.expected: step1. INVALID_ARGS
1677      */
1678     std::map<std::string, std::shared_ptr<ICloudDb>> cloudDbs;
1679     EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), INVALID_ARGS);
1680     /**
1681      * @tc.steps: step2. set cloudDB while conn is nullptr
1682      * @tc.expected: step2. DB_ERROR
1683      */
1684     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegatePtrS1_);
1685     EXPECT_EQ(kvStoreImpl->Close(), OK);
1686     cloudDbs[USER_ID] = virtualCloudDb_;
1687     EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), DB_ERROR);
1688 }
1689 
1690 /**
1691  * @tc.name: NormalSyncInvalid007
1692  * @tc.desc: Test normal sync set cloudDb schema while conn is nullptr.
1693  * @tc.type: FUNC
1694  * @tc.require:
1695  * @tc.author: caihaoting
1696  */
1697 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid007, TestSize.Level0)
1698 {
1699     /**
1700      * @tc.steps: step1. set cloudDB schema while conn is nullptr
1701      * @tc.expected: step1. DB_ERROR
1702      */
1703     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegatePtrS1_);
1704     EXPECT_EQ(kvStoreImpl->Close(), OK);
1705     std::map<std::string, DataBaseSchema> schemas;
1706     schemas[USER_ID] = GetDataBaseSchema(true);
1707     EXPECT_EQ(kvDelegatePtrS1_->SetCloudDbSchema(schemas), DB_ERROR);
1708 }
1709 
1710 /**
1711  * @tc.name: NormalSyncInvalid008
1712  * @tc.desc: Test SetCloudSyncConfig with invalid parm.
1713  * @tc.type: FUNC
1714  * @tc.require:
1715  * @tc.author: caihaoting
1716  */
1717 HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid008, TestSize.Level0)
1718 {
1719     /**
1720      * @tc.steps: step1. SetCloudSyncConfig with invalid maxUploadCount.
1721      * @tc.expected: step1. INVALID_ARGS
1722      */
1723     CloudSyncConfig config;
1724     int maxUploadCount = 0;
1725     config.maxUploadCount = maxUploadCount;
1726     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS);
1727     maxUploadCount = 2001;
1728     config.maxUploadCount = maxUploadCount;
1729     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS);
1730     maxUploadCount = 50;
1731     config.maxUploadCount = maxUploadCount;
1732     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK);
1733 
1734     /**
1735      * @tc.steps: step2. SetCloudSyncConfig with invalid maxUploadSize.
1736      * @tc.expected: step2. INVALID_ARGS
1737      */
1738     int maxUploadSize = 1023;
1739     config.maxUploadSize = maxUploadSize;
1740     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS);
1741     maxUploadSize = 128 * 1024 * 1024 + 1;
1742     config.maxUploadSize = maxUploadSize;
1743     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS);
1744     maxUploadSize = 10240;
1745     config.maxUploadSize = maxUploadSize;
1746     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK);
1747 
1748     /**
1749      * @tc.steps: step3. SetCloudSyncConfig with invalid maxRetryConflictTimes.
1750      * @tc.expected: step3. INVALID_ARGS
1751      */
1752     int maxRetryConflictTimes = -2;
1753     config.maxRetryConflictTimes = maxRetryConflictTimes;
1754     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS);
1755     maxRetryConflictTimes = 2;
1756     config.maxRetryConflictTimes = maxRetryConflictTimes;
1757     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK);
1758 
1759     /**
1760      * @tc.steps: step4. SetCloudSyncConfig while conn is nullptr
1761      * @tc.expected: step4. DB_ERROR
1762      */
1763     auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(kvDelegatePtrS1_);
1764     EXPECT_EQ(kvStoreImpl->Close(), OK);
1765     EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), DB_ERROR);
1766 }
1767 
1768 /**
1769  * @tc.name: ConflictSync001
1770  * @tc.desc: test upload delete with version conflict error under merge mode, then success after retry.
1771  * @tc.type: FUNC
1772  * @tc.require:
1773  * @tc.author: suyuchen
1774  */
1775 HWTEST_F(DistributedDBCloudKvStoreTest, ConflictSync001, TestSize.Level0)
1776 {
1777     /**
1778      * @tc.steps: step1. Set the retry count to 2
1779      * @tc.expected: step1. ok.
1780      */
1781     CloudSyncConfig config;
1782     config.maxRetryConflictTimes = 2;
1783     kvDelegatePtrS1_->SetCloudSyncConfig(config);
1784     /**
1785      * @tc.steps: step2. Put 2 records and set flag to cloud
1786      * @tc.expected: step2. ok.
1787      */
1788     InsertRecord(2);
1789     SetFlag({'k', '0'}, LogInfoFlag::FLAG_CLOUD);
1790     SetFlag({'k', '1'}, LogInfoFlag::FLAG_CLOUD);
1791     /**
1792      * @tc.steps: step3. delete {k1, v1}
1793      * @tc.expected: step3. ok.
1794      */
1795     kvDelegatePtrS1_->Delete(KEY_1);
1796     /**
1797      * @tc.steps: step4. Set CLOUD_VERSION_CONFLICT when upload, and do sync
1798      * @tc.expected: step4. OK.
1799      */
1800     int recordIndex = 0;
1801     virtualCloudDb_->ForkInsertConflict([&recordIndex](const std::string &tableName, VBucket &extend, VBucket &record,
__anone34464d90c02(const std::string &tableName, VBucket &extend, VBucket &record, vector<VirtualCloudDb::CloudData> &cloudDataVec) 1802         vector<VirtualCloudDb::CloudData> &cloudDataVec) {
1803         recordIndex++;
1804         if (recordIndex == 1) { // set 1st record return CLOUD_VERSION_CONFLICT
1805             extend[CloudDbConstant::ERROR_FIELD] = static_cast<int64_t>(DBStatus::CLOUD_VERSION_CONFLICT);
1806             return CLOUD_VERSION_CONFLICT;
1807         }
1808         return OK;
1809     });
1810     BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption);
1811     /**
1812      * @tc.steps: step5. Check last process
1813      * @tc.expected: step5. ok.
1814      */
1815     for (const auto &table : lastProcess_.tableProcess) {
1816         EXPECT_EQ(table.second.upLoadInfo.total, 1u);
1817         EXPECT_EQ(table.second.upLoadInfo.successCount, 1u);
1818         EXPECT_EQ(table.second.upLoadInfo.failCount, 0u);
1819         EXPECT_EQ(table.second.upLoadInfo.deleteCount, 1u);
1820     }
1821     virtualCloudDb_->ForkInsertConflict(nullptr);
1822 }
1823 }
1824