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