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 
16 
17 #include "cloud_syncer_test.h"
18 #include "distributeddb_tools_unit_test.h"
19 #include "mock_iclouddb.h"
20 #include "mock_icloud_sync_storage_interface.h"
21 
22 
23 using namespace testing::ext;
24 using namespace testing;
25 using namespace DistributedDB;
26 using namespace DistributedDBUnitTest;
27 
28 namespace {
29 class DistributedDBCloudSyncerProgressManagerTest : public testing::Test {
30 public:
31     static void SetUpTestCase(void);
32     static void TearDownTestCase(void);
33     void SetUp();
34     void TearDown();
35 };
36 
SetUpTestCase(void)37 void DistributedDBCloudSyncerProgressManagerTest::SetUpTestCase(void)
38 {
39 }
40 
TearDownTestCase(void)41 void DistributedDBCloudSyncerProgressManagerTest::TearDownTestCase(void)
42 {
43 }
44 
SetUp(void)45 void DistributedDBCloudSyncerProgressManagerTest::SetUp(void)
46 {
47     DistributedDBToolsUnitTest::PrintTestCaseInfo();
48 }
49 
TearDown(void)50 void DistributedDBCloudSyncerProgressManagerTest::TearDown(void)
51 {
52 }
53 
54 /**
55  * @tc.name: SyncerMgrCheck001
56  * @tc.desc: Test case1 about Synchronization parameter
57  * @tc.type: FUNC
58  * @tc.require: SR000HPUOS
59  * @tc.author: huangboxin
60  */
61 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSize.Level1)
62 {
63     // Synchronization parameter checks
64     MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface();
65     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
66     TestCloudSyncer cloudSyncer(storageProxy);
67     std::shared_ptr<MockICloudDB> idb = std::make_shared<MockICloudDB>();
68     cloudSyncer.SetMockICloudDB(idb);
69     std::vector<DeviceID> devices = {"cloud"};
70     std::vector<std::string> tables = {"TestTableA", "TestTableB" };
71 
72     // check different sync mode
73     cloudSyncer.InitCloudSyncerForSync();
74 
75     EXPECT_CALL(*idb, Query(_, _, _)).WillRepeatedly(Return(QUERY_END));
76     EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK));
77     EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK));
78     EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair<DBStatus, uint32_t>(OK, 10)));
79     EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK));
80     EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK));
81     EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK));
82     EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK));
83     EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK));
84     EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK));
85     EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK));
86     EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK));
87     EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK));
88 
89     SyncProcess res;
90     int errCode = cloudSyncer.Sync(devices, SYNC_MODE_CLOUD_FORCE_PUSH, tables, [&res](
__anon444c46650202( const std::map<std::string, SyncProcess> &process) 91         const std::map<std::string, SyncProcess> &process) {
92         res = process.begin()->second;
93     }, 5000);
94     EXPECT_EQ(errCode, E_OK);
95     std::this_thread::sleep_for(std::chrono::seconds(1));
96     EXPECT_EQ(res.process, FINISHED);
97 
98     TestCloudSyncer cloudSyncer2(storageProxy);
99     cloudSyncer2.InitCloudSyncerForSync();
100     cloudSyncer2.SetMockICloudDB(idb);
101     errCode = cloudSyncer2.Sync(devices, SYNC_MODE_CLOUD_FORCE_PULL, tables, [&res](
__anon444c46650302( const std::map<std::string, SyncProcess> &process) 102         const std::map<std::string, SyncProcess> &process) {
103         res = process.begin()->second;
104     }, 5000);
105     EXPECT_EQ(errCode, E_OK);
106     std::this_thread::sleep_for(std::chrono::seconds(1));
107     EXPECT_EQ(res.process, FINISHED);
108 
109     RuntimeContext::GetInstance()->StopTaskPool();
110     storageProxy.reset();
111     delete iCloud;
112 }
113 
114 /**
115  * @tc.name: SyncerMgrCheck002
116  * @tc.desc: Test case2 about Synchronization parameter
117  * @tc.type: FUNC
118  * @tc.require: SR000HPUOS
119  * @tc.author: huangboxin
120  */
121 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSize.Level1)
122 {
123     MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface();
124     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
125     std::shared_ptr<MockICloudDB> idb = std::make_shared<MockICloudDB>();
126     TestCloudSyncer cloudSyncer3(storageProxy);
127     cloudSyncer3.SetMockICloudDB(idb);
128     cloudSyncer3.InitCloudSyncerForSync();
129 
130     std::vector<DeviceID> devices = {"cloud"};
131     std::vector<std::string> tables = {"TestTableA", "TestTableB" };
132     EXPECT_CALL(*idb, Query(_, _, _)).WillRepeatedly(Return(QUERY_END));
133     EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK));
134     EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK));
135     EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair<DBStatus, uint32_t>(OK, 10)));
136     EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK));
137     EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK));
138     EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK));
139     EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK));
140     EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK));
141     EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK));
142     EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK));
143     EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK));
144     EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK));
145 
146     SyncProcess res;
147     int errCode = cloudSyncer3.Sync(devices, SYNC_MODE_CLOUD_MERGE, tables, [&res](
__anon444c46650402( const std::map<std::string, SyncProcess> &process) 148         const std::map<std::string, SyncProcess> &process) {
149         res = process.begin()->second;
150     }, 5000);
151     EXPECT_EQ(errCode, E_OK);
152     std::this_thread::sleep_for(std::chrono::seconds(1));
153     EXPECT_EQ(res.process, FINISHED);
154 
155     TestCloudSyncer cloudSyncer4(storageProxy);
156     cloudSyncer4.InitCloudSyncerForSync();
157     cloudSyncer4.SetMockICloudDB(idb);
158     errCode = cloudSyncer4.Sync(devices, SYNC_MODE_PULL_ONLY, tables, [&res](
__anon444c46650502( const std::map<std::string, SyncProcess> &process) 159         const std::map<std::string, SyncProcess> &process) {
160         res = process.begin()->second;
161     }, 5000);
162     EXPECT_EQ(errCode, -E_NOT_SUPPORT);
163     std::this_thread::sleep_for(std::chrono::seconds(1));
164     EXPECT_EQ(res.process, FINISHED);
165 
166     RuntimeContext::GetInstance()->StopTaskPool();
167     storageProxy.reset();
168     delete iCloud;
169     idb = nullptr;
170 }
171 
172 /**
173  * @tc.name: SyncerMgrCheck003
174  * @tc.desc: Test case2 about Synchronization parameter
175  * @tc.type: FUNC
176  * @tc.require: SR000HPUOS
177  * @tc.author: huangboxin
178  */
179 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSize.Level1)
180 {
181     MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface();
182     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
183     TestCloudSyncer cloudSyncer5(storageProxy);
184     std::shared_ptr<MockICloudDB> idb = std::make_shared<MockICloudDB>();
185     cloudSyncer5.SetMockICloudDB(idb);
186     cloudSyncer5.InitCloudSyncerForSync();
187 
188     std::vector<std::string> tables = {"TestTableA", "TestTableB" };
189     EXPECT_CALL(*idb, Query(_, _, _)).WillRepeatedly(Return(QUERY_END));
190     EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK));
191     EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK));
192     EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair<DBStatus, uint32_t>(OK, 10)));
193     EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK));
194     EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK));
195     EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK));
196     EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK));
197     EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK));
198     EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK));
199     EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK));
200     EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK));
201     EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK));
202 
203     SyncProcess res;
204     // check if device is empty
205     std::vector<DeviceID> devices = {};
206     int errCode = cloudSyncer5.Sync(devices, SYNC_MODE_CLOUD_MERGE, tables, [&res](
__anon444c46650602( const std::map<std::string, SyncProcess> &process) 207         const std::map<std::string, SyncProcess> &process) {
208         res = process.begin()->second;
209     }, 5000);
210     EXPECT_EQ(errCode, -E_INVALID_ARGS);
211     std::string invalidDevice = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0');
212     devices.emplace_back(invalidDevice);
213     EXPECT_EQ(cloudSyncer5.Sync(devices, SYNC_MODE_CLOUD_MERGE, tables, nullptr, 5000), -E_INVALID_ARGS); // 5000 ms
214     std::this_thread::sleep_for(std::chrono::seconds(1));
215     RuntimeContext::GetInstance()->StopTaskPool();
216     storageProxy.reset();
217     delete iCloud;
218     idb = nullptr;
219 }
220 /**
221  * @tc.name: SyncerMgrCheck004
222  * @tc.desc: Test the number of queues
223 
224  * @tc.type: FUNC
225  * @tc.require: SR000HPUOS
226  * @tc.author: huangboxin
227  */
228 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck004, TestSize.Level1)
229 {
230     // Check the number of queues
231     MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface();
232     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
233     TestCloudSyncer cloudSyncer(storageProxy);
234     std::shared_ptr<MockICloudDB> idb = std::make_shared<MockICloudDB>();
235     cloudSyncer.SetMockICloudDB(idb);
236     std::vector<std::string> tables = {"TestTableA", "TestTableB" };
237     SyncProcessCallback onProcess;
238     // current limit is 32;
239     for (int i = 1; i <= 32; i++) {
240         cloudSyncer.taskInfo_ = cloudSyncer.SetAndGetCloudTaskInfo(SYNC_MODE_CLOUD_FORCE_PUSH, tables, onProcess, 5000);
241         int errCode = cloudSyncer.CallTryToAddSyncTask(std::move(cloudSyncer.taskInfo_));
242         EXPECT_EQ(errCode, E_OK);
243     }
244     cloudSyncer.taskInfo_ = cloudSyncer.SetAndGetCloudTaskInfo(SYNC_MODE_CLOUD_FORCE_PUSH, tables, onProcess, 5000);
245     int errCode = cloudSyncer.CallTryToAddSyncTask(std::move(cloudSyncer.taskInfo_));
246     EXPECT_EQ(errCode, -E_BUSY);
247 
248     cloudSyncer.PopTaskQueue();
249     cloudSyncer.PopTaskQueue();
250 
251     // After pop task from taskQueue, it should be ok to call TryToAddSyncTask
252     cloudSyncer.taskInfo_ = cloudSyncer.SetAndGetCloudTaskInfo(SYNC_MODE_CLOUD_FORCE_PUSH, tables, onProcess, 5000);
253     errCode = cloudSyncer.CallTryToAddSyncTask(std::move(cloudSyncer.taskInfo_));
254     EXPECT_EQ(errCode, E_OK);
255 
256     RuntimeContext::GetInstance()->StopTaskPool();
257     storageProxy.reset();
258     delete iCloud;
259     idb = nullptr;
260 }
261 
262 /**
263  * @tc.name: SyncerMgrCheck005
264  * @tc.desc: Test Single-threaded execution of tasks
265  * @tc.type: FUNC
266  * @tc.require: SR000HPUOS
267  * @tc.author: huangboxin
268  */
269 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck005, TestSize.Level1)
270 {
271     // Single-threaded execution of tasks
272     MockICloudSyncStorageInterface *iCloud = new MockICloudSyncStorageInterface();
273     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
274     TestCloudSyncer cloudSyncer(storageProxy);
275     std::shared_ptr<MockICloudDB> idb = std::make_shared<MockICloudDB>();
276     cloudSyncer.SetMockICloudDB(idb);
277 
278     std::vector<string> devices = {"cloud"};
279     std::vector<std::string> tables = {"TestTableA", "TestTableB" };
280 
281     cloudSyncer.InitCloudSyncer(0u, SYNC_MODE_CLOUD_FORCE_PUSH);
282     int errCode = cloudSyncer.CreateCloudTaskInfoAndCallTryToAddSync(SYNC_MODE_CLOUD_FORCE_PUSH, tables, {}, 5000);
283     errCode = cloudSyncer.CallPrepareSync(1u);
284     EXPECT_EQ(errCode, E_OK);
285 
286     cloudSyncer.InitCloudSyncer(2u, SYNC_MODE_CLOUD_FORCE_PUSH);
287     errCode = cloudSyncer.CallPrepareSync(2u);
288     EXPECT_EQ(errCode, -E_DB_CLOSED);
289 
290     RuntimeContext::GetInstance()->StopTaskPool();
291     storageProxy.reset();
292     delete iCloud;
293     idb = nullptr;
294 }
295 
296 /**
297  * @tc.name: SyncerMockCheck001
298  * @tc.desc: Test Syncer pause tasks
299  * @tc.type: FUNC
300  * @tc.require:
301  * @tc.author: zhangqiquan
302  */
303 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMockCheck001, TestSize.Level0)
304 {
305     auto *iCloud = new MockICloudSyncStorageInterface();
306     ASSERT_NE(iCloud, nullptr);
307     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
308     auto cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy);
309     ASSERT_NE(cloudSyncer, nullptr);
310 
311     cloudSyncer->SetCurrentContext(2u); // 2 is taskId
312     cloudSyncer->SetLastTaskId(3u); // 3 is taskId
313     cloudSyncer->SetCurrentTaskPause();
314     cloudSyncer->SetAssetFields("test", {{}});
315     cloudSyncer->SetAssetDownloadList(1);
316     EXPECT_EQ(cloudSyncer->CallDownloadAssets(), -E_TASK_PAUSED);
317     cloudSyncer->SetCurrentContext(0);
318     cloudSyncer->Close();
319     RefObject::KillAndDecObjRef(cloudSyncer);
320     storageProxy.reset();
321     delete iCloud;
322 }
323 
324 /**
325  * @tc.name: SyncerMockCheck002
326  * @tc.desc: Test Syncer get current query
327  * @tc.type: FUNC
328  * @tc.require:
329  * @tc.author: zhangqiquan
330  */
331 HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMockCheck002, TestSize.Level0)
332 {
333     auto *iCloud = new MockICloudSyncStorageInterface();
334     std::shared_ptr<TestStorageProxy> storageProxy = std::make_shared<TestStorageProxy>(iCloud);
335     ASSERT_NE(iCloud, nullptr);
336     EXPECT_CALL(*iCloud, GetIdentify).WillRepeatedly(Return(""));
337     auto cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy);
338     ASSERT_NE(cloudSyncer, nullptr);
339 
340     // prepare current query and last query
341     // make them has diff sort type
342     const TaskId currentTask = 2u;
343     QuerySyncObject currentQuery;
344     currentQuery.SetTableName("current");
345     currentQuery.SetSortType(SortType::TIMESTAMP_ASC);
346     cloudSyncer->SetQuerySyncObject(currentTask, currentQuery);
347     const TaskId lastTask = 3u;
348     QuerySyncObject lastQuery;
349     lastQuery.SetTableName("last");
350     lastQuery.SetSortType(SortType::TIMESTAMP_DESC);
351     cloudSyncer->SetQuerySyncObject(lastTask, lastQuery);
352     cloudSyncer->SetCurrentContext(currentTask);
353     cloudSyncer->SetLastTaskId(lastTask);
354     // check get current query from syncer
355     QuerySyncObject actualQuery = cloudSyncer->CallGetQuerySyncObject(currentQuery.GetTableName());
356     EXPECT_EQ(actualQuery.GetSortType(), currentQuery.GetSortType());
357     EXPECT_NE(actualQuery.GetSortType(), lastQuery.GetSortType());
358 
359     cloudSyncer->SetCurrentContext(0);
360     cloudSyncer->Close();
361     RefObject::KillAndDecObjRef(cloudSyncer);
362     storageProxy = nullptr;
363     delete iCloud;
364 }
365 }