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 #include <cstdio>
17 #include <cstring>
18 #include <memory>
19 #include <sys/mman.h>
20 #include <sys/ioctl.h>
21 #include <thread>
22 #include <unistd.h>
23
24 #include <linux/ashmem.h>
25
26 #include "gtest/gtest.h"
27 #include "ashmem.h"
28 #include "securec.h"
29 #include "pm_util.h"
30
31 #define private public
32 #define protected public
33 #include "purgeable_ashmem.h"
34 #undef private
35 #undef protected
36
37 namespace OHOS {
38 namespace PurgeableMem {
39 using namespace testing;
40 using namespace testing::ext;
41
42 static constexpr int PRINT_INTERVAL_SECONDS = 1;
43 static constexpr int RECLAIM_INTERVAL_SECONDS = 1;
44 static constexpr int MODIFY_INTERVAL_SECONDS = 2;
45 void LoopPrintAlphabet(PurgeableAshMem *pdata, unsigned int loopCount);
46 bool ReclaimPurgeable(void);
47 void LoopReclaimPurgeable(unsigned int loopCount);
48 void ModifyPurgMemByBuilder(PurgeableAshMem *pdata, std::unique_ptr<PurgeableMemBuilder> mod);
49
50 class TestDataBuilder : public PurgeableMemBuilder {
51 public:
TestDataBuilder(char start,char end)52 TestDataBuilder(char start, char end)
53 {
54 this->start_ = start;
55 this->end_ = end;
56 }
57
Build(void * data,size_t size)58 bool Build(void *data, size_t size)
59 {
60 if (size <= 0) {
61 return true;
62 }
63 char *str = static_cast<char *>(data);
64 size_t len = 0;
65 for (char ch = start_; ch <= end_ && len < size; ch++) {
66 str[len++] = ch;
67 }
68 str[size - 1] = 0;
69 std::cout << "rebuild addr("<< (unsigned long long)str <<") " <<
70 start_ << "~" << end_ << ", data=[" << str << "]" << std::endl;
71 return true;
72 }
73
~TestDataBuilder()74 ~TestDataBuilder()
75 {
76 std::cout << "~TestDataBuilder" << std::endl;
77 }
78
79 private:
80 char start_;
81 char end_;
82 };
83
84 class TestDataModifier : public PurgeableMemBuilder {
85 public:
TestDataModifier(char from,char to)86 TestDataModifier(char from, char to)
87 {
88 this->from_ = from;
89 this->to_ = to;
90 }
91
Build(void * data,size_t size)92 bool Build(void *data, size_t size)
93 {
94 char *str = static_cast<char *>(data);
95 for (size_t i = 0; i < size && str[i]; i++) {
96 if (str[i] == from_) {
97 str[i] = to_;
98 }
99 }
100 return true;
101 }
102
~TestDataModifier()103 ~TestDataModifier()
104 {
105 std::cout << "~TestDataModifier" << std::endl;
106 }
107
108 private:
109 char from_;
110 char to_;
111 };
112
113 class TestBigDataBuilder : public PurgeableMemBuilder {
114 public:
TestBigDataBuilder(char target)115 explicit TestBigDataBuilder(char target)
116 {
117 this->target_ = target;
118 }
119
Build(void * data,size_t size)120 bool Build(void *data, size_t size)
121 {
122 if (size <= 0) {
123 return true;
124 }
125 char *str = static_cast<char *>(data);
126 size_t len = 0;
127 for (char ch = target_; len < size;) {
128 str[len++] = ch;
129 }
130 str[size - 1] = 0;
131 return true;
132 }
133
~TestBigDataBuilder()134 ~TestBigDataBuilder()
135 {
136 std::cout << "~TestBigDataBuilder" << std::endl;
137 }
138
139 private:
140 char target_;
141 };
142
143 class PurgeableAshmemTest : public testing::Test {
144 public:
145 static void SetUpTestCase();
146 static void TearDownTestCase();
147 void SetUp();
148 void TearDown();
149 };
150
SetUpTestCase()151 void PurgeableAshmemTest::SetUpTestCase()
152 {
153 }
154
TearDownTestCase()155 void PurgeableAshmemTest::TearDownTestCase()
156 {
157 }
158
SetUp()159 void PurgeableAshmemTest::SetUp()
160 {
161 }
162
TearDown()163 void PurgeableAshmemTest::TearDown()
164 {
165 }
166
167 HWTEST_F(PurgeableAshmemTest, KernelInterfaceTest, TestSize.Level1)
168 {
169 size_t size = 4096 * 100;
170 int fd = AshmemCreate("Purgeable Ashmem", size);
171 ASSERT_GT(fd, 0);
172 if (AshmemSetProt(fd, PROT_READ | PROT_WRITE) < 0) {
173 close(fd);
174 return;
175 }
176 void *dataPtr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
177 if (dataPtr == MAP_FAILED) {
178 dataPtr = nullptr;
179 close(fd);
180 return;
181 }
182 char *str = static_cast<char *>(dataPtr);
183 for (size_t i = 0; i < size; i++) {
184 str[i] = 'a';
185 }
186 str[size - 1] = '\0';
187 ashmem_pin pin_ = { static_cast<uint32_t>(0), static_cast<uint32_t>(0) };
188 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PURGEABLE), -1);
189 EXPECT_EQ(ioctl(fd, ASHMEM_SET_PURGEABLE), 0);
190 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PURGEABLE), 1);
191 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
192 ioctl(fd, ASHMEM_PIN, &pin_);
193 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 2);
194 ioctl(fd, ASHMEM_PIN, &pin_);
195 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 3);
196 ioctl(fd, ASHMEM_UNPIN, &pin_);
197 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 2);
198 ioctl(fd, ASHMEM_UNPIN, &pin_);
199 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
200 EXPECT_EQ(ioctl(fd, ASHMEM_PURGE_ALL_CACHES), 0);
201 EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
202 ioctl(fd, ASHMEM_UNPIN, &pin_);
203 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 0);
204 EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
205 ioctl(fd, ASHMEM_PURGE_ALL_CACHES);
206 EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 1);
207 ioctl(fd, ASHMEM_PIN, &pin_);
208 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
209 EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 1);
210 ioctl(fd, ASHMEM_UNPIN, &pin_);
211 EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 0);
212 ioctl(fd, PURGEABLE_ASHMEM_REBUILD_SUCCESS);
213 EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
214 }
215
216 HWTEST_F(PurgeableAshmemTest, MultiObjCreateTest, TestSize.Level1)
217 {
218 const char alphabetFinal[] = "BBCDEFGHIJKLMNOPQRSTUVWXYZ\0";
219 std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
220 std::unique_ptr<PurgeableMemBuilder> builder2 = std::make_unique<TestDataBuilder>('A', 'Z');
221 std::unique_ptr<PurgeableMemBuilder> mod1 = std::make_unique<TestDataModifier>('A', 'B');
222 std::unique_ptr<PurgeableMemBuilder> mod2 = std::make_unique<TestDataModifier>('A', 'B');
223
224 PurgeableAshMem pobj1(27, std::move(builder1));
225 LoopPrintAlphabet(&pobj1, 1);
226 ModifyPurgMemByBuilder(&pobj1, std::move(mod1));
227 LoopPrintAlphabet(&pobj1, 1);
228 LoopReclaimPurgeable(1);
229
230 PurgeableAshMem pobj2(27, std::move(builder2));
231 LoopPrintAlphabet(&pobj2, 1);
232 ModifyPurgMemByBuilder(&pobj2, std::move(mod2));
233 LoopPrintAlphabet(&pobj2, 1);
234 LoopReclaimPurgeable(1);
235
236 int ret1 = 1;
237 int ret2 = 1;
238 int times1 = 0;
239 int times2 = 0;
240 while (times1++ < 10) {
241 if (pobj1.BeginRead()) {
242 ret1 = strncmp(alphabetFinal, static_cast<char *>(pobj1.GetContent()), 26);
243 pobj1.EndRead();
244 break;
245 } else {
246 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
247 }
248 }
249
250 while (times2++ < 10) {
251 if (pobj2.BeginRead()) {
252 ret2 = strncmp(alphabetFinal, static_cast<char *>(pobj2.GetContent()), 26);
253 pobj2.EndRead();
254 break;
255 } else {
256 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
257 }
258 }
259
260 EXPECT_EQ(ret1, 0);
261 EXPECT_EQ(ret2, 0);
262 }
263
264 HWTEST_F(PurgeableAshmemTest, ReadTest, TestSize.Level1)
265 {
266 const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\0";
267 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
268 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
269 ASSERT_NE(pobj, nullptr);
270 LoopReclaimPurgeable(1);
271
272 int times = 0;
273 int ret = 1;
274 while (times++ < 10) {
275 if (pobj->BeginRead()) {
276 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
277 pobj->EndRead();
278 break;
279 } else {
280 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
281 }
282 }
283 delete pobj;
284 pobj = nullptr;
285 EXPECT_EQ(ret, 0);
286 }
287
288 HWTEST_F(PurgeableAshmemTest, WriteTest, TestSize.Level1)
289 {
290 const char alphabet[] = "CCCDEFGHIJKLMNOPQRSTUVWXYZ\0";
291 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
292 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
293 ASSERT_NE(pobj, nullptr);
294 LoopReclaimPurgeable(1);
295
296 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
297 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
298 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
299 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
300
301 int times = 0;
302 int ret = 1;
303 while (times++ < 10) {
304 if (pobj->BeginRead()) {
305 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
306 pobj->EndRead();
307 break;
308 } else {
309 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
310 }
311 }
312 delete pobj;
313 pobj = nullptr;
314 EXPECT_EQ(ret, 0);
315 }
316
317 HWTEST_F(PurgeableAshmemTest, ReadWriteTest, TestSize.Level1)
318 {
319 const char alphabet[] = "DDDDEFGHIJKLMNOPQRSTUVWXYZ\0";
320 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
321 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
322 ASSERT_NE(pobj, nullptr);
323
324 LoopReclaimPurgeable(1);
325 LoopPrintAlphabet(pobj, 1);
326
327 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
328 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
329 std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
330 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
331 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
332 ModifyPurgMemByBuilder(pobj, std::move(modC2D));
333
334 int times = 0;
335 int ret = 1;
336 while (times++ < 10) {
337 if (pobj->BeginRead()) {
338 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
339 pobj->EndRead();
340 break;
341 } else {
342 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
343 }
344 }
345 delete pobj;
346 pobj = nullptr;
347 EXPECT_EQ(ret, 0);
348 }
349
350 HWTEST_F(PurgeableAshmemTest, MutiPageReadTest, TestSize.Level1)
351 {
352 char alphabet[4098];
353 size_t len = 0;
354 for (char ch = 'A'; len < 4098;) {
355 alphabet[len++] = ch;
356 }
357 alphabet[4097] = 0;
358 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
359 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
360 ASSERT_NE(pobj, nullptr);
361
362 LoopReclaimPurgeable(1);
363
364 int times = 0;
365 int ret = 1;
366 while (times++ < 10) {
367 if (pobj->BeginRead()) {
368 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
369 pobj->EndRead();
370 break;
371 } else {
372 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
373 }
374 }
375 delete pobj;
376 pobj = nullptr;
377 EXPECT_EQ(ret, 0);
378 }
379
380 HWTEST_F(PurgeableAshmemTest, MutiPageWriteTest, TestSize.Level1)
381 {
382 char alphabet[4098];
383 size_t len = 0;
384 for (char ch = 'C'; len < 4098;) {
385 alphabet[len++] = ch;
386 }
387 alphabet[4097] = 0;
388 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
389 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
390 ASSERT_NE(pobj, nullptr);
391
392 LoopReclaimPurgeable(1);
393
394 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
395 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
396 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
397 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
398
399 int times = 0;
400 int ret = 1;
401 while (times++ < 10) {
402 if (pobj->BeginRead()) {
403 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
404 pobj->EndRead();
405 break;
406 } else {
407 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
408 }
409 }
410 delete pobj;
411 pobj = nullptr;
412 EXPECT_EQ(ret, 0);
413 }
414
415 HWTEST_F(PurgeableAshmemTest, MutiPageReadWriteTest, TestSize.Level1)
416 {
417 char alphabet[4098];
418 size_t len = 0;
419 for (char ch = 'D'; len < 4098;) {
420 alphabet[len++] = ch;
421 }
422 alphabet[4097] = 0;
423 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
424 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
425 ASSERT_NE(pobj, nullptr);
426 LoopReclaimPurgeable(1);
427 LoopPrintAlphabet(pobj, 1);
428
429 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
430 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
431 std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
432 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
433 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
434 ModifyPurgMemByBuilder(pobj, std::move(modC2D));
435
436 int times = 0;
437 int ret = 1;
438 while (times++ < 10) {
439 if (pobj->BeginRead()) {
440 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
441 pobj->EndRead();
442 break;
443 } else {
444 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
445 }
446 }
447 delete pobj;
448 pobj = nullptr;
449 EXPECT_EQ(ret, 0);
450 }
451
452 HWTEST_F(PurgeableAshmemTest, MutiMorePageReadWriteTest, TestSize.Level1)
453 {
454 size_t size = 5 * 1024 * 1024;
455 char *alphabet = static_cast<char *>(malloc(size));
456 size_t len = 0;
457 for (char ch = 'D'; len < size;) {
458 alphabet[len++] = ch;
459 }
460 alphabet[size - 1] = 0;
461 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
462 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(size, std::move(builder));
463 ASSERT_NE(pobj, nullptr);
464
465 LoopReclaimPurgeable(1);
466 LoopPrintAlphabet(pobj, 1);
467
468 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
469 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
470 std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
471 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
472 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
473 ModifyPurgMemByBuilder(pobj, std::move(modC2D));
474
475 int times = 0;
476 int ret = 1;
477 while (times++ < 10) {
478 if (pobj->BeginRead()) {
479 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), size - 1);
480 pobj->EndRead();
481 break;
482 } else {
483 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
484 }
485 }
486 delete pobj;
487 pobj = nullptr;
488 free(alphabet);
489 alphabet = nullptr;
490 EXPECT_EQ(ret, 0);
491 }
492
493 HWTEST_F(PurgeableAshmemTest, StableMutiMorePageReadWriteTest, TestSize.Level1)
494 {
495 size_t size = 5 * 1024 * 1024;
496 char *alphabet = static_cast<char *>(malloc(size));
497 size_t len = 0;
498 for (char ch = 'D'; len < size;) {
499 alphabet[len++] = ch;
500 }
501 alphabet[size - 1] = 0;
502 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
503 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(size, std::move(builder));
504 ASSERT_NE(pobj, nullptr);
505
506 std::thread reclaimThread(LoopReclaimPurgeable, 10);
507 std::thread readThread(LoopPrintAlphabet, pobj, 10);
508
509 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
510 std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
511 std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
512 ModifyPurgMemByBuilder(pobj, std::move(modA2B));
513 ModifyPurgMemByBuilder(pobj, std::move(modB2C));
514 ModifyPurgMemByBuilder(pobj, std::move(modC2D));
515
516 int times = 0;
517 int ret = 1;
518 while (times++ < 10) {
519 if (pobj->BeginRead()) {
520 ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), size - 1);
521 pobj->EndRead();
522 break;
523 } else {
524 std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
525 }
526 }
527 reclaimThread.join();
528 readThread.join();
529 delete pobj;
530 pobj = nullptr;
531 free(alphabet);
532 alphabet = nullptr;
533 EXPECT_EQ(ret, 0);
534 }
535
536 HWTEST_F(PurgeableAshmemTest, InvalidInputSizeTest, TestSize.Level1)
537 {
538 std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
539 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(0, std::move(builder));
540 ASSERT_NE(pobj, nullptr);
541 bool ret = pobj->BeginRead();
542 if (ret) {
543 pobj->EndRead();
544 }
545 delete pobj;
546 pobj = nullptr;
547 EXPECT_EQ(ret, false);
548 }
549
550 HWTEST_F(PurgeableAshmemTest, InvalidInputBuilderTest, TestSize.Level1)
551 {
552 PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, nullptr);
553 ASSERT_NE(pobj, nullptr);
554 bool ret = pobj->BeginRead();
555 if (ret) {
556 pobj->EndRead();
557 }
558 delete pobj;
559 pobj = nullptr;
560 EXPECT_EQ(ret, false);
561 }
562
563 HWTEST_F(PurgeableAshmemTest, IsPurgedTest, TestSize.Level1)
564 {
565 std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
566 std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
567 PurgeableAshMem pobj(std::move(builder1));
568 pobj.isSupport_ = 0;
569 EXPECT_EQ(pobj.IsPurged(), false);
570 EXPECT_EQ(pobj.Pin(), true);
571 EXPECT_EQ(pobj.Unpin(), true);
572 EXPECT_EQ(pobj.GetPinStatus(), false);
573 pobj.isSupport_ = 1;
574 pobj.ashmemFd_ = 0;
575 EXPECT_EQ(pobj.Pin(), false);
576 EXPECT_EQ(pobj.Unpin(), false);
577 pobj.dataSizeInput_ = 0;
578 EXPECT_EQ(pobj.CreatePurgeableData(), false);
579 pobj.dataPtr_ = nullptr;
580 ModifyPurgMemByBuilder(&pobj, std::move(modA2B));
581 pobj.isDataValid_ = false;
582 pobj.BeginRead();
583 pobj.isDataValid_ = true;
584 pobj.EndRead();
585 }
586
587 HWTEST_F(PurgeableAshmemTest, GetPinStatusTest, TestSize.Level1)
588 {
589 std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
590 PurgeableAshMem pobj(std::move(builder1));
591 pobj.isSupport_ = 1;
592 EXPECT_NE(pobj.GetPinStatus(), 0);
593 pobj.isSupport_ = 0;
594 EXPECT_EQ(pobj.GetPinStatus(), 0);
595 }
596
597 HWTEST_F(PurgeableAshmemTest, ChangeAshmemDataTest, TestSize.Level1)
598 {
599 std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
600 PurgeableAshMem pobj1(27, std::move(builder1));
601 PurgeableAshMem pobj2(27, std::move(builder1));
602 PurgeableAshMem pobj3(27, std::move(builder1));
603 PurgeableAshMem pobj4(27, std::move(builder1));
604 size_t newSize = 0;
605 size_t size = 123;
606 int fd = 5;
607 int intdata = 12345;
608 void *data = &intdata;
609 size_t pageSize = PAGE_SIZE;
610 pobj1.ResizeData(newSize);
611 newSize = 1;
612 pobj1.ResizeData(newSize);
613 pobj2.ashmemFd_ = 0;
614 pobj2.ResizeData(newSize);
615 pobj2.dataPtr_ = data;
616 pobj2.ResizeData(newSize);
617
618 pobj3.ChangeAshmemData(size, fd, data);
619 pobj4.ashmemFd_ = 0;
620 pobj4.ChangeAshmemData(size, fd, data);
621 pobj4.dataPtr_ = data;
622 pobj4.ChangeAshmemData(size, fd, data);
623 size = ((pobj4.dataSizeInput_ + pageSize - 1) / pageSize) * pageSize;
624 fd = AshmemCreate("PurgeableAshmem", size);
625 EXPECT_EQ(pobj4.ChangeAshmemData(size, fd, data), true);
626 }
627
628 HWTEST_F(PurgeableAshmemTest, GetContentSizeTest, TestSize.Level1)
629 {
630 std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
631 PurgeableAshMem pobj(27, std::move(builder1));
632 EXPECT_EQ(pobj.GetContentSize(), 27);
633 bool target = true;
634 pobj.SetDataValid(target);
635 EXPECT_EQ(pobj.IsDataValid(), target);
636 EXPECT_NE(pobj.GetAshmemFd(), -1);
637 }
638
LoopPrintAlphabet(PurgeableAshMem * pdata,unsigned int loopCount)639 void LoopPrintAlphabet(PurgeableAshMem *pdata, unsigned int loopCount)
640 {
641 std::cout << "inter " << __func__ << std::endl;
642 for (unsigned int i = 0; i < loopCount; i++) {
643 if (!pdata->BeginRead()) {
644 std::cout << __func__ << ": " << i << ". ERROR! BeginRead failed." << std::endl;
645 break;
646 }
647 pdata->EndRead();
648 std::this_thread::sleep_for(std::chrono::seconds(PRINT_INTERVAL_SECONDS));
649 }
650 std::cout << "quit " << __func__ << std::endl;
651 }
652
ReclaimPurgeable(void)653 bool ReclaimPurgeable(void)
654 {
655 FILE *f = fopen("/proc/sys/vm/drop_caches", "w");
656 if (!f) {
657 std::cout << __func__ << ": kernel not support" << std::endl;
658 return false;
659 }
660 bool succ = true;
661 if (fputs("3", f) == EOF) {
662 succ = false;
663 }
664
665 if (fclose(f) == EOF) {
666 std::cout << __func__ << ": close file failed" << std::endl;
667 }
668
669 return succ;
670 }
671
LoopReclaimPurgeable(unsigned int loopCount)672 void LoopReclaimPurgeable(unsigned int loopCount)
673 {
674 bool ret = false;
675 std::cout << "inter " << __func__ << std::endl;
676 for (unsigned int i = 0; i < loopCount; i++) {
677 ret = ReclaimPurgeable();
678 std::cout << __func__ << ": " << i << ". Reclaim result=" << (ret ? "succ" : "fail") << std::endl;
679 std::this_thread::sleep_for(std::chrono::seconds(RECLAIM_INTERVAL_SECONDS)); /* wait reclaim finish */
680 }
681 std::cout << "quit " << __func__ << std::endl;
682 }
683
ModifyPurgMemByBuilder(PurgeableAshMem * pdata,std::unique_ptr<PurgeableMemBuilder> mod)684 void ModifyPurgMemByBuilder(PurgeableAshMem *pdata, std::unique_ptr<PurgeableMemBuilder> mod)
685 {
686 if (!pdata->BeginWrite()) {
687 std::cout << __func__ << ": ERROR! BeginWrite failed." << std::endl;
688 return;
689 }
690 std::this_thread::sleep_for(std::chrono::seconds(MODIFY_INTERVAL_SECONDS));
691 pdata->ModifyContentByBuilder(std::move(mod));
692 pdata->EndWrite();
693 }
694 } /* namespace PurgeableAshMem */
695 } /* namespace OHOS */
696