1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <gtest/gtest.h>
16 #include "distributeddb_tools_unit_test.h"
17 #include "strategy_factory.h"
18 #include "virtual_cloud_syncer.h"
19
20 using namespace std;
21 using namespace testing::ext;
22 using namespace DistributedDB;
23
24 namespace {
25 class DistributedDBCloudStrategyTest : public testing::Test {
26 public:
27 static void SetUpTestCase(void);
28 static void TearDownTestCase(void);
29 void SetUp();
30 void TearDown();
31 };
32
SetUpTestCase(void)33 void DistributedDBCloudStrategyTest::SetUpTestCase(void)
34 {
35 }
36
TearDownTestCase(void)37 void DistributedDBCloudStrategyTest::TearDownTestCase(void)
38 {
39 }
40
SetUp(void)41 void DistributedDBCloudStrategyTest::SetUp(void)
42 {
43 DistributedDBUnitTest::DistributedDBToolsUnitTest::PrintTestCaseInfo();
44 }
45
TearDown(void)46 void DistributedDBCloudStrategyTest::TearDown(void)
47 {
48 }
49
50 /**
51 * @tc.name: StrategyFactoryTest001
52 * @tc.desc: Verify cloud strategy build function.
53 * @tc.type: FUNC
54 * @tc.require:
55 * @tc.author: zhangqiquan
56 */
57 HWTEST_F(DistributedDBCloudStrategyTest, StrategyFactoryTest001, TestSize.Level0)
58 {
59 /**
60 * @tc.steps: step1. PUSH PULL PUSH_PULL mode will get base strategy
61 * @tc.expected: step1. both judge update cursor and upload got false
62 */
63 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_PUSH_ONLY);
64 ASSERT_NE(strategy, nullptr);
65 EXPECT_EQ(strategy->JudgeUpdateCursor(), false);
66 EXPECT_EQ(strategy->JudgeUpload(), false);
67
68 strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_PULL_ONLY);
69 ASSERT_NE(strategy, nullptr);
70 EXPECT_EQ(strategy->JudgeUpdateCursor(), false);
71 EXPECT_EQ(strategy->JudgeUpload(), false);
72
73 strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_PUSH_PULL);
74 ASSERT_NE(strategy, nullptr);
75 EXPECT_EQ(strategy->JudgeUpdateCursor(), false);
76 EXPECT_EQ(strategy->JudgeUpload(), false);
77 /**
78 * @tc.steps: step2. CLOUD_MERGE mode will get cloud merge strategy
79 * @tc.expected: step2. both judge update cursor and upload got true
80 */
81 strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE);
82 ASSERT_NE(strategy, nullptr);
83 EXPECT_EQ(strategy->JudgeUpdateCursor(), true);
84 EXPECT_EQ(strategy->JudgeUpload(), true);
85 }
86
87 /**
88 * @tc.name: TagOpTyeTest001
89 * @tc.desc: Verify cloud merge strategy tag operation type function.
90 * @tc.type: FUNC
91 * @tc.require:
92 * @tc.author: zhangqiquan
93 */
94 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest001, TestSize.Level0)
95 {
96 /**
97 * @tc.steps: step1. build cloud merge strategy
98 */
99 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE);
100 ASSERT_NE(strategy, nullptr);
101 LogInfo localInfo;
102 LogInfo cloudInfo;
103 /**
104 * @tc.steps: step2. local not exist cloud record
105 * @tc.expected: step2. insert cloud record to local
106 */
107 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::INSERT);
108 /**
109 * @tc.steps: step3. local record is newer and local not exist gid, while local data is not sync-ed
110 * @tc.expected: step3. only update gid
111 */
112 localInfo.timestamp = 1u;
113 localInfo.flag = static_cast<uint64_t>(LogInfoFlag::FLAG_LOCAL);
114 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::ONLY_UPDATE_GID);
115 /**
116 * @tc.steps: step4. local record is newer and local exist gid
117 * @tc.expected: step4. no need handle this record
118 */
119 localInfo.cloudGid = "gid";
120 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
121 /**
122 * @tc.steps: step5. cloud record is newer
123 * @tc.expected: step5. update cloud record
124 */
125 cloudInfo.timestamp = 2u; // mark 2 means cloud is new
126 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
127 /**
128 * @tc.steps: step6. cloud record is newer and it is delete
129 * @tc.expected: step6. delete cloud record
130 */
131 cloudInfo.flag = 0x01; // it means delete
132 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::DELETE);
133 /**
134 * @tc.steps: step7. cloud is new and local is delete
135 * @tc.expected: step7 insert cloud record
136 */
137 cloudInfo.flag = 0; // it means no delete
138 localInfo.flag = 0x01; // it means delete
139 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::INSERT);
140 /**
141 * @tc.steps: step8. cloud is new and local both delete
142 * @tc.expected: step8 not handle cloud record
143 */
144 cloudInfo.flag = 0x01; // it means delete
145 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE_TIMESTAMP);
146 /**
147 * @tc.steps: step9. cloud is delete and local not exist
148 * @tc.expected: step9 not handle cloud record
149 */
150 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
151 /**
152 * @tc.steps: step10. cloud is old and delete, local has gid
153 * @tc.expected: step10 clear gid
154 */
155 localInfo.timestamp = 3u; // mark 3 means local is new
156 localInfo.flag = static_cast<uint64_t>(LogInfoFlag::FLAG_LOCAL);
157 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::CLEAR_GID);
158 /**
159 * @tc.steps: step10. cloud is old and delete, local has not gid
160 * @tc.expected: step10 not handle cloud record
161 */
162 localInfo.cloudGid = "";
163 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
164 /**
165 * @tc.steps: step11. cloud has same timestamp with local, and local has empty gid
166 * @tc.expected: step11 only update gid
167 */
168 cloudInfo.timestamp = localInfo.timestamp;
169 cloudInfo.flag = 0; // it means no delete
170 localInfo.flag = 0; // it means no delete
171 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::ONLY_UPDATE_GID);
172
173 /**
174 * @tc.steps: step12. local record is newer and local not exist gid, while record is sync-ed
175 * @tc.expected: step12. update
176 */
177 localInfo.timestamp = 4u;
178 localInfo.flag = static_cast<uint64_t>(LogInfoFlag::FLAG_CLOUD);
179 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
180 }
181
182 /**
183 * @tc.name: TagOpTyeTest002
184 * @tc.desc: Verify local cover cloud strategy tag operation type function.
185 * @tc.type: FUNC
186 * @tc.require:
187 * @tc.author: huangboxin
188 */
189 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest002, TestSize.Level0)
190 {
191 /**
192 * @tc.steps: step1. build local cover cloud strategy
193 */
194 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH);
195 ASSERT_NE(strategy, nullptr);
196 LogInfo localInfo;
197 LogInfo cloudInfo;
198
199 /**
200 * @tc.steps: step2. local not exist cloud record
201 * @tc.expected: step2. not handle
202 */
203 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
204
205 /**
206 * @tc.steps: step3. local has cloud record but don't have gid
207 * @tc.expected: step3. only update gid
208 */
209 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::ONLY_UPDATE_GID);
210
211 /**
212 * @tc.steps: step4. local has cloud record and have gid
213 * @tc.expected: step4. not handle
214 */
215 localInfo.cloudGid = "gid";
216 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
217 localInfo.cloudGid = "";
218 /**
219 * @tc.steps: step5. local has cloud record(without gid) but cloud flag is delete
220 * @tc.expected: step5. ONLY UPDATE GID
221 */
222 cloudInfo.flag = 0x01; // it means delete
223 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
224 /**
225 * @tc.steps: step6. local has cloud record(with gid) but cloud flag is delete
226 * @tc.expected: step6. CLEAR_GID
227 */
228 localInfo.cloudGid = "gid";
229 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::CLEAR_GID);
230 }
231
232 /**
233 * @tc.name: TagOpTyeTest003
234 * @tc.desc: Verify cloud cover local strategy tag operation type function.
235 * @tc.type: FUNC
236 * @tc.require:
237 * @tc.author: huangboxin
238 */
239 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest003, TestSize.Level0)
240 {
241 /**
242 * @tc.steps: step1. cloud cover local strategy
243 */
244 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_FORCE_PULL);
245 ASSERT_NE(strategy, nullptr);
246 LogInfo localInfo;
247 LogInfo cloudInfo;
248
249 /**
250 * @tc.steps: step2. local not exist cloud record(without gid) and its not deleted in cloud
251 * @tc.expected: step2. insert
252 */
253 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::INSERT);
254
255 /**
256 * @tc.steps: step3. local not exist cloud record and it's deleted in cloud (without gid)
257 * @tc.expected: step3. not handle
258 */
259 localInfo.cloudGid = "";
260 cloudInfo.flag = 0x01; // it means delete
261 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
262
263 /**
264 * @tc.steps: step4. local not exist cloud record and it's deleted in cloud (with gid)
265 * @tc.expected: step4. delete
266 */
267 localInfo.cloudGid = "gid";
268 EXPECT_EQ(strategy->TagSyncDataStatus(false, false, localInfo, cloudInfo), OpType::DELETE);
269
270 /**
271 * @tc.steps: step5. local exist cloud record and its deleted in cloud
272 * @tc.expected: step5. delete
273 */
274 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::DELETE);
275 localInfo.cloudGid = "";
276 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::DELETE);
277
278 /**
279 * @tc.steps: step6. local exist cloud record and its not deleted in cloud(WITH OR WITHOUT gid)
280 * @tc.expected: step6. UPDATE
281 */
282 cloudInfo.flag = 0x00;
283 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
284 localInfo.cloudGid = "gid";
285 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
286 }
287
288 /**
289 * @tc.name: TagOpTyeTest004
290 * @tc.desc: Verify cloud cover local strategy tag operation type function.
291 * @tc.type: FUNC
292 * @tc.require:
293 * @tc.author: huangboxin
294 */
295 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest004, TestSize.Level0)
296 {
297 /**
298 * @tc.steps: step1. cloud cover local strategy
299 */
300 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_FORCE_PULL);
301 ASSERT_NE(strategy, nullptr);
302 LogInfo localInfo;
303 LogInfo cloudInfo;
304
305 cloudInfo.flag = 0x01;
306 localInfo.flag = 0x01;
307 localInfo.cloudGid = "";
308 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE_TIMESTAMP);
309
310 cloudInfo.flag = 0x00;
311 localInfo.flag = 0x01;
312 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::INSERT);
313 }
314
315 /**
316 * @tc.name: TagOpTyeTest005
317 * @tc.desc: Verify same data conflict in local.
318 * @tc.type: FUNC
319 * @tc.require:
320 * @tc.author: zhangqiquan
321 */
322 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest005, TestSize.Level0)
323 {
324 auto syncer = new(std::nothrow) VirtualCloudSyncer(nullptr);
325 ASSERT_NE(syncer, nullptr);
326 DataInfoWithLog localInfo;
327 LogInfo cloudInfo;
328 OpType result = OpType::INSERT;
329 EXPECT_EQ(syncer->CallTagStatusByStrategy(true, localInfo, cloudInfo, result), E_OK);
330 EXPECT_EQ(result, OpType::NOT_HANDLE);
331 localInfo.logInfo.device = "dev";
332 EXPECT_EQ(syncer->CallTagStatusByStrategy(true, localInfo, cloudInfo, result), -E_INTERNAL_ERROR);
333 RefObject::KillAndDecObjRef(syncer);
334 }
335
336 /**
337 * @tc.name: TagOpTyeTest006
338 * @tc.desc: Verify cloud merge strategy for same record.
339 * @tc.type: FUNC
340 * @tc.require:
341 * @tc.author: zhangqiquan
342 */
343 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest006, TestSize.Level0)
344 {
345 /**
346 * @tc.steps: step1. create merge strategy
347 * @tc.expected: step1. create ok
348 */
349 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE);
350 ASSERT_NE(strategy, nullptr);
351 /**
352 * @tc.steps: step2. build cloud and local info, both has same version and diff timestamp
353 * @tc.expected: step2. strategy res is NOT_HANDLE
354 */
355 LogInfo localInfo;
356 LogInfo cloudInfo;
357 localInfo.cloudGid = "gid";
358 localInfo.version = "version";
359 localInfo.timestamp = 1;
360 cloudInfo.cloudGid = "gid";
361 cloudInfo.version = "version";
362 cloudInfo.timestamp = localInfo.timestamp + 1;
363 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
364 /**
365 * @tc.steps: step3. make timestamp gap is more than 1s
366 * @tc.expected: step3. strategy res is UPDATE
367 */
368 cloudInfo.timestamp = cloudInfo.timestamp + CloudDbConstant::ONE_SECOND;
369 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
370 }
371
372 /**
373 * @tc.name: TagOpTyeTest007
374 * @tc.desc: Verify cloud merge strategy for KV and RDB scene when local time is larger and local flag different.
375 * @tc.type: FUNC
376 * @tc.require:
377 * @tc.author: suyue
378 */
379 HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest007, TestSize.Level0)
380 {
381 /**
382 * @tc.steps: step1. create merge strategy, init localInfo/cloudInfo and local time is larger
383 * @tc.expected: step1. create ok
384 */
385 auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE);
386 ASSERT_NE(strategy, nullptr);
387 LogInfo localInfo;
388 LogInfo cloudInfo;
389 localInfo.cloudGid = "gid";
390 localInfo.timestamp = 1u;
391
392 /**
393 * @tc.steps: step2. local record is newer when flag is FLAG_LOCAL for RDB scene
394 * @tc.expected: step2. no need handle this record
395 */
396 localInfo.flag = static_cast<uint64_t>(LogInfoFlag::FLAG_LOCAL);
397 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
398
399 /**
400 * @tc.steps: step3. local data need update when flag is not FLAG_LOCAL for RDB scene
401 * @tc.expected: step3. need UPDATE this record
402 */
403 localInfo.flag = 0x00;
404 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
405
406 /**
407 * @tc.steps: step4. local record is newer when flag is not FLAG_CLOUD_WRITE for KV scene
408 * @tc.expected: step4. no need handle this record
409 */
410 strategy->SetIsKvScene(true);
411 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
412 localInfo.flag = 0x00;
413 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE);
414
415 /**
416 * @tc.steps: step5. local data need update when flag is FLAG_CLOUD_WRITE for KV scene
417 * @tc.expected: step5. need UPDATE this record
418 */
419 localInfo.flag = static_cast<uint64_t>(LogInfoFlag::FLAG_CLOUD_WRITE);
420 EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE);
421 }
422 }