/* * Copyright (c) 2023-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "securec.h" #define PAGE_SIZE 4096 using namespace testing::ext; using namespace std; class MadviseApiTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); void SetUp(); void TearDown(); private: }; void MadviseApiTest::SetUp() { } void MadviseApiTest::TearDown() { } void MadviseApiTest::SetUpTestCase() { } void MadviseApiTest::TearDownTestCase() { } static void CreateFile() { FILE *file; int ret = -1; char *buffer = static_cast(malloc(PAGE_SIZE)); if (buffer != nullptr) { ret = memset_s(buffer, PAGE_SIZE, 'a', PAGE_SIZE); ASSERT_TRUE(ret == 0); file = fopen("output_file.txt", "wb"); if (fwrite(buffer, 1, PAGE_SIZE, file) != PAGE_SIZE) { std::cout << "Error fwrite file.\n" << std::endl; ASSERT_TRUE(ret != 0); } fclose(file); } free(buffer); } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0100 * @tc.name MadviseMadvCold001 * @tc.desc MADV_COLD with MAP_PRIVATE */ HWTEST_F(MadviseApiTest, MadviseMadvCold001, Function | MediumTest | Level1) { void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ASSERT_TRUE(addr != MAP_FAILED); int err = madvise(addr, PAGE_SIZE, MADV_COLD); ASSERT_TRUE(err == 0); int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0200 * @tc.name MadviseMadvCold002 * @tc.desc MADV_COLD with MAP_SHARED */ HWTEST_F(MadviseApiTest, MadviseMadvCold002, Function | MediumTest | Level1) { CreateFile(); int fd = open("output_file.txt", O_RDWR); ASSERT_TRUE(fd > 0); void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); ASSERT_TRUE(addr != MAP_FAILED); int ret = madvise(addr, PAGE_SIZE, MADV_COLD); ASSERT_TRUE(ret == 0); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; close(fd); ret = unlink("output_file.txt"); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0300 * @tc.name MadviseMadvCold003 * @tc.desc MADV_COLD with mlock MAP_PRIVATE FILE */ HWTEST_F(MadviseApiTest, MadviseMadvCold003, Function | MediumTest | Level1) { CreateFile(); int fd = open("output_file.txt", O_RDWR); ASSERT_TRUE(fd > 0); void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); ASSERT_TRUE(addr != MAP_FAILED); int ret = mlock(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_COLD); ASSERT_TRUE(ret == -1); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; close(fd); ret = unlink("output_file.txt"); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0400 * @tc.name MadviseMadvCold004 * @tc.desc MADV_COLD with mlock MAP_PRIVATE anon */ HWTEST_F(MadviseApiTest, MadviseMadvCold004, Function | MediumTest | Level1) { void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ASSERT_TRUE(addr != MAP_FAILED); int ret = mlock(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_COLD); ASSERT_TRUE(ret == -1); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0500 * @tc.name MadviseMadvPageOut001 * @tc.desc MADV_PAGEOUT with MAP_PRIVATE anon */ HWTEST_F(MadviseApiTest, MadviseMadvPageOut001, Function | MediumTest | Level1) { int ret = -1; void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ASSERT_TRUE(addr != MAP_FAILED); ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); ASSERT_TRUE(ret == 0); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0600 * @tc.name MadviseMadvPageOut002 * @tc.desc MADV_PAGEOUT with MAP_SHARED FILE */ HWTEST_F(MadviseApiTest, MadviseMadvPageOut002, Function | MediumTest | Level1) { CreateFile(); int fd = open("output_file.txt", O_RDWR); ASSERT_TRUE(fd > 0); void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); ASSERT_TRUE(addr != MAP_FAILED); int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); ASSERT_TRUE(ret == 0); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); close(fd); ret = unlink("output_file.txt"); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0700 * @tc.name MadviseMadvPageOut003 * @tc.desc MADV_PAGEOUT with mlock MAP_SHARED FILE */ HWTEST_F(MadviseApiTest, MadviseMadvPageOut003, Function | MediumTest | Level1) { CreateFile(); int fd = open("output_file.txt", O_RDWR); ASSERT_TRUE(fd > 0); void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); ASSERT_TRUE(addr != MAP_FAILED); int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = mlock(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); ASSERT_TRUE(ret == -1); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); close(fd); ret = unlink("output_file.txt"); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0800 * @tc.name MadviseMadvPageOut004 * @tc.desc MADV_PAGEOUT with mlock MAP_PRIVATE anon */ HWTEST_F(MadviseApiTest, MadviseMadvPageOut004, Function | MediumTest | Level1) { int ret = -2; void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ASSERT_TRUE(addr != MAP_FAILED); ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = mlock(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); ASSERT_TRUE(ret == -1); ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_0900 * @tc.name MadviseMadvWipeOnFork001 * @tc.desc MADV_WIPEONFORK with MAP_PRIVATE anon */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork001, Function | MediumTest | Level1) { int status = 0; char *addr = static_cast(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); ASSERT_TRUE(addr != MAP_FAILED); *addr = 'A'; int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); if (pid == 0) { ASSERT_TRUE(*addr == 0); exit(0); } else { ASSERT_TRUE(*addr == 'A'); waitpid(0, &status, 0); } int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_1000 * @tc.name MadviseMadvWipeOnFork002 * @tc.desc MADV_WIPEONFORK with MAP_SHARED */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork002, Function | MediumTest | Level1) { void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); ASSERT_TRUE(addr != MAP_FAILED); int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == -1); int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_1100 * @tc.name MadviseMadvWipeOnFork003 * @tc.desc MADV_KEEPONFORK after MADV_WIPEONFORK */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork003, Function | MediumTest | Level1) { int status = 0; char *addr = static_cast(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); ASSERT_TRUE(addr != MAP_FAILED); *addr = 'A'; int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK); ASSERT_TRUE(err == 0); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); if (pid == 0) { ASSERT_TRUE(*addr == 'A'); exit(0); } else { ASSERT_TRUE(*addr == 'A'); waitpid(0, &status, 0); } int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_1200 * @tc.name MadviseMadvWipeOnFork004 * @tc.desc next vregion is no MADV_WIPEONFORK */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork004, Function | MediumTest | Level1) { int status = 0; char *addr = static_cast(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); ASSERT_TRUE(addr != MAP_FAILED); char *nextAddr = static_cast(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); ASSERT_TRUE(nextAddr != MAP_FAILED); *addr = 'A'; *nextAddr = 'B'; int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); if (pid == 0) { ASSERT_TRUE(*addr == 0); ASSERT_TRUE(*nextAddr == 'B'); exit(0); } else { ASSERT_TRUE(*addr == 'A'); ASSERT_TRUE(*nextAddr == 'B'); waitpid(0, &status, 0); } int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = munmap(nextAddr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; nextAddr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_1300 * @tc.name MadviseMadvWipeOnFork005 * @tc.desc next vregion is MADV_WIPEONFORK */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork005, Function | MediumTest | Level1) { int status = 0; char *addr = static_cast(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); ASSERT_TRUE(addr != MAP_FAILED); char *nextAddr = static_cast(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); ASSERT_TRUE(nextAddr != MAP_FAILED); *addr = 'A'; *nextAddr = 'B'; int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); if (pid == 0) { ASSERT_TRUE(*addr == 0); ASSERT_TRUE(*nextAddr == 0); exit(0); } else { ASSERT_TRUE(*addr == 'A'); ASSERT_TRUE(*nextAddr == 'B'); waitpid(0, &status, 0); } int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = munmap(nextAddr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; nextAddr = nullptr; } /* * @tc.number SUB_KERNEL_MEM_MADVISE_1400 * @tc.name MadviseMadvWipeOnFork006 * @tc.desc next vregion is MADV_KEEPONFORK */ HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork006, Function | MediumTest | Level1) { int status = 0; char *addr = static_cast(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); ASSERT_TRUE(addr != MAP_FAILED); char *nextAddr = static_cast(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); ASSERT_TRUE(nextAddr != MAP_FAILED); *addr = 'A'; *nextAddr = 'B'; int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK); ASSERT_TRUE(err == 0); err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK); ASSERT_TRUE(err == 0); err = madvise(nextAddr, PAGE_SIZE, MADV_KEEPONFORK); ASSERT_TRUE(err == 0); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); if (pid == 0) { ASSERT_TRUE(*addr == 'A'); ASSERT_TRUE(*nextAddr == 'B'); exit(0); } else { ASSERT_TRUE(*addr == 'A'); ASSERT_TRUE(*nextAddr == 'B'); waitpid(0, &status, 0); } int ret = munmap(addr, PAGE_SIZE); ASSERT_TRUE(ret == 0); ret = munmap(nextAddr, PAGE_SIZE); ASSERT_TRUE(ret == 0); addr = nullptr; nextAddr = nullptr; }