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/LibcTest.h"
20#include "test/UnitTest/Test.h"
21
22#include <sys/mman.h>
23#include <sys/syscall.h>
24#include <unistd.h>
25
26using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
27using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
28
29TEST(LlvmLibcMincoreTest, UnMappedMemory) {
30 LIBC_NAMESPACE::libc_errno = 0;
31 unsigned char vec;
32 int res = LIBC_NAMESPACE::mincore(addr: nullptr, len: 1, vec: &vec);
33 EXPECT_THAT(res, Fails(ENOMEM, -1));
34}
35
36TEST(LlvmLibcMincoreTest, UnalignedAddr) {
37 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
38 void *addr = LIBC_NAMESPACE::mmap(addr: nullptr, size: page_size, PROT_READ,
39 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
40 EXPECT_NE(addr, MAP_FAILED);
41 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
42 LIBC_NAMESPACE::libc_errno = 0;
43 int res = LIBC_NAMESPACE::mincore(addr: static_cast<char *>(addr) + 1, len: 1, vec: nullptr);
44 EXPECT_THAT(res, Fails(EINVAL, -1));
45 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
46}
47
48TEST(LlvmLibcMincoreTest, InvalidVec) {
49 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
50 void *addr = LIBC_NAMESPACE::mmap(addr: nullptr, size: 4 * page_size, PROT_READ,
51 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
52 EXPECT_NE(addr, MAP_FAILED);
53 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
54 LIBC_NAMESPACE::libc_errno = 0;
55 int res = LIBC_NAMESPACE::mincore(addr, len: 1, vec: nullptr);
56 EXPECT_THAT(res, Fails(EFAULT, -1));
57}
58
59TEST(LlvmLibcMincoreTest, NoError) {
60 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
61 void *addr = LIBC_NAMESPACE::mmap(addr: nullptr, size: page_size, PROT_READ,
62 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
63 EXPECT_NE(addr, MAP_FAILED);
64 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
65 unsigned char vec;
66 LIBC_NAMESPACE::libc_errno = 0;
67 int res = LIBC_NAMESPACE::mincore(addr, len: 1, vec: &vec);
68 EXPECT_THAT(res, Succeeds());
69 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
70}
71
72TEST(LlvmLibcMincoreTest, NegativeLength) {
73 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
74 void *addr = LIBC_NAMESPACE::mmap(addr: nullptr, size: page_size, PROT_READ,
75 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
76 EXPECT_NE(addr, MAP_FAILED);
77 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
78 unsigned char vec;
79 LIBC_NAMESPACE::libc_errno = 0;
80 int res = LIBC_NAMESPACE::mincore(addr, len: -1, vec: &vec);
81 EXPECT_THAT(res, Fails(ENOMEM, -1));
82 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
83}
84
85TEST(LlvmLibcMincoreTest, PageOut) {
86 unsigned long page_size = LIBC_NAMESPACE::sysconf(_SC_PAGESIZE);
87 unsigned char vec;
88 void *addr = LIBC_NAMESPACE::mmap(addr: nullptr, size: page_size, PROT_READ | PROT_WRITE,
89 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
90 EXPECT_NE(addr, MAP_FAILED);
91 EXPECT_EQ(reinterpret_cast<unsigned long>(addr) % page_size, 0ul);
92
93 // touch the page
94 {
95 static_cast<char *>(addr)[0] = 0;
96 EXPECT_THAT(LIBC_NAMESPACE::mlock(addr, page_size), Succeeds());
97 int res = LIBC_NAMESPACE::mincore(addr, len: 1, vec: &vec);
98 EXPECT_EQ(vec & 1u, 1u);
99 EXPECT_THAT(res, Succeeds());
100 EXPECT_THAT(LIBC_NAMESPACE::munlock(addr, page_size), Succeeds());
101 }
102
103 // page out the memory
104 {
105 LIBC_NAMESPACE::libc_errno = 0;
106 EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, page_size, MADV_DONTNEED),
107 Succeeds());
108
109 LIBC_NAMESPACE::libc_errno = 0;
110 int res = LIBC_NAMESPACE::mincore(addr, len: page_size, vec: &vec);
111 EXPECT_EQ(vec & 1u, 0u);
112 EXPECT_THAT(res, Succeeds());
113 }
114
115 EXPECT_THAT(LIBC_NAMESPACE::munmap(addr, page_size), Succeeds());
116}
117

source code of libc/test/src/sys/mman/linux/mincore_test.cpp