xref: /aosp_15_r20/external/llvm-libc/test/src/unistd/syscall_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Unittests for syscalls --------------------------------------------===//
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/errno/libc_errno.h"
10 #include "src/unistd/syscall.h"
11 #include "test/UnitTest/ErrnoSetterMatcher.h"
12 #include "test/UnitTest/Test.h"
13 
14 #include "hdr/fcntl_macros.h"
15 #include <sys/stat.h>    // For S_* flags.
16 #include <sys/syscall.h> // For syscall numbers.
17 #include <unistd.h>
18 
19 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
20 
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.
24 
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.
TEST(LlvmLibcSyscallTest,TrivialCall)29 TEST(LlvmLibcSyscallTest, TrivialCall) {
30   LIBC_NAMESPACE::libc_errno = 0;
31 
32   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_gettid), 0l);
33   ASSERT_ERRNO_SUCCESS();
34 }
35 
TEST(LlvmLibcSyscallTest,SymlinkCreateDestroy)36 TEST(LlvmLibcSyscallTest, SymlinkCreateDestroy) {
37   constexpr const char LINK_VAL[] = "syscall_readlink_test_value";
38   constexpr const char LINK[] = "testdata/syscall_readlink.test.link";
39 
40 #ifdef SYS_symlink
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),
44             0l);
45 #else
46 #error "symlink and symlinkat syscalls not available."
47 #endif
48   ASSERT_ERRNO_SUCCESS();
49 
50   char buf[sizeof(LINK_VAL)];
51 
52 #ifdef SYS_readlink
53   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_readlink, LINK, buf, sizeof(buf)), 0l);
54 #elif defined(SYS_readlinkat)
55   ASSERT_GE(
56       LIBC_NAMESPACE::syscall(SYS_readlinkat, AT_FDCWD, LINK, buf, sizeof(buf)),
57       0l);
58 #endif
59   ASSERT_ERRNO_SUCCESS();
60 
61 #ifdef SYS_unlink
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);
65 #else
66 #error "unlink and unlinkat syscalls not available."
67 #endif
68   ASSERT_ERRNO_SUCCESS();
69 }
70 
TEST(LlvmLibcSyscallTest,FileReadWrite)71 TEST(LlvmLibcSyscallTest, FileReadWrite) {
72   constexpr const char HELLO[] = "hello";
73   constexpr int HELLO_SIZE = sizeof(HELLO);
74 
75   constexpr const char *TEST_FILE = "testdata/syscall_pread_pwrite.test";
76 
77 #ifdef SYS_open
78   int fd =
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);
83 #else
84 #error "open and openat syscalls not available."
85 #endif
86   ASSERT_GT(fd, 0);
87   ASSERT_ERRNO_SUCCESS();
88 
89   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_pwrite64, fd, HELLO, HELLO_SIZE, 0),
90             0l);
91   ASSERT_ERRNO_SUCCESS();
92 
93   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_fsync, fd), 0l);
94   ASSERT_ERRNO_SUCCESS();
95 
96   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, fd), 0l);
97   ASSERT_ERRNO_SUCCESS();
98 }
99 
TEST(LlvmLibcSyscallTest,FileLinkCreateDestroy)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";
107 
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.
113 
114 #ifdef SYS_open
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);
120 #else
121 #error "open and openat syscalls not available."
122 #endif
123   ASSERT_GT(write_fd, 0);
124   ASSERT_ERRNO_SUCCESS();
125 
126   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, write_fd), 0l);
127   ASSERT_ERRNO_SUCCESS();
128 
129 #ifdef SYS_open
130   int dir_fd = LIBC_NAMESPACE::syscall(SYS_open, TEST_DIR, O_DIRECTORY, 0);
131 #elif defined(SYS_openat)
132   int dir_fd =
133       LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_DIR, O_DIRECTORY, 0);
134 #else
135 #error "open and openat syscalls not available."
136 #endif
137   ASSERT_GT(dir_fd, 0);
138   ASSERT_ERRNO_SUCCESS();
139 
140   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_linkat, dir_fd, TEST_FILE, dir_fd,
141                                     TEST_FILE_LINK, 0),
142             0l);
143   ASSERT_ERRNO_SUCCESS();
144 #ifdef SYS_open
145   int link_fd =
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);
150 #else
151 #error "open and openat syscalls not available."
152 #endif
153   ASSERT_GT(link_fd, 0);
154   ASSERT_ERRNO_SUCCESS();
155 
156 #ifdef SYS_unlink
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),
160             0l);
161 #else
162 #error "unlink and unlinkat syscalls not available."
163 #endif
164   ASSERT_ERRNO_SUCCESS();
165 
166 #ifdef SYS_unlink
167   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, TEST_FILE_LINK_PATH), 0l);
168 #elif defined(SYS_unlinkat)
169   ASSERT_GE(
170       LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, TEST_FILE_LINK_PATH, 0),
171       0l);
172 #else
173 #error "unlink and unlinkat syscalls not available."
174 #endif
175   ASSERT_ERRNO_SUCCESS();
176 
177   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, dir_fd), 0l);
178   ASSERT_ERRNO_SUCCESS();
179 }
180