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"
14 #include "hdr/fcntl_macros.h"
15 #include <sys/stat.h> // For S_* flags.
16 #include <sys/syscall.h> // For syscall numbers.
19 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds
;
21 // We only do a smoke test here. Actual functionality tests are
22 // done by the unit tests of the syscall wrappers like mmap.
23 // The goal is to test syscalls with a wide number of args.
25 // There is no function named "syscall" in llvm-libc, we instead use a macro to
26 // set up the arguments properly. We still need to specify the namespace though
27 // because the macro generates a call to the actual internal function
28 // (__llvm_libc_syscall) which is inside the namespace.
29 TEST(LlvmLibcSyscallTest
, TrivialCall
) {
30 LIBC_NAMESPACE::libc_errno
= 0;
32 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_gettid
), 0l);
33 ASSERT_ERRNO_SUCCESS();
36 TEST(LlvmLibcSyscallTest
, SymlinkCreateDestroy
) {
37 constexpr const char LINK_VAL
[] = "syscall_readlink_test_value";
38 constexpr const char LINK
[] = "testdata/syscall_readlink.test.link";
41 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlink
, LINK_VAL
, LINK
), 0l);
42 #elif defined(SYS_symlinkat)
43 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlinkat
, LINK_VAL
, AT_FDCWD
, LINK
),
46 #error "symlink and symlinkat syscalls not available."
48 ASSERT_ERRNO_SUCCESS();
50 char buf
[sizeof(LINK_VAL
)];
53 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_readlink
, LINK
, buf
, sizeof(buf
)), 0l);
54 #elif defined(SYS_readlinkat)
56 LIBC_NAMESPACE::syscall(SYS_readlinkat
, AT_FDCWD
, LINK
, buf
, sizeof(buf
)),
59 ASSERT_ERRNO_SUCCESS();
62 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, LINK
), 0l);
63 #elif defined(SYS_unlinkat)
64 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, LINK
, 0), 0l);
66 #error "unlink and unlinkat syscalls not available."
68 ASSERT_ERRNO_SUCCESS();
71 TEST(LlvmLibcSyscallTest
, FileReadWrite
) {
72 constexpr const char HELLO
[] = "hello";
73 constexpr int HELLO_SIZE
= sizeof(HELLO
);
75 constexpr const char *TEST_FILE
= "testdata/syscall_pread_pwrite.test";
79 LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE
, O_WRONLY
| O_CREAT
, S_IRWXU
);
80 #elif defined(SYS_openat)
81 int fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_FILE
,
82 O_WRONLY
| O_CREAT
, S_IRWXU
);
84 #error "open and openat syscalls not available."
87 ASSERT_ERRNO_SUCCESS();
89 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_pwrite64
, fd
, HELLO
, HELLO_SIZE
, 0),
91 ASSERT_ERRNO_SUCCESS();
93 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_fsync
, fd
), 0l);
94 ASSERT_ERRNO_SUCCESS();
96 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, fd
), 0l);
97 ASSERT_ERRNO_SUCCESS();
100 TEST(LlvmLibcSyscallTest
, FileLinkCreateDestroy
) {
101 constexpr const char *TEST_DIR
= "testdata";
102 constexpr const char *TEST_FILE
= "syscall_linkat.test";
103 constexpr const char *TEST_FILE_PATH
= "testdata/syscall_linkat.test";
104 constexpr const char *TEST_FILE_LINK
= "syscall_linkat.test.link";
105 constexpr const char *TEST_FILE_LINK_PATH
=
106 "testdata/syscall_linkat.test.link";
108 // The test strategy is as follows:
109 // 1. Create a normal file
110 // 2. Create a link to that file.
111 // 3. Open the link to check that the link was created.
112 // 4. Cleanup the file and its link.
115 int write_fd
= LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE_PATH
,
116 O_WRONLY
| O_CREAT
, S_IRWXU
);
117 #elif defined(SYS_openat)
118 int write_fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_FILE_PATH
,
119 O_WRONLY
| O_CREAT
, S_IRWXU
);
121 #error "open and openat syscalls not available."
123 ASSERT_GT(write_fd
, 0);
124 ASSERT_ERRNO_SUCCESS();
126 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, write_fd
), 0l);
127 ASSERT_ERRNO_SUCCESS();
130 int dir_fd
= LIBC_NAMESPACE::syscall(SYS_open
, TEST_DIR
, O_DIRECTORY
, 0);
131 #elif defined(SYS_openat)
133 LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
, TEST_DIR
, O_DIRECTORY
, 0);
135 #error "open and openat syscalls not available."
137 ASSERT_GT(dir_fd
, 0);
138 ASSERT_ERRNO_SUCCESS();
140 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_linkat
, dir_fd
, TEST_FILE
, dir_fd
,
143 ASSERT_ERRNO_SUCCESS();
146 LIBC_NAMESPACE::syscall(SYS_open
, TEST_FILE_LINK_PATH
, O_PATH
, 0);
147 #elif defined(SYS_openat)
148 int link_fd
= LIBC_NAMESPACE::syscall(SYS_openat
, AT_FDCWD
,
149 TEST_FILE_LINK_PATH
, O_PATH
, 0);
151 #error "open and openat syscalls not available."
153 ASSERT_GT(link_fd
, 0);
154 ASSERT_ERRNO_SUCCESS();
157 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, TEST_FILE_PATH
), 0l);
158 #elif defined(SYS_unlinkat)
159 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, TEST_FILE_PATH
, 0),
162 #error "unlink and unlinkat syscalls not available."
164 ASSERT_ERRNO_SUCCESS();
167 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink
, TEST_FILE_LINK_PATH
), 0l);
168 #elif defined(SYS_unlinkat)
170 LIBC_NAMESPACE::syscall(SYS_unlinkat
, AT_FDCWD
, TEST_FILE_LINK_PATH
, 0),
173 #error "unlink and unlinkat syscalls not available."
175 ASSERT_ERRNO_SUCCESS();
177 ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close
, dir_fd
), 0l);
178 ASSERT_ERRNO_SUCCESS();