1 /*
2 * Copyright (c) 2025 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 "kv_general_ut.h"
17 #include "process_communicator_test_stub.h"
18
19 namespace DistributedDB {
20 using namespace testing::ext;
21 using namespace DistributedDB;
22 using namespace DistributedDBUnitTest;
23
24 class DistributedDBKvMultiUserSyncTest : public KVGeneralUt {
25 protected:
26 void PrepareData();
27 void SyncStep1();
28 void SyncStep2();
29 void SyncStep3();
30 static void SetTargetUserId(const std::string &deviceId, const std::string &userId);
31 static constexpr const char *DEVICE_A = "DEVICE_A";
32 static constexpr const char *DEVICE_B = "DEVICE_B";
33 static constexpr const char *USER_ID_1 = "USER_ID_1";
34 static constexpr const char *USER_ID_2 = "USER_ID_2";
35 static constexpr const char *USER_ID_3 = "USER_ID_3";
36 };
37
CheckData(KvStoreNbDelegate * delegate,const Key & key,const Value & expectValue)38 void CheckData(KvStoreNbDelegate *delegate, const Key &key, const Value &expectValue)
39 {
40 Value actualValue;
41 if (expectValue.empty()) {
42 EXPECT_EQ(delegate->Get(key, actualValue), NOT_FOUND);
43 } else {
44 EXPECT_EQ(delegate->Get(key, actualValue), OK);
45 EXPECT_EQ(actualValue, expectValue);
46 }
47 }
48
SetTargetUserId(const std::string & deviceId,const std::string & userId)49 void DistributedDBKvMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId)
50 {
51 ICommunicatorAggregator *communicatorAggregator = nullptr;
52 RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator);
53 ASSERT_NE(communicatorAggregator, nullptr);
54 auto virtualCommunicatorAggregator = static_cast<VirtualCommunicatorAggregator*>(communicatorAggregator);
55 auto communicator = static_cast<VirtualCommunicator*>(virtualCommunicatorAggregator->GetCommunicator(deviceId));
56 ASSERT_NE(communicator, nullptr);
57 communicator->SetTargetUserId(userId);
58 }
59
PrepareData()60 void DistributedDBKvMultiUserSyncTest::PrepareData()
61 {
62 KvStoreNbDelegate::Option option;
63 option.syncDualTupleMode = true;
64 SetOption(option);
65
66 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
67 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
68 auto store1 = GetDelegate(storeInfo1);
69 ASSERT_NE(store1, nullptr);
70
71 StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID};
72 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK);
73 auto store2 = GetDelegate(storeInfo2);
74 ASSERT_NE(store2, nullptr);
75
76 EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK);
77 EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK);
78 EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK);
79 EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK);
80
81 CheckData(store1, KEY_1, VALUE_1);
82 CheckData(store1, KEY_2, VALUE_2);
83 CheckData(store1, KEY_3, VALUE_3);
84 CheckData(store2, KEY_4, VALUE_4);
85 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
86 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK);
87 }
88
SyncStep1()89 void DistributedDBKvMultiUserSyncTest::SyncStep1()
90 {
91 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
92 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
93 auto store1 = GetDelegate(storeInfo1);
94 ASSERT_NE(store1, nullptr);
95
96 StoreInfo storeInfo3 = {USER_ID_1, STORE_ID_2, APP_ID};
97 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK);
98 auto store3 = GetDelegate(storeInfo3);
99 ASSERT_NE(store3, nullptr);
100
101 SetTargetUserId(DEVICE_A, USER_ID_1);
102 SetTargetUserId(DEVICE_B, USER_ID_1);
103 BlockPush(storeInfo1, storeInfo3);
104
105 CheckData(store3, KEY_1, VALUE_1);
106 CheckData(store3, KEY_2, VALUE_2);
107 CheckData(store3, KEY_3, VALUE_3);
108
109 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
110 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK);
111 }
112
SyncStep2()113 void DistributedDBKvMultiUserSyncTest::SyncStep2()
114 {
115 StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID};
116 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK);
117 auto store2 = GetDelegate(storeInfo2);
118 ASSERT_NE(store2, nullptr);
119
120 StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID};
121 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK);
122 auto store4 = GetDelegate(storeInfo4);
123 ASSERT_NE(store4, nullptr);
124
125 SetTargetUserId(DEVICE_A, USER_ID_2);
126 SetTargetUserId(DEVICE_B, USER_ID_2);
127 BlockPush(storeInfo2, storeInfo4);
128
129 CheckData(store4, KEY_1, {});
130 CheckData(store4, KEY_2, {});
131 CheckData(store4, KEY_3, {});
132 CheckData(store4, KEY_4, VALUE_4);
133
134 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK);
135 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK);
136 }
137
SyncStep3()138 void DistributedDBKvMultiUserSyncTest::SyncStep3()
139 {
140 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
141 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
142 auto store1 = GetDelegate(storeInfo1);
143 ASSERT_NE(store1, nullptr);
144
145 StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID};
146 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK);
147 auto store4 = GetDelegate(storeInfo4);
148 ASSERT_NE(store4, nullptr);
149
150 SetTargetUserId(DEVICE_A, USER_ID_2);
151 SetTargetUserId(DEVICE_B, USER_ID_1);
152 BlockPush(storeInfo1, storeInfo4);
153
154 CheckData(store4, KEY_1, VALUE_1);
155 CheckData(store4, KEY_2, VALUE_2);
156 CheckData(store4, KEY_3, VALUE_3);
157 CheckData(store4, KEY_4, VALUE_4);
158
159 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
160 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK);
161 }
162
163 /**
164 * @tc.name: NormalSyncTest001
165 * @tc.desc: Test normal sync.
166 * @tc.type: FUNC
167 * @tc.require:
168 * @tc.author: liaoyonghuang
169 */
170 HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest001, TestSize.Level1)
171 {
172 /**
173 * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record
174 * @tc.expected: step1. OK.
175 */
176 PrepareData();
177 /**
178 * @tc.steps: step2. (devA, user1) sync to (devB, user1)
179 * @tc.expected: step2. OK.
180 */
181 SyncStep1();
182 /**
183 * @tc.steps: step3. (devA, user2) put 3 records, (devB, user2) put 1 record
184 * @tc.expected: step3. OK.
185 */
186 SyncStep2();
187 /**
188 * @tc.steps: step4. (devA, user1) put 3 records, (devB, user2) put 1 record
189 * @tc.expected: step4. OK.
190 */
191 SyncStep3();
192 }
193
194 /**
195 * @tc.name: NormalSyncTest002
196 * @tc.desc: Test sync with low version target.
197 * @tc.type: FUNC
198 * @tc.require:
199 * @tc.author: liaoyonghuang
200 */
201 HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest002, TestSize.Level0)
202 {
203 /**
204 * @tc.steps: step1. Init process communicator
205 * @tc.expected: step1. OK.
206 */
207 KvStoreNbDelegate::Option option;
208 option.syncDualTupleMode = true;
209 SetOption(option);
210 std::shared_ptr<ProcessCommunicatorTestStub> processCommunicator =
211 std::make_shared<ProcessCommunicatorTestStub>();
212 processCommunicator->SetDataHeadInfo({DBStatus::LOW_VERSION_TARGET, 0u});
213 SetProcessCommunicator(processCommunicator);
214
215 /**
216 * @tc.steps: step2. (devA, user1) put 1 record and sync to (devB, user2)
217 * @tc.expected: step2. OK.
218 */
219 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
220 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
221 auto store1 = GetDelegate(storeInfo1);
222 ASSERT_NE(store1, nullptr);
223 EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK);
224
225 StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_2, APP_ID};
226 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK);
227 auto store2 = GetDelegate(storeInfo2);
228 ASSERT_NE(store2, nullptr);
229
230 SetTargetUserId(DEVICE_A, USER_ID_2);
231 SetTargetUserId(DEVICE_B, USER_ID_1);
232 UserInfo userInfo = {.receiveUser = USER_ID_2, .sendUser = USER_ID_1};
233 processCommunicator->SetDataUserInfo({{userInfo}});
234 BlockPush(storeInfo1, storeInfo2);
235
236 CheckData(store2, KEY_1, VALUE_1);
237
238 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK);
239
240 /**
241 * @tc.steps: step3. (devA, user1) put 1 record and sync to (devB, user3)
242 * @tc.expected: step3. OK.
243 */
244 StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID};
245 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK);
246 auto store3 = GetDelegate(storeInfo3);
247 ASSERT_NE(store3, nullptr);
248
249 EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK);
250
251 SetTargetUserId(DEVICE_A, USER_ID_3);
252 SetTargetUserId(DEVICE_B, USER_ID_1);
253 userInfo = {.receiveUser = USER_ID_3, .sendUser = USER_ID_1};
254 processCommunicator->SetDataUserInfo({{userInfo}});
255 BlockPush(storeInfo1, storeInfo3);
256
257 CheckData(store3, KEY_2, VALUE_2);
258
259 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
260 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK);
261 }
262
263 /**
264 * @tc.name: NormalSyncTest003
265 * @tc.desc: deviceA:user1 put 2 records and sync to deviceB, deviceA:user1 delete 1 records, deviceA:user2 put
266 * 2 records and sync to deviceB, deviceA:user1 sync to deviceB.
267 * @tc.type: FUNC
268 * @tc.require:
269 * @tc.author: liaoyonghuang
270 */
271 HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest003, TestSize.Level0)
272 {
273 /**
274 * @tc.steps: step1. set option
275 * @tc.expected: step1. OK.
276 */
277 KvStoreNbDelegate::Option option;
278 option.syncDualTupleMode = true;
279 option.conflictResolvePolicy = DEVICE_COLLABORATION;
280 SetOption(option);
281
282 /**
283 * @tc.steps: step2. deviceA:user1 put 10 records and sync to deviceB, deviceA:user1 delete 1 records
284 * @tc.expected: step2. OK.
285 */
286 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
287 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
288 auto store1 = GetDelegate(storeInfo1);
289 ASSERT_NE(store1, nullptr);
290 EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK);
291 EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK);
292
293 StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID};
294 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK);
295 auto store3 = GetDelegate(storeInfo3);
296 ASSERT_NE(store3, nullptr);
297
298 SetTargetUserId(DEVICE_A, USER_ID_3);
299 SetTargetUserId(DEVICE_B, USER_ID_1);
300 BlockPush(storeInfo1, storeInfo3);
301 EXPECT_EQ(store1->Delete(KEY_1), OK);
302 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
303
304 /**
305 * @tc.steps: step3. deviceA:user2 put 2 records and sync to deviceB
306 * @tc.expected: step3. OK.
307 */
308 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
309
310 StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID};
311 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK);
312 auto store2 = GetDelegate(storeInfo2);
313 ASSERT_NE(store2, nullptr);
314 EXPECT_EQ(store2->Put(KEY_1, VALUE_1), OK);
315 EXPECT_EQ(store2->Put(KEY_2, VALUE_2), OK);
316
317 SetTargetUserId(DEVICE_A, USER_ID_3);
318 SetTargetUserId(DEVICE_B, USER_ID_2);
319 BlockPush(storeInfo2, storeInfo3);
320 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK);
321
322 /**
323 * @tc.steps: step4. deviceA:user1 sync to deviceB.
324 * @tc.expected: step4. OK.
325 */
326 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
327 BlockPush(storeInfo1, storeInfo3);
328 Value actualValue;
329 EXPECT_EQ(store3->Get(KEY_1, actualValue), NOT_FOUND);
330 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
331 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK);
332 }
333
334 /**
335 * @tc.name: InvalidSync001
336 * @tc.desc: Test sync with empty target user.
337 * @tc.type: FUNC
338 * @tc.require:
339 * @tc.author: liaoyonghuang
340 */
341 HWTEST_F(DistributedDBKvMultiUserSyncTest, InvalidSync001, TestSize.Level0)
342 {
343 /**
344 * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record
345 * @tc.expected: step1. OK.
346 */
347 KvStoreNbDelegate::Option option;
348 option.syncDualTupleMode = true;
349 SetOption(option);
350 StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID};
351 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
352 auto store1 = GetDelegate(storeInfo1);
353 ASSERT_NE(store1, nullptr);
354
355 StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID};
356 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK);
357 auto store2 = GetDelegate(storeInfo2);
358 ASSERT_NE(store2, nullptr);
359
360 EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK);
361 EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK);
362 EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK);
363 EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK);
364
365 CheckData(store1, KEY_1, VALUE_1);
366 CheckData(store1, KEY_2, VALUE_2);
367 CheckData(store1, KEY_3, VALUE_3);
368 CheckData(store2, KEY_4, VALUE_4);
369 /**
370 * @tc.steps: step2. set empty target user and sync
371 * @tc.expected: step2. return OK.
372 */
373 SetTargetUserId(DEVICE_A, "");
374 BlockPush(storeInfo1, storeInfo2);
375 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK);
376 ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK);
377 }
378 }