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