1 //===-- Unittests for syscalls --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/errno/libc_errno.h"
10 #include "src/unistd/syscall.h"
11 #include "test/UnitTest/ErrnoSetterMatcher.h"
12 #include "test/UnitTest/Test.h"
15 #include <sys/syscall.h> // For syscall numbers.
18 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds
;
20 // We only do a smoke test here. Actual functionality tests are
21 // done by the unit tests of the syscall wrappers like mmap.
22 // The goal is to test syscalls with a wide number of args.
24 // There is no function named "syscall" in llvm-libc, we instead use a macro to
25 // set up the arguments properly. We still need to specify the namespace though
26 // because the macro generates a call to the actual internal function
27 // (__llvm_libc_syscall) which is inside the namespace.
28 TEST(LlvmLibcSyscallTest
, TrivialCall
) {
31 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_gettid
), 0l);
32 ASSERT_EQ(libc_errno
, 0);
35 TEST(LlvmLibcSyscallTest
, SymlinkCreateDestroy
) {
36 constexpr const char LINK_VAL
[] = "syscall_readlink_test_value";
37 constexpr const char LINK
[] = "testdata/syscall_readlink.test.link";
40 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlink
, LINK_VAL
, LINK
), 0l);
41 #elif defined(SYS_symlinkat)
42 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlinkat
, LINK_VAL
, AT_FDCWD
, LINK
),
45 #error "symlink and symlinkat syscalls not available."
47 ASSERT_EQ(libc_errno
, 0);
49 char buf
[sizeof(LINK_VAL
)];
52 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_readlink
, LINK
, buf
, sizeof(buf
)), 0l);
53 #elif defined(SYS_readlinkat)
55 LIBC_NAMESPACE::syscall(SYS_readlinkat
, AT_FDCWD
, LINK
, buf
, sizeof(buf
)),
58 ASSERT_EQ(libc_errno
, 0);
61 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, LINK
), 0l);
62 #elif defined(SYS_unlinkat)
63 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, LINK
, 0), 0l);
65 #error "unlink and unlinkat syscalls not available."
67 ASSERT_EQ(libc_errno
, 0);
70 TEST(LlvmLibcSyscallTest
, FileReadWrite
) {
71 constexpr const char HELLO
[] = "hello";
72 constexpr int HELLO_SIZE
= sizeof(HELLO
);
74 constexpr const char *TEST_FILE
= "testdata/syscall_pread_pwrite.test";
78 LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE
, O_WRONLY
| O_CREAT
, S_IRWXU
);
79 #elif defined(SYS_openat)
80 int fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_FILE
,
81 O_WRONLY
| O_CREAT
, S_IRWXU
);
83 #error "open and openat syscalls not available."
86 ASSERT_EQ(libc_errno
, 0);
88 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_pwrite64
, fd
, HELLO
, HELLO_SIZE
, 0),
90 ASSERT_EQ(libc_errno
, 0);
92 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_fsync
, fd
), 0l);
93 ASSERT_EQ(libc_errno
, 0);
95 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, fd
), 0l);
96 ASSERT_EQ(libc_errno
, 0);
99 TEST(LlvmLibcSyscallTest
, FileLinkCreateDestroy
) {
100 constexpr const char *TEST_DIR
= "testdata";
101 constexpr const char *TEST_FILE
= "syscall_linkat.test";
102 constexpr const char *TEST_FILE_PATH
= "testdata/syscall_linkat.test";
103 constexpr const char *TEST_FILE_LINK
= "syscall_linkat.test.link";
104 constexpr const char *TEST_FILE_LINK_PATH
=
105 "testdata/syscall_linkat.test.link";
107 // The test strategy is as follows:
108 // 1. Create a normal file
109 // 2. Create a link to that file.
110 // 3. Open the link to check that the link was created.
111 // 4. Cleanup the file and its link.
114 int write_fd
= LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE_PATH
,
115 O_WRONLY
| O_CREAT
, S_IRWXU
);
116 #elif defined(SYS_openat)
117 int write_fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_FILE_PATH
,
118 O_WRONLY
| O_CREAT
, S_IRWXU
);
120 #error "open and openat syscalls not available."
122 ASSERT_GT(write_fd
, 0);
123 ASSERT_EQ(libc_errno
, 0);
125 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, write_fd
), 0l);
126 ASSERT_EQ(libc_errno
, 0);
129 int dir_fd
= LIBC_NAMESPACE::syscall(SYS_open
, TEST_DIR
, O_DIRECTORY
, 0);
130 #elif defined(SYS_openat)
132 LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_DIR
, O_DIRECTORY
, 0);
134 #error "open and openat syscalls not available."
136 ASSERT_GT(dir_fd
, 0);
137 ASSERT_EQ(libc_errno
, 0);
139 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_linkat
, dir_fd
, TEST_FILE
, dir_fd
,
142 ASSERT_EQ(libc_errno
, 0);
145 LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE_LINK_PATH
, O_PATH
, 0);
146 #elif defined(SYS_openat)
147 int link_fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
,
148 TEST_FILE_LINK_PATH
, O_PATH
, 0);
150 #error "open and openat syscalls not available."
152 ASSERT_GT(link_fd
, 0);
153 ASSERT_EQ(libc_errno
, 0);
156 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, TEST_FILE_PATH
), 0l);
157 #elif defined(SYS_unlinkat)
158 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, TEST_FILE_PATH
, 0),
161 #error "unlink and unlinkat syscalls not available."
163 ASSERT_EQ(libc_errno
, 0);
166 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, TEST_FILE_LINK_PATH
), 0l);
167 #elif defined(SYS_unlinkat)
169 LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, TEST_FILE_LINK_PATH
, 0),
172 #error "unlink and unlinkat syscalls not available."
174 ASSERT_EQ(libc_errno
, 0);
176 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, dir_fd
), 0l);
177 ASSERT_EQ(libc_errno
, 0);