xref: /llvm-project/libc/test/src/sys/mman/linux/mincore_test.cpp (revision 04aaa35d40d8c5ff030014866691f9a56e59c142)
1 //===-- Unittests for mincore ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
10 #include "src/errno/libc_errno.h"
11 #include "src/sys/mman/madvise.h"
12 #include "src/sys/mman/mincore.h"
13 #include "src/sys/mman/mlock.h"
14 #include "src/sys/mman/mmap.h"
15 #include "src/sys/mman/munlock.h"
16 #include "src/sys/mman/munmap.h"
17 #include "src/unistd/sysconf.h"
18 #include "test/UnitTest/ErrnoSetterMatcher.h"
19 #include "test/UnitTest/Test.h"
20 
21 #include <sys/mman.h>
22 #include <sys/syscall.h>
23 #include <unistd.h>
24 
25 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
26 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
27 
28 TEST(LlvmLibcMincoreTest, UnMappedMemory) {
29   LIBC_NAMESPACE::libc_errno = 0;
30   unsigned char vec;
31   int res = LIBC_NAMESPACE::mincore(nullptr, 1, &vec);
32   EXPECT_THAT(res, Fails(ENOMEM, -1));
33 }
34 
35 TEST(LlvmLibcMincoreTest, UnalignedAddr) {
36   unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
37   void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ,
38                                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
39   EXPECT_NE(addr, MAP_FAILED);
40   EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
41   LIBC_NAMESPACE::libc_errno = 0;
42   int res = LIBC_NAMESPACE::mincore(static_cast<char *>(addr) + 1, 1, nullptr);
43   EXPECT_THAT(res, Fails(EINVAL, -1));
44   EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
45 }
46 
47 TEST(LlvmLibcMincoreTest, InvalidVec) {
48   unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
49   void *addr = LIBC_NAMESPACE::mmap(nullptr, 4 * page_size, PROT_READ,
50                                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
51   EXPECT_NE(addr, MAP_FAILED);
52   EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
53   LIBC_NAMESPACE::libc_errno = 0;
54   int res = LIBC_NAMESPACE::mincore(addr, 1, nullptr);
55   EXPECT_THAT(res, Fails(EFAULT, -1));
56 }
57 
58 TEST(LlvmLibcMincoreTest, NoError) {
59   unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
60   void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ,
61                                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
62   EXPECT_NE(addr, MAP_FAILED);
63   EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
64   unsigned char vec;
65   LIBC_NAMESPACE::libc_errno = 0;
66   int res = LIBC_NAMESPACE::mincore(addr, 1, &vec);
67   EXPECT_THAT(res, Succeeds());
68   EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
69 }
70 
71 TEST(LlvmLibcMincoreTest, NegativeLength) {
72   unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
73   void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ,
74                                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
75   EXPECT_NE(addr, MAP_FAILED);
76   EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
77   unsigned char vec;
78   LIBC_NAMESPACE::libc_errno = 0;
79   int res = LIBC_NAMESPACE::mincore(addr, -1, &vec);
80   EXPECT_THAT(res, Fails(ENOMEM, -1));
81   EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
82 }
83 
84 TEST(LlvmLibcMincoreTest, PageOut) {
85   unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
86   unsigned char vec;
87   void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE,
88                                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
89   EXPECT_NE(addr, MAP_FAILED);
90   EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
91 
92   // touch the page
93   {
94     static_cast<char *>(addr)[0] = 0;
95     EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, page_size), Succeeds());
96     int res = LIBC_NAMESPACE::mincore(addr, 1, &vec);
97     EXPECT_EQ(vec & 1u, 1u);
98     EXPECT_THAT(res, Succeeds());
99     EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, page_size), Succeeds());
100   }
101 
102   // page out the memory
103   {
104     LIBC_NAMESPACE::libc_errno = 0;
105     EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, page_size, MADV_DONTNEED),
106                 Succeeds());
107 
108     LIBC_NAMESPACE::libc_errno = 0;
109     int res = LIBC_NAMESPACE::mincore(addr, page_size, &vec);
110     EXPECT_EQ(vec & 1u, 0u);
111     EXPECT_THAT(res, Succeeds());
112   }
113 
114   EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
115 }
116