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
37namespace OHOS {
38namespace PurgeableMem {
39using namespace testing;
40using namespace testing::ext;
41
42static constexpr int PRINT_INTERVAL_SECONDS = 1;
43static constexpr int RECLAIM_INTERVAL_SECONDS = 1;
44static constexpr int MODIFY_INTERVAL_SECONDS = 2;
45void LoopPrintAlphabet(PurgeableAshMem *pdata, unsigned int loopCount);
46bool ReclaimPurgeable(void);
47void LoopReclaimPurgeable(unsigned int loopCount);
48void ModifyPurgMemByBuilder(PurgeableAshMem *pdata, std::unique_ptr<PurgeableMemBuilder> mod);
49
50class TestDataBuilder : public PurgeableMemBuilder {
51public:
52    TestDataBuilder(char start, char end)
53    {
54        this->start_ = start;
55        this->end_ = end;
56    }
57
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
74    ~TestDataBuilder()
75    {
76        std::cout << "~TestDataBuilder" << std::endl;
77    }
78
79private:
80    char start_;
81    char end_;
82};
83
84class TestDataModifier : public PurgeableMemBuilder {
85public:
86    TestDataModifier(char from, char to)
87    {
88        this->from_ = from;
89        this->to_ = to;
90    }
91
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
103    ~TestDataModifier()
104    {
105        std::cout << "~TestDataModifier" << std::endl;
106    }
107
108private:
109    char from_;
110    char to_;
111};
112
113class TestBigDataBuilder : public PurgeableMemBuilder {
114public:
115    explicit TestBigDataBuilder(char target)
116    {
117        this->target_ = target;
118    }
119
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
134    ~TestBigDataBuilder()
135    {
136        std::cout << "~TestBigDataBuilder" << std::endl;
137    }
138
139private:
140    char target_;
141};
142
143class PurgeableAshmemTest : public testing::Test {
144public:
145    static void SetUpTestCase();
146    static void TearDownTestCase();
147    void SetUp();
148    void TearDown();
149};
150
151void PurgeableAshmemTest::SetUpTestCase()
152{
153}
154
155void PurgeableAshmemTest::TearDownTestCase()
156{
157}
158
159void PurgeableAshmemTest::SetUp()
160{
161}
162
163void PurgeableAshmemTest::TearDown()
164{
165}
166
167HWTEST_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
216HWTEST_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
264HWTEST_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
288HWTEST_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
317HWTEST_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
350HWTEST_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
380HWTEST_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
415HWTEST_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
452HWTEST_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
493HWTEST_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
536HWTEST_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
550HWTEST_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
563HWTEST_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
587HWTEST_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
597HWTEST_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
628HWTEST_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
639void 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
653bool 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
672void 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
684void 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