1/* 2 * Copyright (c) 2023-2024 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 <gtest/gtest.h> 17#include <fcntl.h> 18#include <cinttypes> 19#include <climits> 20#include <cstdio> 21#include <cstdlib> 22#include <unistd.h> 23#include <iomanip> 24#include <iostream> 25#include <string> 26#include <vector> 27#include <sys/mman.h> 28#include <sys/utsname.h> 29#include <string> 30#include <regex> 31#include "securec.h" 32 33#define PAGE_SIZE 4096 34 35 36using namespace testing::ext; 37using namespace std; 38 39class MadviseApiTest : public testing::Test { 40public: 41 static void SetUpTestCase(); 42 static void TearDownTestCase(); 43 void SetUp(); 44 void TearDown(); 45private: 46}; 47void MadviseApiTest::SetUp() 48{ 49} 50void MadviseApiTest::TearDown() 51{ 52} 53void MadviseApiTest::SetUpTestCase() 54{ 55} 56void MadviseApiTest::TearDownTestCase() 57{ 58} 59 60static void CreateFile() 61{ 62 FILE *file; 63 int ret = -1; 64 char *buffer = static_cast<char *>(malloc(PAGE_SIZE)); 65 if (buffer != nullptr) { 66 ret = memset_s(buffer, PAGE_SIZE, 'a', PAGE_SIZE); 67 ASSERT_TRUE(ret == 0); 68 file = fopen("output_file.txt", "wb"); 69 if (fwrite(buffer, 1, PAGE_SIZE, file) != PAGE_SIZE) { 70 std::cout << "Error fwrite file.\n" << std::endl; 71 ASSERT_TRUE(ret != 0); 72 } 73 fclose(file); 74 } 75 free(buffer); 76} 77 78/* 79 * @tc.number SUB_KERNEL_MEM_MADVISE_0100 80 * @tc.name MadviseMadvCold001 81 * @tc.desc MADV_COLD with MAP_PRIVATE 82*/ 83HWTEST_F(MadviseApiTest, MadviseMadvCold001, Function | MediumTest | Level1) 84{ 85 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 86 ASSERT_TRUE(addr != MAP_FAILED); 87 int err = madvise(addr, PAGE_SIZE, MADV_COLD); 88 ASSERT_TRUE(err == 0); 89 int ret = munmap(addr, PAGE_SIZE); 90 ASSERT_TRUE(ret == 0); 91 addr = nullptr; 92} 93 94/* 95 * @tc.number SUB_KERNEL_MEM_MADVISE_0200 96 * @tc.name MadviseMadvCold002 97 * @tc.desc MADV_COLD with MAP_SHARED 98*/ 99HWTEST_F(MadviseApiTest, MadviseMadvCold002, Function | MediumTest | Level1) 100{ 101 CreateFile(); 102 int fd = open("output_file.txt", O_RDWR); 103 ASSERT_TRUE(fd > 0); 104 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); 105 ASSERT_TRUE(addr != MAP_FAILED); 106 int ret = madvise(addr, PAGE_SIZE, MADV_COLD); 107 ASSERT_TRUE(ret == 0); 108 ret = munmap(addr, PAGE_SIZE); 109 ASSERT_TRUE(ret == 0); 110 addr = nullptr; 111 close(fd); 112 ret = unlink("output_file.txt"); 113 ASSERT_TRUE(ret == 0); 114 addr = nullptr; 115} 116 117/* 118 * @tc.number SUB_KERNEL_MEM_MADVISE_0300 119 * @tc.name MadviseMadvCold003 120 * @tc.desc MADV_COLD with mlock MAP_PRIVATE FILE 121*/ 122HWTEST_F(MadviseApiTest, MadviseMadvCold003, Function | MediumTest | Level1) 123{ 124 CreateFile(); 125 int fd = open("output_file.txt", O_RDWR); 126 ASSERT_TRUE(fd > 0); 127 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); 128 ASSERT_TRUE(addr != MAP_FAILED); 129 int ret = mlock(addr, PAGE_SIZE); 130 ASSERT_TRUE(ret == 0); 131 ret = madvise(addr, PAGE_SIZE, MADV_COLD); 132 ASSERT_TRUE(ret == -1); 133 ret = munmap(addr, PAGE_SIZE); 134 ASSERT_TRUE(ret == 0); 135 addr = nullptr; 136 close(fd); 137 ret = unlink("output_file.txt"); 138 ASSERT_TRUE(ret == 0); 139 addr = nullptr; 140} 141 142/* 143 * @tc.number SUB_KERNEL_MEM_MADVISE_0400 144 * @tc.name MadviseMadvCold004 145 * @tc.desc MADV_COLD with mlock MAP_PRIVATE anon 146*/ 147HWTEST_F(MadviseApiTest, MadviseMadvCold004, Function | MediumTest | Level1) 148{ 149 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 150 ASSERT_TRUE(addr != MAP_FAILED); 151 int ret = mlock(addr, PAGE_SIZE); 152 ASSERT_TRUE(ret == 0); 153 ret = madvise(addr, PAGE_SIZE, MADV_COLD); 154 ASSERT_TRUE(ret == -1); 155 ret = munmap(addr, PAGE_SIZE); 156 ASSERT_TRUE(ret == 0); 157 addr = nullptr; 158} 159 160/* 161 * @tc.number SUB_KERNEL_MEM_MADVISE_0500 162 * @tc.name MadviseMadvPageOut001 163 * @tc.desc MADV_PAGEOUT with MAP_PRIVATE anon 164*/ 165HWTEST_F(MadviseApiTest, MadviseMadvPageOut001, Function | MediumTest | Level1) 166{ 167 int ret = -1; 168 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 169 ASSERT_TRUE(addr != MAP_FAILED); 170 ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); 171 ASSERT_TRUE(ret == 0); 172 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); 173 ASSERT_TRUE(ret == 0); 174 ret = munmap(addr, PAGE_SIZE); 175 ASSERT_TRUE(ret == 0); 176 addr = nullptr; 177} 178 179/* 180 * @tc.number SUB_KERNEL_MEM_MADVISE_0600 181 * @tc.name MadviseMadvPageOut002 182 * @tc.desc MADV_PAGEOUT with MAP_SHARED FILE 183*/ 184HWTEST_F(MadviseApiTest, MadviseMadvPageOut002, Function | MediumTest | Level1) 185{ 186 CreateFile(); 187 int fd = open("output_file.txt", O_RDWR); 188 ASSERT_TRUE(fd > 0); 189 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); 190 ASSERT_TRUE(addr != MAP_FAILED); 191 int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); 192 ASSERT_TRUE(ret == 0); 193 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); 194 ASSERT_TRUE(ret == 0); 195 ret = munmap(addr, PAGE_SIZE); 196 ASSERT_TRUE(ret == 0); 197 close(fd); 198 ret = unlink("output_file.txt"); 199 ASSERT_TRUE(ret == 0); 200 addr = nullptr; 201} 202 203/* 204 * @tc.number SUB_KERNEL_MEM_MADVISE_0700 205 * @tc.name MadviseMadvPageOut003 206 * @tc.desc MADV_PAGEOUT with mlock MAP_SHARED FILE 207*/ 208HWTEST_F(MadviseApiTest, MadviseMadvPageOut003, Function | MediumTest | Level1) 209{ 210 CreateFile(); 211 int fd = open("output_file.txt", O_RDWR); 212 ASSERT_TRUE(fd > 0); 213 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED | MAP_FILE, fd, 0); 214 ASSERT_TRUE(addr != MAP_FAILED); 215 int ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); 216 ASSERT_TRUE(ret == 0); 217 ret = mlock(addr, PAGE_SIZE); 218 ASSERT_TRUE(ret == 0); 219 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); 220 ASSERT_TRUE(ret == -1); 221 ret = munmap(addr, PAGE_SIZE); 222 ASSERT_TRUE(ret == 0); 223 close(fd); 224 ret = unlink("output_file.txt"); 225 ASSERT_TRUE(ret == 0); 226 addr = nullptr; 227} 228 229/* 230 * @tc.number SUB_KERNEL_MEM_MADVISE_0800 231 * @tc.name MadviseMadvPageOut004 232 * @tc.desc MADV_PAGEOUT with mlock MAP_PRIVATE anon 233*/ 234HWTEST_F(MadviseApiTest, MadviseMadvPageOut004, Function | MediumTest | Level1) 235{ 236 int ret = -2; 237 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 238 ASSERT_TRUE(addr != MAP_FAILED); 239 ret = memset_s(addr, PAGE_SIZE, 'a', PAGE_SIZE); 240 ASSERT_TRUE(ret == 0); 241 ret = mlock(addr, PAGE_SIZE); 242 ASSERT_TRUE(ret == 0); 243 ret = madvise(addr, PAGE_SIZE, MADV_PAGEOUT); 244 ASSERT_TRUE(ret == -1); 245 ret = munmap(addr, PAGE_SIZE); 246 ASSERT_TRUE(ret == 0); 247 addr = nullptr; 248} 249 250/* 251 * @tc.number SUB_KERNEL_MEM_MADVISE_0900 252 * @tc.name MadviseMadvWipeOnFork001 253 * @tc.desc MADV_WIPEONFORK with MAP_PRIVATE anon 254*/ 255HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork001, Function | MediumTest | Level1) 256{ 257 int status = 0; 258 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, 259 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); 260 ASSERT_TRUE(addr != MAP_FAILED); 261 *addr = 'A'; 262 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 263 ASSERT_TRUE(err == 0); 264 pid_t pid = fork(); 265 ASSERT_TRUE(pid >= 0); 266 if (pid == 0) 267 { 268 ASSERT_TRUE(*addr == 0); 269 exit(0); 270 } else { 271 ASSERT_TRUE(*addr == 'A'); 272 waitpid(0, &status, 0); 273 } 274 int ret = munmap(addr, PAGE_SIZE); 275 ASSERT_TRUE(ret == 0); 276 addr = nullptr; 277} 278 279/* 280 * @tc.number SUB_KERNEL_MEM_MADVISE_1000 281 * @tc.name MadviseMadvWipeOnFork002 282 * @tc.desc MADV_WIPEONFORK with MAP_SHARED 283*/ 284HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork002, Function | MediumTest | Level1) 285{ 286 void *addr = mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); 287 ASSERT_TRUE(addr != MAP_FAILED); 288 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 289 ASSERT_TRUE(err == -1); 290 int ret = munmap(addr, PAGE_SIZE); 291 ASSERT_TRUE(ret == 0); 292 addr = nullptr; 293} 294 295/* 296 * @tc.number SUB_KERNEL_MEM_MADVISE_1100 297 * @tc.name MadviseMadvWipeOnFork003 298 * @tc.desc MADV_KEEPONFORK after MADV_WIPEONFORK 299*/ 300HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork003, Function | MediumTest | Level1) 301{ 302 int status = 0; 303 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, 304 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); 305 ASSERT_TRUE(addr != MAP_FAILED); 306 *addr = 'A'; 307 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 308 ASSERT_TRUE(err == 0); 309 err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK); 310 ASSERT_TRUE(err == 0); 311 pid_t pid = fork(); 312 ASSERT_TRUE(pid >= 0); 313 if (pid == 0) 314 { 315 ASSERT_TRUE(*addr == 'A'); 316 exit(0); 317 } else { 318 ASSERT_TRUE(*addr == 'A'); 319 waitpid(0, &status, 0); 320 } 321 int ret = munmap(addr, PAGE_SIZE); 322 ASSERT_TRUE(ret == 0); 323 addr = nullptr; 324} 325 326/* 327 * @tc.number SUB_KERNEL_MEM_MADVISE_1200 328 * @tc.name MadviseMadvWipeOnFork004 329 * @tc.desc next vregion is no MADV_WIPEONFORK 330*/ 331HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork004, Function | MediumTest | Level1) 332{ 333 int status = 0; 334 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, 335 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); 336 ASSERT_TRUE(addr != MAP_FAILED); 337 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, 338 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); 339 ASSERT_TRUE(nextAddr != MAP_FAILED); 340 *addr = 'A'; 341 *nextAddr = 'B'; 342 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 343 ASSERT_TRUE(err == 0); 344 pid_t pid = fork(); 345 ASSERT_TRUE(pid >= 0); 346 if (pid == 0) 347 { 348 ASSERT_TRUE(*addr == 0); 349 ASSERT_TRUE(*nextAddr == 'B'); 350 exit(0); 351 } else { 352 ASSERT_TRUE(*addr == 'A'); 353 ASSERT_TRUE(*nextAddr == 'B'); 354 waitpid(0, &status, 0); 355 } 356 int ret = munmap(addr, PAGE_SIZE); 357 ASSERT_TRUE(ret == 0); 358 ret = munmap(nextAddr, PAGE_SIZE); 359 ASSERT_TRUE(ret == 0); 360 addr = nullptr; 361 nextAddr = nullptr; 362} 363 364/* 365 * @tc.number SUB_KERNEL_MEM_MADVISE_1300 366 * @tc.name MadviseMadvWipeOnFork005 367 * @tc.desc next vregion is MADV_WIPEONFORK 368*/ 369HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork005, Function | MediumTest | Level1) 370{ 371 int status = 0; 372 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, 373 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); 374 ASSERT_TRUE(addr != MAP_FAILED); 375 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, 376 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); 377 ASSERT_TRUE(nextAddr != MAP_FAILED); 378 *addr = 'A'; 379 *nextAddr = 'B'; 380 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 381 ASSERT_TRUE(err == 0); 382 err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK); 383 ASSERT_TRUE(err == 0); 384 pid_t pid = fork(); 385 ASSERT_TRUE(pid >= 0); 386 if (pid == 0) 387 { 388 ASSERT_TRUE(*addr == 0); 389 ASSERT_TRUE(*nextAddr == 0); 390 exit(0); 391 } else { 392 ASSERT_TRUE(*addr == 'A'); 393 ASSERT_TRUE(*nextAddr == 'B'); 394 waitpid(0, &status, 0); 395 } 396 int ret = munmap(addr, PAGE_SIZE); 397 ASSERT_TRUE(ret == 0); 398 ret = munmap(nextAddr, PAGE_SIZE); 399 ASSERT_TRUE(ret == 0); 400 addr = nullptr; 401 nextAddr = nullptr; 402} 403 404/* 405 * @tc.number SUB_KERNEL_MEM_MADVISE_1400 406 * @tc.name MadviseMadvWipeOnFork006 407 * @tc.desc next vregion is MADV_KEEPONFORK 408*/ 409HWTEST_F(MadviseApiTest, MadviseMadvWipeOnFork006, Function | MediumTest | Level1) 410{ 411 int status = 0; 412 char *addr = static_cast<char*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, 413 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); 414 ASSERT_TRUE(addr != MAP_FAILED); 415 char *nextAddr = static_cast<char*>(mmap(addr, PAGE_SIZE, PROT_READ | PROT_WRITE, 416 MAP_ANONYMOUS | MAP_PRIVATE, -1, PAGE_SIZE)); 417 ASSERT_TRUE(nextAddr != MAP_FAILED); 418 *addr = 'A'; 419 *nextAddr = 'B'; 420 int err = madvise(addr, PAGE_SIZE, MADV_WIPEONFORK); 421 ASSERT_TRUE(err == 0); 422 err = madvise(nextAddr, PAGE_SIZE, MADV_WIPEONFORK); 423 ASSERT_TRUE(err == 0); 424 err = madvise(addr, PAGE_SIZE, MADV_KEEPONFORK); 425 ASSERT_TRUE(err == 0); 426 err = madvise(nextAddr, PAGE_SIZE, MADV_KEEPONFORK); 427 ASSERT_TRUE(err == 0); 428 pid_t pid = fork(); 429 ASSERT_TRUE(pid >= 0); 430 if (pid == 0) 431 { 432 ASSERT_TRUE(*addr == 'A'); 433 ASSERT_TRUE(*nextAddr == 'B'); 434 exit(0); 435 } else { 436 ASSERT_TRUE(*addr == 'A'); 437 ASSERT_TRUE(*nextAddr == 'B'); 438 waitpid(0, &status, 0); 439 } 440 int ret = munmap(addr, PAGE_SIZE); 441 ASSERT_TRUE(ret == 0); 442 ret = munmap(nextAddr, PAGE_SIZE); 443 ASSERT_TRUE(ret == 0); 444 addr = nullptr; 445 nextAddr = nullptr; 446}