1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef OMIT_MULTI_VER
16 #include <functional>
17 #include <gtest/gtest.h>
18 #include <thread>
19 #include "db_errno.h"
20 #include "distributeddb_tools_unit_test.h"
21 #include "log_print.h"
22 #include "multi_ver_vacuum.h"
23 #include "multi_ver_vacuum_executor_stub.h"
24 
25 using namespace std;
26 using namespace testing::ext;
27 using namespace DistributedDB;
28 
29 namespace {
30     using Predication = std::function<bool(void)>;
31     // repeatInterval in millisecond
RepeatCheckAsyncResult(const Predication & inPred,uint8_t repeatLimit,uint32_t repeatInterval)32     bool RepeatCheckAsyncResult(const Predication &inPred, uint8_t repeatLimit, uint32_t repeatInterval)
33     {
34         uint8_t limit = repeatLimit;
35         while (limit != 0) {
36             if (inPred()) {
37                 return true;
38             }
39             if (--limit == 0) {
40                 break;
41             }
42             std::this_thread::sleep_for(std::chrono::milliseconds(repeatInterval));
43         }
44         return false;
45     }
46 
47     const string DB_IDENTITY_A = "DATABASE_A";
48     const string DB_IDENTITY_B = "DATABASE_B";
49     const string DB_IDENTITY_C = "DATABASE_C";
50 
CheckVacuumTaskStatus(const MultiVerVacuum & inVacuum,const string & inDbIdentifier,VacuumTaskStatus expectStatus,uint8_t repeatLimit=5,uint32_t repeatInterval=100)51     bool CheckVacuumTaskStatus(const MultiVerVacuum &inVacuum, const string &inDbIdentifier,
52         VacuumTaskStatus expectStatus, uint8_t repeatLimit = 5, uint32_t repeatInterval = 100) // 5 times, 100 ms
53     {
54         return RepeatCheckAsyncResult([inVacuum, inDbIdentifier, expectStatus]()->bool {
55             VacuumTaskStatus outStatus = VacuumTaskStatus::RUN_WAIT;
56             int errCode = inVacuum.QueryStatus(inDbIdentifier, outStatus);
57             return errCode == E_OK && outStatus == expectStatus;
58         }, repeatLimit, repeatInterval);
59     }
60 }
61 
62 class DistributedDBMultiVerVacuumTest : public testing::Test {
63 public:
64     static void SetUpTestCase(void);
65     static void TearDownTestCase(void);
66     void SetUp();
67     void TearDown();
68 };
69 
SetUpTestCase(void)70 void DistributedDBMultiVerVacuumTest::SetUpTestCase(void)
71 {
72     MultiVerVacuum::Enable(true); // Make sure functionality is enabled.
73 }
74 
TearDownTestCase(void)75 void DistributedDBMultiVerVacuumTest::TearDownTestCase(void)
76 {
77 }
78 
SetUp()79 void DistributedDBMultiVerVacuumTest::SetUp()
80 {
81     DistributedDBUnitTest::DistributedDBToolsUnitTest::PrintTestCaseInfo();
82 }
83 
TearDown()84 void DistributedDBMultiVerVacuumTest::TearDown()
85 {
86 }
87 
88 /**
89  * @tc.name: SingleTaskNormalStatusSwitch001
90  * @tc.desc: Test status switch for single task under normal operation
91  * @tc.type: FUNC
92  * @tc.require: AR000C6TRV AR000CQDTM
93  * @tc.author: xiaozhenjian
94  */
95 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch001, TestSize.Level2)
96 {
97     // Preset
98     MultiVerVacuum vacuum;
99     MultiVerVacuumExecutorStub databaseA(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
100 
101     /**
102      * @tc.steps: step1. launch dbTaskA for databaseA
103      * @tc.expected: step1. dbTaskA RUN_NING
104      */
105     int errCode = vacuum.Launch(DB_IDENTITY_A, &databaseA);
106     EXPECT_EQ(errCode, E_OK);
107     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
108     EXPECT_EQ(stepOne, true);
109 
110     /**
111      * @tc.steps: step2. pause dbTaskA
112      * @tc.expected: step2. dbTaskA PAUSE_DONE
113      */
114     errCode = vacuum.Pause(DB_IDENTITY_A);
115     EXPECT_EQ(errCode, E_OK);
116     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
117     EXPECT_EQ(stepTwo, true);
118 
119     /**
120      * @tc.steps: step3. pause dbTaskA again
121      * @tc.expected: step3. dbTaskA PAUSE_DONE
122      */
123     errCode = vacuum.Pause(DB_IDENTITY_A);
124     EXPECT_EQ(errCode, E_OK);
125     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
126     EXPECT_EQ(stepThree, true);
127 
128     /**
129      * @tc.steps: step4. continue dbTaskA with autoRelaunch false
130      * @tc.expected: step4. dbTaskA PAUSE_DONE
131      */
132     errCode = vacuum.Continue(DB_IDENTITY_A, false);
133     EXPECT_EQ(errCode, E_OK);
134     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100 ms
135     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::PAUSE_DONE);
136     EXPECT_EQ(stepFour, true);
137 
138     /**
139      * @tc.steps: step5. continue dbTaskA with autoRelaunch false again
140      * @tc.expected: step5. dbTaskA RUN_NING
141      */
142     errCode = vacuum.Continue(DB_IDENTITY_A, false);
143     EXPECT_EQ(errCode, E_OK);
144     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
145     EXPECT_EQ(stepFive, true);
146 
147     /**
148      * @tc.steps: step6. wait for some time
149      * @tc.expected: step6. dbTaskA FINISH
150      */
151     bool stepSix = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
152     EXPECT_EQ(stepSix, true);
153 }
154 
155 /**
156  * @tc.name: SingleTaskNormalStatusSwitch002
157  * @tc.desc: Test status switch for single task under normal operation
158  * @tc.type: FUNC
159  * @tc.require: AR000C6TRV AR000CQDTM
160  * @tc.author: xiaozhenjian
161  */
162 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch002, TestSize.Level2)
163 {
164     // Preset
165     MultiVerVacuum vacuum;
166     MultiVerVacuumExecutorStub databaseB(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
167 
168     /**
169      * @tc.steps: step1. launch dbTaskB for databaseB, then wait for some time
170      * @tc.expected: step1. dbTaskB FINISH
171      */
172     int errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
173     EXPECT_EQ(errCode, E_OK);
174     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
175     EXPECT_EQ(stepOne, true);
176 
177     /**
178      * @tc.steps: step2. pause dbTaskB
179      * @tc.expected: step2. dbTaskB FINISH
180      */
181     errCode = vacuum.Pause(DB_IDENTITY_B);
182     EXPECT_EQ(errCode, E_OK);
183     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 1); // only 1 time
184     EXPECT_EQ(stepTwo, true);
185 
186     /**
187      * @tc.steps: step3. continue dbTaskB with autoRelaunch false
188      * @tc.expected: step3. dbTaskB FINISH
189      */
190     errCode = vacuum.Continue(DB_IDENTITY_B, false);
191     EXPECT_EQ(errCode, E_OK);
192     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100 ms
193     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 1); // only 1 time
194     EXPECT_EQ(stepThree, true);
195 
196     /**
197      * @tc.steps: step4. pause dbTaskB again
198      * @tc.expected: step4. dbTaskB FINISH
199      */
200     errCode = vacuum.Pause(DB_IDENTITY_B);
201     EXPECT_EQ(errCode, E_OK);
202     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 1); // only 1 time
203     EXPECT_EQ(stepFour, true);
204 
205     /**
206      * @tc.steps: step5. continue dbTaskB again with autoRelaunch true
207      * @tc.expected: step5. dbTaskB RUN_NING
208      */
209     errCode = vacuum.Continue(DB_IDENTITY_B, true);
210     EXPECT_EQ(errCode, E_OK);
211     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
212     EXPECT_EQ(stepFive, true);
213 
214     /**
215      * @tc.steps: step6. wait for some time
216      * @tc.expected: step6. dbTaskB FINISH
217      */
218     bool stepSix = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
219     EXPECT_EQ(stepSix, true);
220 }
221 
222 /**
223  * @tc.name: SingleTaskNormalStatusSwitch003
224  * @tc.desc: Test status switch for single task under normal operation
225  * @tc.type: FUNC
226  * @tc.require: AR000C6TRV AR000CQDTM
227  * @tc.author: xiaozhenjian
228  */
229 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch003, TestSize.Level2)
230 {
231     // Preset
232     MultiVerVacuum vacuum;
233     MultiVerVacuumExecutorStub databaseC(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
234 
235     /**
236      * @tc.steps: step1. launch dbTaskC for databaseC, then wait for some time
237      * @tc.expected: step1. dbTaskC FINISH
238      */
239     int errCode = vacuum.Launch(DB_IDENTITY_C, &databaseC);
240     EXPECT_EQ(errCode, E_OK);
241     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
242     EXPECT_EQ(stepOne, true);
243 
244     /**
245      * @tc.steps: step2. AutoRelaunch dbTaskC
246      * @tc.expected: step2. dbTaskC RUN_NING
247      */
248     errCode = vacuum.AutoRelaunchOnce(DB_IDENTITY_C);
249     EXPECT_EQ(errCode, E_OK);
250     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING);
251     EXPECT_EQ(stepTwo, true);
252 
253     /**
254      * @tc.steps: step3. Abort dbTaskC
255      * @tc.expected: step3. dbTaskC ABORT_DONE
256      */
257     errCode = vacuum.Abort(DB_IDENTITY_C);
258     EXPECT_EQ(errCode, E_OK);
259     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
260     EXPECT_EQ(stepThree, true);
261 
262     /**
263      * @tc.steps: step4. launch dbTaskC again
264      * @tc.expected: step4. dbTaskC RUN_NING
265      */
266     errCode = vacuum.Launch(DB_IDENTITY_C, &databaseC);
267     EXPECT_EQ(errCode, E_OK);
268     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING);
269     EXPECT_EQ(stepFour, true);
270 
271     /**
272      * @tc.steps: step5. wait for some time
273      * @tc.expected: step5. dbTaskC FINISH
274      */
275     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
276     EXPECT_EQ(stepFive, true);
277 
278     /**
279      * @tc.steps: step6. Abort dbTaskC again
280      * @tc.expected: step6. dbTaskC ABORT_DONE
281      */
282     errCode = vacuum.Abort(DB_IDENTITY_C);
283     EXPECT_EQ(errCode, E_OK);
284     bool stepSix = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
285     EXPECT_EQ(stepSix, true);
286 }
287 
288 /**
289  * @tc.name: SingleTaskNormalStatusSwitch004
290  * @tc.desc: Test status switch for single task under normal operation
291  * @tc.type: FUNC
292  * @tc.require: AR000C6TRV AR000CQDTM
293  * @tc.author: xiaozhenjian
294  */
295 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch004, TestSize.Level2)
296 {
297     // Preset
298     MultiVerVacuum vacuum;
299     MultiVerVacuumExecutorStub databaseA(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
300 
301     /**
302      * @tc.steps: step1. launch dbTaskA for databaseA, then wait for some time
303      * @tc.expected: step1. dbTaskA FINISH
304      */
305     int errCode = vacuum.Launch(DB_IDENTITY_A, &databaseA);
306     EXPECT_EQ(errCode, E_OK);
307     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
308     EXPECT_EQ(stepOne, true);
309 
310     /**
311      * @tc.steps: step2. pause dbTaskA
312      * @tc.expected: step2. dbTaskA FINISH
313      */
314     errCode = vacuum.Pause(DB_IDENTITY_A);
315     EXPECT_EQ(errCode, E_OK);
316     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 1); // only 1 time
317     EXPECT_EQ(stepTwo, true);
318 
319     /**
320      * @tc.steps: step3. AutoRelaunch dbTaskA
321      * @tc.expected: step3. dbTaskA FINISH
322      */
323     errCode = vacuum.AutoRelaunchOnce(DB_IDENTITY_A);
324     EXPECT_EQ(errCode, E_OK);
325     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100 ms
326     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 1); // only 1 time
327     EXPECT_EQ(stepThree, true);
328 
329     /**
330      * @tc.steps: step4. continue dbTaskA with autoRelaunch false
331      * @tc.expected: step4. dbTaskA RUN_NING
332      */
333     errCode = vacuum.Continue(DB_IDENTITY_A, false);
334     EXPECT_EQ(errCode, E_OK);
335     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
336     EXPECT_EQ(stepFour, true);
337 
338     /**
339      * @tc.steps: step5. wait for some time
340      * @tc.expected: step5. dbTaskA FINISH
341      */
342     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
343     EXPECT_EQ(stepFive, true);
344 }
345 
346 /**
347  * @tc.name: SingleTaskAbnormalStatusSwitch001
348  * @tc.desc: Test status switch for single task under abnormal operation
349  * @tc.type: FUNC
350  * @tc.require: AR000C6TRV AR000CQDTM
351  * @tc.author: xiaozhenjian
352  */
353 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskAbnormalStatusSwitch001, TestSize.Level2)
354 {
355     // Preset
356     MultiVerVacuum vacuum;
357     MultiVerVacuumExecutorStub databaseB(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
358 
359     /**
360      * @tc.steps: step1. launch dbTaskB for databaseB
361      * @tc.expected: step1. dbTaskB RUN_NING
362      */
363     int errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
364     EXPECT_EQ(errCode, E_OK);
365     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
366     EXPECT_EQ(stepOne, true);
367 
368     /**
369      * @tc.steps: step2. pause dbTaskB
370      * @tc.expected: step2. dbTaskB PAUSE_DONE
371      */
372     errCode = vacuum.Pause(DB_IDENTITY_B);
373     EXPECT_EQ(errCode, E_OK);
374     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
375     EXPECT_EQ(stepTwo, true);
376 
377     /**
378      * @tc.steps: step3. abort dbTaskB
379      * @tc.expected: step3. dbTaskB ABORT_DONE
380      */
381     errCode = vacuum.Abort(DB_IDENTITY_B);
382     EXPECT_EQ(errCode, E_OK);
383     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
384     EXPECT_EQ(stepThree, true);
385 
386     /**
387      * @tc.steps: step4. launch dbTaskB again
388      * @tc.expected: step4. dbTaskB RUN_NING
389      */
390     errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
391     EXPECT_EQ(errCode, E_OK);
392     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
393     EXPECT_EQ(stepFour, true);
394 
395     /**
396      * @tc.steps: step5. pause dbTaskB again
397      * @tc.expected: step5. dbTaskB PAUSE_DONE
398      */
399     errCode = vacuum.Pause(DB_IDENTITY_B);
400     EXPECT_EQ(errCode, E_OK);
401     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
402     EXPECT_EQ(stepFive, true);
403 
404     /**
405      * @tc.steps: step6. continue dbTaskA with autoRelaunch false
406      * @tc.expected: step6. dbTaskB RUN_NING
407      */
408     errCode = vacuum.Continue(DB_IDENTITY_B, false);
409     EXPECT_EQ(errCode, E_OK);
410     bool stepSix = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
411     EXPECT_EQ(stepSix, true);
412 
413     /**
414      * @tc.steps: step7. wait for some time
415      * @tc.expected: step7. dbTaskB FINISH
416      */
417     bool stepSeven = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
418     EXPECT_EQ(stepSeven, true);
419 }
420 
421 namespace {
ConcurrentPauseThenCheckResult(MultiVerVacuum & vacuum,const std::string & dbIdentifier)422     bool ConcurrentPauseThenCheckResult(MultiVerVacuum &vacuum, const std::string &dbIdentifier)
423     {
424         int retForThreadA = E_OK;
425         int retForThreadB = E_OK;
426         int isQuitThreadA = false;
427         int isQuitThreadB = false;
428         std::thread threadA([&vacuum, &dbIdentifier, &retForThreadA, &isQuitThreadA]() {
429             LOGI("[ConcurrentPauseThenCheckResult] ThreadA Enter Do Pause.");
430             retForThreadA = vacuum.Pause(dbIdentifier);
431             isQuitThreadA = true;
432             LOGI("[ConcurrentPauseThenCheckResult] ThreadA Exit Do Pause.");
433         });
434         std::thread threadB([&vacuum, &dbIdentifier, &retForThreadB, &isQuitThreadB]() {
435             LOGI("[ConcurrentPauseThenCheckResult] ThreadB Enter Do Pause.");
436             retForThreadB = vacuum.Pause(dbIdentifier);
437             isQuitThreadB = true;
438             LOGI("[ConcurrentPauseThenCheckResult] ThreadB Exit Do Pause.");
439         });
440         threadA.detach();
441         threadB.detach();
442         bool result = RepeatCheckAsyncResult([&retForThreadA, &isQuitThreadA, &retForThreadB, &isQuitThreadB]()->bool {
443             LOGI("[ConcurrentPauseThenCheckResult] Check.");
444             return retForThreadA == E_OK && retForThreadB == E_OK && isQuitThreadA == true && isQuitThreadB == true;
445         }, 6, 500); // 6 time, 500 ms
446         if (!result) {
447             LOGE("[ConcurrentPauseThenCheckResult] RepeatCheckAsyncResult Fail.");
448             return false;
449         }
450         return CheckVacuumTaskStatus(vacuum, dbIdentifier, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
451     }
452 
ConcurrentPauseAndAbortThenCheckResult(MultiVerVacuum & vacuum,const std::string & dbIdentifier)453     bool ConcurrentPauseAndAbortThenCheckResult(MultiVerVacuum &vacuum, const std::string &dbIdentifier)
454     {
455         int retForThreadA = E_OK;
456         int retForThreadB = E_OK;
457         int isQuitThreadA = false;
458         int isQuitThreadB = false;
459         std::thread threadA([&vacuum, &dbIdentifier, &retForThreadA, &isQuitThreadA]() {
460             LOGI("[ConcurrentPauseAndAbortThenCheckResult] ThreadA Enter Do Pause.");
461             retForThreadA = vacuum.Pause(dbIdentifier);
462             isQuitThreadA = true;
463             LOGI("[ConcurrentPauseAndAbortThenCheckResult] ThreadA Exit Do Pause.");
464         });
465         std::thread threadB([&vacuum, &dbIdentifier, &retForThreadB, &isQuitThreadB]() {
466             LOGI("[ConcurrentPauseAndAbortThenCheckResult] ThreadB Enter Do Abort.");
467             retForThreadB = vacuum.Abort(dbIdentifier);
468             isQuitThreadB = true;
469             LOGI("[ConcurrentPauseAndAbortThenCheckResult] ThreadB Exit Do Abort.");
470         });
471         threadA.detach();
472         threadB.detach();
473         bool result = RepeatCheckAsyncResult([&retForThreadA, &isQuitThreadA, &retForThreadB, &isQuitThreadB]()->bool {
474             LOGI("[ConcurrentPauseAndAbortThenCheckResult] Check."); // Pause May Fail if Abort First
475             return retForThreadB == E_OK && isQuitThreadA == true && isQuitThreadB == true;
476         }, 6, 500); // 6 time, 500 ms
477         if (!result) {
478             LOGE("[ConcurrentPauseAndAbortThenCheckResult] RepeatCheckAsyncResult Fail.");
479             return false;
480         }
481         return CheckVacuumTaskStatus(vacuum, dbIdentifier, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
482     }
483 }
484 
485 /**
486  * @tc.name: SingleTaskConcurrentStatusSwitch001
487  * @tc.desc: Test status switch for single task under Concurrent operation
488  * @tc.type: FUNC
489  * @tc.require: AR000C6TRV AR000CQDTM
490  * @tc.author: xiaozhenjian
491  */
492 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskConcurrentStatusSwitch001, TestSize.Level2)
493 {
494     // Preset
495     MultiVerVacuum vacuum;
496     MultiVerVacuumExecutorStub databaseC(DbScale {1, 1, 1, 1}, 1000); // 1 For Scale, 1000 For TimeCost, 11s in Total
497 
498     /**
499      * @tc.steps: step1. launch dbTaskC for databaseC, databaseC is timecost
500      * @tc.expected: step1. dbTaskC FINISH
501      */
502     int errCode = vacuum.Launch(DB_IDENTITY_C, &databaseC);
503     EXPECT_EQ(errCode, E_OK);
504     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING);
505     EXPECT_EQ(stepOne, true);
506 
507     /**
508      * @tc.steps: step2. Concurrently pause dbTaskC in two thread
509      * @tc.expected: step2. thread can quit and dbTaskC PAUSE_DONE
510      */
511     bool stepTwo = ConcurrentPauseThenCheckResult(vacuum, DB_IDENTITY_C);
512     EXPECT_EQ(stepTwo, true);
513 
514     /**
515      * @tc.steps: step3. continue dbTaskC with autoRelaunch false
516      * @tc.expected: step3. dbTaskC PAUSE_DONE
517      */
518     errCode = vacuum.Continue(DB_IDENTITY_C, false);
519     EXPECT_EQ(errCode, E_OK);
520     std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100 ms
521     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
522     EXPECT_EQ(stepThree, true);
523 
524     /**
525      * @tc.steps: step4. continue dbTaskC with autoRelaunch false again
526      * @tc.expected: step4. dbTaskC RUN_NING
527      */
528     errCode = vacuum.Continue(DB_IDENTITY_C, false);
529     EXPECT_EQ(errCode, E_OK);
530     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING);
531     EXPECT_EQ(stepFour, true);
532 
533     /**
534      * @tc.steps: step5. Concurrently pause and abort dbTaskC in two thread
535      * @tc.expected: step5. thread can quit and dbTaskC ABORT_DONE
536      */
537     bool stepFive = ConcurrentPauseAndAbortThenCheckResult(vacuum, DB_IDENTITY_C);
538     EXPECT_EQ(stepFive, true);
539 }
540 
541 /**
542  * @tc.name: SingleTaskWriteHandleOccupy001
543  * @tc.desc: Test write handle occupy for single task under normal operation
544  * @tc.type: FUNC
545  * @tc.require: AR000C6TRV AR000CQDTM
546  * @tc.author: xiaozhenjian
547  */
548 HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskWriteHandleOccupy001, TestSize.Level2)
549 {
550     // Preset
551     MultiVerVacuum vacuum;
552     MultiVerVacuumExecutorStub databaseA(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
553 
554     /**
555      * @tc.steps: step1. launch dbTaskA for databaseA
556      * @tc.expected: step1. dbTaskA RUN_NING
557      */
558     int errCode = vacuum.Launch(DB_IDENTITY_A, &databaseA);
559     EXPECT_EQ(errCode, E_OK);
560     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
561     EXPECT_EQ(stepOne, true);
__anon19147f8f0a02()562     stepOne = RepeatCheckAsyncResult([&databaseA]()->bool {
563         return databaseA.IsTransactionOccupied() == true;
564     }, 5, 100); // 5 times, 100 ms
565     EXPECT_EQ(stepOne, true);
566 
567     /**
568      * @tc.steps: step2. pause dbTaskA
569      * @tc.expected: step2. dbTaskA PAUSE_DONE
570      */
571     errCode = vacuum.Pause(DB_IDENTITY_A);
572     EXPECT_EQ(errCode, E_OK);
573     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
574     EXPECT_EQ(stepTwo, true);
575     EXPECT_EQ(databaseA.IsTransactionOccupied(), false);
576 
577     /**
578      * @tc.steps: step3. Continue dbTaskA
579      * @tc.expected: step3. dbTaskA RUN_NING
580      */
581     errCode = vacuum.Continue(DB_IDENTITY_A, false);
582     EXPECT_EQ(errCode, E_OK);
583     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
584     EXPECT_EQ(stepThree, true);
__anon19147f8f0b02()585     stepThree = RepeatCheckAsyncResult([&databaseA]()->bool {
586         return databaseA.IsTransactionOccupied() == true;
587     }, 5, 100); // 5 times, 100 ms
588     EXPECT_EQ(stepThree, true);
589 
590     /**
591      * @tc.steps: step4. Abort dbTaskA
592      * @tc.expected: step4. dbTaskA ABORT_DONE
593      */
594     errCode = vacuum.Abort(DB_IDENTITY_A);
595     EXPECT_EQ(errCode, E_OK);
596     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
597     EXPECT_EQ(stepFour, true);
598     EXPECT_EQ(databaseA.IsTransactionOccupied(), false);
599 }
600 
601 /**
602  * @tc.name: MultipleTaskNormalStatusSwitch001
603  * @tc.desc: Test status switch for multiple task under normal operation
604  * @tc.type: FUNC
605  * @tc.require: AR000C6TRV AR000CQDTM
606  * @tc.author: xiaozhenjian
607  */
608 HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch001, TestSize.Level1)
609 {
610     // Preset
611     MultiVerVacuum vacuum;
612     MultiVerVacuumExecutorStub databaseA(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
613     MultiVerVacuumExecutorStub databaseB(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
614 
615     /**
616      * @tc.steps: step1. launch dbTaskA for databaseA and dbTaskB for databaseB
617      * @tc.expected: step1. dbTaskA RUN_NING and dbTaskB RUN_WAIT
618      */
619     int errCode = vacuum.Launch(DB_IDENTITY_A, &databaseA);
620     EXPECT_EQ(errCode, E_OK);
621     errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
622     EXPECT_EQ(errCode, E_OK);
623     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING);
624     EXPECT_EQ(stepOne, true);
625     stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_WAIT);
626     EXPECT_EQ(stepOne, true);
627 
628     /**
629      * @tc.steps: step2. pause dbTaskB
630      * @tc.expected: step2. dbTaskA RUN_NING and dbTaskB PAUSE_DONE
631      */
632     errCode = vacuum.Pause(DB_IDENTITY_B);
633     EXPECT_EQ(errCode, E_OK);
634     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING, 1); // only 1 time
635     EXPECT_EQ(stepTwo, true);
636     stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::PAUSE_DONE, 1); // only 1 time
637     EXPECT_EQ(stepTwo, true);
638     /**
639      * @tc.steps: step3. continue dbTaskB with autoRelaunch false
640      * @tc.expected: step3. dbTaskA RUN_NING and dbTaskB RUN_WAIT
641      */
642     errCode = vacuum.Continue(DB_IDENTITY_B, false);
643     EXPECT_EQ(errCode, E_OK);
644     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_NING, 1); // only 1 time
645     EXPECT_EQ(stepThree, true);
646     stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_WAIT, 1); // only 1 time
647     EXPECT_EQ(stepThree, true);
648 
649     /**
650      * @tc.steps: step4. Abort dbTaskA
651      * @tc.expected: step4. dbTaskA ABORT_DONE and dbTaskB RUN_NING
652      */
653     errCode = vacuum.Abort(DB_IDENTITY_A);
654     EXPECT_EQ(errCode, E_OK);
655     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
656     EXPECT_EQ(stepFour, true);
657     stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
658     EXPECT_EQ(stepFour, true);
659 
660     /**
661      * @tc.steps: step5. Abort dbTaskB
662      * @tc.expected: step5. dbTaskA ABORT_DONE and dbTaskB ABORT_DONE
663      */
664     errCode = vacuum.Abort(DB_IDENTITY_B);
665     EXPECT_EQ(errCode, E_OK);
666     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
667     EXPECT_EQ(stepFive, true);
668     stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
669     EXPECT_EQ(stepFive, true);
670 }
671 
672 /**
673  * @tc.name: MultipleTaskNormalStatusSwitch002
674  * @tc.desc: Test status switch for multiple task under normal operation
675  * @tc.type: FUNC
676  * @tc.require: AR000C6TRV AR000CQDTM
677  * @tc.author: xiaozhenjian
678  */
679 HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch002, TestSize.Level2)
680 {
681     // Preset
682     MultiVerVacuum vacuum;
683     MultiVerVacuumExecutorStub databaseA(DbScale {1, 1, 1, 1}, 30); // 1 For Scale, 30 For TimeCost, 330ms in Total
684     MultiVerVacuumExecutorStub databaseB(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
685     MultiVerVacuumExecutorStub databaseC(DbScale {1, 1, 2, 2}, 100); // 1, 2 For Scale, 100 For TimeCost, 1.7s in Total
686 
687     /**
688      * @tc.steps: step1. launch dbTaskA,B,C for databaseA,B,C and wait dbTaskA,B FINISH
689      * @tc.expected: step1. dbTaskA FINISH and dbTaskB FINISH and dbTaskC RUN_NING
690      */
691     int errCode = vacuum.Launch(DB_IDENTITY_A, &databaseA);
692     EXPECT_EQ(errCode, E_OK);
693     errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
694     EXPECT_EQ(errCode, E_OK);
695     errCode = vacuum.Launch(DB_IDENTITY_C, &databaseC);
696     EXPECT_EQ(errCode, E_OK);
697     bool stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
698     EXPECT_EQ(stepOne, true);
699     stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
700     EXPECT_EQ(stepOne, true);
701     stepOne = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING);
702     EXPECT_EQ(stepOne, true);
703 
704     /**
705      * @tc.steps: step2. abnormal operation, Launch dbTaskB again without abort dbTaskB
706      * @tc.expected: step2. dbTaskA FINISH and dbTaskB RUN_WAIT and dbTaskC RUN_NING
707      */
708     errCode = vacuum.Launch(DB_IDENTITY_B, &databaseB);
709     EXPECT_EQ(errCode, E_OK);
710     bool stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::FINISH, 1); // only 1 time
711     EXPECT_EQ(stepTwo, true);
712     stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_WAIT, 1); // only 1 time
713     EXPECT_EQ(stepTwo, true);
714     stepTwo = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING, 1); // only 1 time
715     EXPECT_EQ(stepTwo, true);
716 
717     /**
718      * @tc.steps: step3. AutoRelaunch dbTaskA
719      * @tc.expected: step3. dbTaskA RUN_WAIT and dbTaskB RUN_WAIT and dbTaskC RUN_NING
720      */
721     errCode = vacuum.AutoRelaunchOnce(DB_IDENTITY_A);
722     EXPECT_EQ(errCode, E_OK);
723     bool stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_WAIT, 1); // only 1 time
724     EXPECT_EQ(stepThree, true);
725     stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_WAIT, 1); // only 1 time
726     EXPECT_EQ(stepThree, true);
727     stepThree = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::RUN_NING, 1); // only 1 time
728     EXPECT_EQ(stepThree, true);
729 
730     /**
731      * @tc.steps: step4. wait dbTaskC FINISH
732      * @tc.expected: step4. dbTaskA RUN_WAIT and dbTaskB RUN_NING and dbTaskC FINISH
733      */
734     bool stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::FINISH, 3, 1000); // 3 time, 1000 ms
735     EXPECT_EQ(stepFour, true);
736     stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::RUN_WAIT, 1); // only 1 time
737     EXPECT_EQ(stepFour, true);
738     stepFour = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::RUN_NING);
739     EXPECT_EQ(stepFour, true);
740 
741     /**
742      * @tc.steps: step5. Abort dbTaskB and dbTaskB
743      * @tc.expected: step5. dbTaskA ABORT_DONE and dbTaskB ABORT_DONE and dbTaskC FINISH
744      */
745     vacuum.Abort(DB_IDENTITY_A);
746     vacuum.Abort(DB_IDENTITY_B);
747     bool stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_A, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
748     EXPECT_EQ(stepFive, true);
749     stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_B, VacuumTaskStatus::ABORT_DONE, 1); // only 1 time
750     EXPECT_EQ(stepFive, true);
751     stepFive = CheckVacuumTaskStatus(vacuum, DB_IDENTITY_C, VacuumTaskStatus::FINISH, 1); // only 1 time
752     EXPECT_EQ(stepFive, true);
753 }
754 #endif // OMIT_MULTI_VER
755