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. 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 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 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 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