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/sys/mman/madvise.h" |
11 | #include "src/sys/mman/mincore.h" |
12 | #include "src/sys/mman/mlock.h" |
13 | #include "src/sys/mman/mmap.h" |
14 | #include "src/sys/mman/munlock.h" |
15 | #include "src/sys/mman/munmap.h" |
16 | #include "src/unistd/sysconf.h" |
17 | #include "test/UnitTest/ErrnoCheckingTest.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 | using LlvmLibcMincoreTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; |
28 | |
29 | TEST_F(LlvmLibcMincoreTest, UnMappedMemory) { |
30 | unsigned char vec; |
31 | int res = LIBC_NAMESPACE::mincore(nullptr, 1, &vec); |
32 | EXPECT_THAT(res, Fails(ENOMEM, -1)); |
33 | } |
34 | |
35 | TEST_F(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 | int res = LIBC_NAMESPACE::mincore(static_cast<char *>(addr) + 1, 1, nullptr); |
42 | EXPECT_THAT(res, Fails(EINVAL, -1)); |
43 | EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); |
44 | } |
45 | |
46 | TEST_F(LlvmLibcMincoreTest, InvalidVec) { |
47 | unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); |
48 | void *addr = LIBC_NAMESPACE::mmap(nullptr, 4 * page_size, PROT_READ, |
49 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
50 | EXPECT_NE(addr, MAP_FAILED); |
51 | EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); |
52 | int res = LIBC_NAMESPACE::mincore(addr, 1, nullptr); |
53 | EXPECT_THAT(res, Fails(EFAULT, -1)); |
54 | } |
55 | |
56 | TEST_F(LlvmLibcMincoreTest, NoError) { |
57 | unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); |
58 | void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, |
59 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
60 | EXPECT_NE(addr, MAP_FAILED); |
61 | EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); |
62 | unsigned char vec; |
63 | int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); |
64 | EXPECT_THAT(res, Succeeds()); |
65 | EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); |
66 | } |
67 | |
68 | TEST_F(LlvmLibcMincoreTest, NegativeLength) { |
69 | unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); |
70 | void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ, |
71 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
72 | EXPECT_NE(addr, MAP_FAILED); |
73 | EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); |
74 | unsigned char vec; |
75 | int res = LIBC_NAMESPACE::mincore(addr, -1, &vec); |
76 | EXPECT_THAT(res, Fails(ENOMEM, -1)); |
77 | EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); |
78 | } |
79 | |
80 | TEST_F(LlvmLibcMincoreTest, PageOut) { |
81 | unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE); |
82 | unsigned char vec; |
83 | void *addr = LIBC_NAMESPACE::mmap(nullptr, page_size, PROT_READ | PROT_WRITE, |
84 | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
85 | EXPECT_NE(addr, MAP_FAILED); |
86 | EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul); |
87 | |
88 | // touch the page |
89 | { |
90 | static_cast<char *>(addr)[0] = 0; |
91 | EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, page_size), Succeeds()); |
92 | int res = LIBC_NAMESPACE::mincore(addr, 1, &vec); |
93 | EXPECT_EQ(vec & 1u, 1u); |
94 | EXPECT_THAT(res, Succeeds()); |
95 | EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, page_size), Succeeds()); |
96 | } |
97 | |
98 | // page out the memory |
99 | { |
100 | EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, page_size, MADV_DONTNEED), |
101 | Succeeds()); |
102 | |
103 | int res = LIBC_NAMESPACE::mincore(addr, page_size, &vec); |
104 | EXPECT_EQ(vec & 1u, 0u); |
105 | EXPECT_THAT(res, Succeeds()); |
106 | } |
107 | |
108 | EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds()); |
109 | } |
110 | |