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