xref: /llvm-project/libc/test/src/unistd/syscall_test.cpp (revision abc49cc19463970d5523d7d3332e4c1f83bc2ef7)
11801c356SMichael Jones //===-- Unittests for syscalls --------------------------------------------===//
21801c356SMichael Jones //
31801c356SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41801c356SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
51801c356SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61801c356SMichael Jones //
71801c356SMichael Jones //===----------------------------------------------------------------------===//
81801c356SMichael Jones 
967de5381SSiva Chandra Reddy #include "src/errno/libc_errno.h"
101801c356SMichael Jones #include "src/unistd/syscall.h"
114f1fe19dSSiva Chandra Reddy #include "test/UnitTest/ErrnoSetterMatcher.h"
12af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
131801c356SMichael Jones 
14*abc49cc1SJob Henandez Lara #include "hdr/fcntl_macros.h"
15c0ad6e2fSNick Desaulniers #include <sys/stat.h>    // For S_* flags.
161801c356SMichael Jones #include <sys/syscall.h> // For syscall numbers.
171801c356SMichael Jones #include <unistd.h>
181801c356SMichael Jones 
19b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
201801c356SMichael Jones 
211801c356SMichael Jones // We only do a smoke test here. Actual functionality tests are
221801c356SMichael Jones // done by the unit tests of the syscall wrappers like mmap.
231801c356SMichael Jones // The goal is to test syscalls with a wide number of args.
241801c356SMichael Jones 
251801c356SMichael Jones // There is no function named "syscall" in llvm-libc, we instead use a macro to
261801c356SMichael Jones // set up the arguments properly. We still need to specify the namespace though
271801c356SMichael Jones // because the macro generates a call to the actual internal function
28d4041301Salfredfo // (__llvm_libc_syscall) which is inside the namespace.
291801c356SMichael Jones TEST(LlvmLibcSyscallTest, TrivialCall) {
303eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
311801c356SMichael Jones 
32b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_gettid), 0l);
3373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
341801c356SMichael Jones }
351801c356SMichael Jones 
361801c356SMichael Jones TEST(LlvmLibcSyscallTest, SymlinkCreateDestroy) {
371801c356SMichael Jones   constexpr const char LINK_VAL[] = "syscall_readlink_test_value";
381801c356SMichael Jones   constexpr const char LINK[] = "testdata/syscall_readlink.test.link";
391801c356SMichael Jones 
401990ce74SMikhail R. Gadelha #ifdef SYS_symlink
41b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlink, LINK_VAL, LINK), 0l);
421990ce74SMikhail R. Gadelha #elif defined(SYS_symlinkat)
43b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlinkat, LINK_VAL, AT_FDCWD, LINK),
44b6bc9d72SGuillaume Chatelet             0l);
451990ce74SMikhail R. Gadelha #else
465b22df99SMikhail R. Gadelha #error "symlink and symlinkat syscalls not available."
471990ce74SMikhail R. Gadelha #endif
4873874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
491801c356SMichael Jones 
501801c356SMichael Jones   char buf[sizeof(LINK_VAL)];
511801c356SMichael Jones 
521990ce74SMikhail R. Gadelha #ifdef SYS_readlink
53b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_readlink, LINK, buf, sizeof(buf)), 0l);
541990ce74SMikhail R. Gadelha #elif defined(SYS_readlinkat)
551990ce74SMikhail R. Gadelha   ASSERT_GE(
56b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::syscall(SYS_readlinkat, AT_FDCWD, LINK, buf, sizeof(buf)),
571990ce74SMikhail R. Gadelha       0l);
581990ce74SMikhail R. Gadelha #endif
5973874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
601801c356SMichael Jones 
611990ce74SMikhail R. Gadelha #ifdef SYS_unlink
62b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, LINK), 0l);
631990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat)
64b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, LINK, 0), 0l);
651990ce74SMikhail R. Gadelha #else
665b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available."
671990ce74SMikhail R. Gadelha #endif
6873874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
691801c356SMichael Jones }
701801c356SMichael Jones 
711801c356SMichael Jones TEST(LlvmLibcSyscallTest, FileReadWrite) {
721801c356SMichael Jones   constexpr const char HELLO[] = "hello";
731801c356SMichael Jones   constexpr int HELLO_SIZE = sizeof(HELLO);
741801c356SMichael Jones 
751801c356SMichael Jones   constexpr const char *TEST_FILE = "testdata/syscall_pread_pwrite.test";
761801c356SMichael Jones 
771990ce74SMikhail R. Gadelha #ifdef SYS_open
781801c356SMichael Jones   int fd =
79b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
801990ce74SMikhail R. Gadelha #elif defined(SYS_openat)
81b6bc9d72SGuillaume Chatelet   int fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_FILE,
821990ce74SMikhail R. Gadelha                                    O_WRONLY | O_CREAT, S_IRWXU);
831990ce74SMikhail R. Gadelha #else
845b22df99SMikhail R. Gadelha #error "open and openat syscalls not available."
851990ce74SMikhail R. Gadelha #endif
861801c356SMichael Jones   ASSERT_GT(fd, 0);
8773874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
881801c356SMichael Jones 
89b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_pwrite64, fd, HELLO, HELLO_SIZE, 0),
90b6bc9d72SGuillaume Chatelet             0l);
9173874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
921801c356SMichael Jones 
93b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_fsync, fd), 0l);
9473874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
951801c356SMichael Jones 
96b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, fd), 0l);
9773874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
981801c356SMichael Jones }
991801c356SMichael Jones 
1001801c356SMichael Jones TEST(LlvmLibcSyscallTest, FileLinkCreateDestroy) {
1011801c356SMichael Jones   constexpr const char *TEST_DIR = "testdata";
1021801c356SMichael Jones   constexpr const char *TEST_FILE = "syscall_linkat.test";
1031801c356SMichael Jones   constexpr const char *TEST_FILE_PATH = "testdata/syscall_linkat.test";
1041801c356SMichael Jones   constexpr const char *TEST_FILE_LINK = "syscall_linkat.test.link";
1051801c356SMichael Jones   constexpr const char *TEST_FILE_LINK_PATH =
1061801c356SMichael Jones       "testdata/syscall_linkat.test.link";
1071801c356SMichael Jones 
1081801c356SMichael Jones   // The test strategy is as follows:
1091801c356SMichael Jones   //   1. Create a normal file
1101801c356SMichael Jones   //   2. Create a link to that file.
1111801c356SMichael Jones   //   3. Open the link to check that the link was created.
1121801c356SMichael Jones   //   4. Cleanup the file and its link.
1131801c356SMichael Jones 
1141990ce74SMikhail R. Gadelha #ifdef SYS_open
115b6bc9d72SGuillaume Chatelet   int write_fd = LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE_PATH,
1161801c356SMichael Jones                                          O_WRONLY | O_CREAT, S_IRWXU);
1171990ce74SMikhail R. Gadelha #elif defined(SYS_openat)
118b6bc9d72SGuillaume Chatelet   int write_fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_FILE_PATH,
1191990ce74SMikhail R. Gadelha                                          O_WRONLY | O_CREAT, S_IRWXU);
1201990ce74SMikhail R. Gadelha #else
1215b22df99SMikhail R. Gadelha #error "open and openat syscalls not available."
1221990ce74SMikhail R. Gadelha #endif
1231801c356SMichael Jones   ASSERT_GT(write_fd, 0);
12473874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1251801c356SMichael Jones 
126b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, write_fd), 0l);
12773874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1281801c356SMichael Jones 
1291990ce74SMikhail R. Gadelha #ifdef SYS_open
130b6bc9d72SGuillaume Chatelet   int dir_fd = LIBC_NAMESPACE::syscall(SYS_open, TEST_DIR, O_DIRECTORY, 0);
1311990ce74SMikhail R. Gadelha #elif defined(SYS_openat)
1321990ce74SMikhail R. Gadelha   int dir_fd =
133b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_DIR, O_DIRECTORY, 0);
1341990ce74SMikhail R. Gadelha #else
1355b22df99SMikhail R. Gadelha #error "open and openat syscalls not available."
1361990ce74SMikhail R. Gadelha #endif
1371801c356SMichael Jones   ASSERT_GT(dir_fd, 0);
13873874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1391801c356SMichael Jones 
140b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_linkat, dir_fd, TEST_FILE, dir_fd,
1411801c356SMichael Jones                                     TEST_FILE_LINK, 0),
1421801c356SMichael Jones             0l);
14373874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1441990ce74SMikhail R. Gadelha #ifdef SYS_open
145b6bc9d72SGuillaume Chatelet   int link_fd =
146b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE_LINK_PATH, O_PATH, 0);
1471990ce74SMikhail R. Gadelha #elif defined(SYS_openat)
148b6bc9d72SGuillaume Chatelet   int link_fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD,
149b6bc9d72SGuillaume Chatelet                                         TEST_FILE_LINK_PATH, O_PATH, 0);
1501990ce74SMikhail R. Gadelha #else
1515b22df99SMikhail R. Gadelha #error "open and openat syscalls not available."
1521990ce74SMikhail R. Gadelha #endif
1531801c356SMichael Jones   ASSERT_GT(link_fd, 0);
15473874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1551801c356SMichael Jones 
1561990ce74SMikhail R. Gadelha #ifdef SYS_unlink
157b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, TEST_FILE_PATH), 0l);
1581990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat)
159b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, TEST_FILE_PATH, 0),
1601990ce74SMikhail R. Gadelha             0l);
1611990ce74SMikhail R. Gadelha #else
1625b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available."
1631990ce74SMikhail R. Gadelha #endif
16473874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1651801c356SMichael Jones 
1661990ce74SMikhail R. Gadelha #ifdef SYS_unlink
167b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, TEST_FILE_LINK_PATH), 0l);
1681990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat)
1691990ce74SMikhail R. Gadelha   ASSERT_GE(
170b6bc9d72SGuillaume Chatelet       LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, TEST_FILE_LINK_PATH, 0),
171b6bc9d72SGuillaume Chatelet       0l);
1721990ce74SMikhail R. Gadelha #else
1735b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available."
1741990ce74SMikhail R. Gadelha #endif
17573874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1761801c356SMichael Jones 
177b6bc9d72SGuillaume Chatelet   ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, dir_fd), 0l);
17873874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
1791801c356SMichael Jones }
180