brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · d008aea Raw
224 lines · cpp
1//===-- Unittest for fcntl ------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "hdr/fcntl_macros.h"10#include "hdr/stdio_macros.h"11#include "hdr/types/struct_flock.h"12#include "src/fcntl/fcntl.h"13#include "src/fcntl/open.h"14#include "src/unistd/close.h"15#include "src/unistd/getpid.h"16#include "test/UnitTest/ErrnoCheckingTest.h"17#include "test/UnitTest/ErrnoSetterMatcher.h"18#include "test/UnitTest/Test.h"19 20#include <sys/stat.h> // For S_IRWXU21 22using LlvmLibcFcntlTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;23 24TEST_F(LlvmLibcFcntlTest, FcntlDupfd) {25  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;26  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_dup.test";27  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);28  int fd2, fd3;29  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU);30  ASSERT_ERRNO_SUCCESS();31  ASSERT_GT(fd, 0);32 33  fd2 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 0);34  ASSERT_ERRNO_SUCCESS();35  ASSERT_GT(fd2, 0);36 37  fd3 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 10);38  ASSERT_ERRNO_SUCCESS();39  ASSERT_GT(fd3, 0);40 41  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));42  ASSERT_THAT(LIBC_NAMESPACE::close(fd2), Succeeds(0));43  ASSERT_THAT(LIBC_NAMESPACE::close(fd3), Succeeds(0));44}45 46TEST_F(LlvmLibcFcntlTest, FcntlGetFl) {47  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;48  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getfl.test";49  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);50  int retVal;51  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU);52  ASSERT_ERRNO_SUCCESS();53  ASSERT_GT(fd, 0);54 55  retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL);56  ASSERT_ERRNO_SUCCESS();57  ASSERT_GT(retVal, -1);58 59  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));60}61 62TEST_F(LlvmLibcFcntlTest, FcntlSetFl) {63  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;64  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_setfl.test";65  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);66 67  int retVal;68  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);69  ASSERT_ERRNO_SUCCESS();70  ASSERT_GT(fd, 0);71 72  retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL);73  ASSERT_ERRNO_SUCCESS();74  ASSERT_GT(retVal, -1);75 76  int oldFlags = LIBC_NAMESPACE::fcntl(fd, F_GETFL, 0);77  ASSERT_ERRNO_SUCCESS();78  ASSERT_GT(oldFlags, 0);79 80  // Add the APPEND flag;81  oldFlags |= O_APPEND;82 83  retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags);84  ASSERT_ERRNO_SUCCESS();85  ASSERT_GT(retVal, -1);86 87  // Remove the APPEND flag;88  oldFlags = -oldFlags & O_APPEND;89 90  retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags);91  ASSERT_ERRNO_SUCCESS();92  ASSERT_GT(retVal, -1);93 94  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));95}96 97/* Tests that are common between OFD and traditional variants of fcntl locks. */98template <int GETLK_CMD, int SETLK_CMD>99class LibcFcntlCommonLockTests : public LlvmLibcFcntlTest {100public:101  void GetLkRead() {102    using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;103    constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkread.test";104    const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);105 106    struct flock flk = {};107    struct flock svflk = {};108    int retVal;109    int fd =110        LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDONLY, S_IRWXU);111    ASSERT_ERRNO_SUCCESS();112    ASSERT_GT(fd, 0);113 114    flk.l_type = F_RDLCK;115    flk.l_start = 0;116    flk.l_whence = SEEK_SET;117    flk.l_len = 50;118 119    // copy flk into svflk120    svflk = flk;121 122    retVal = LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &svflk);123    ASSERT_ERRNO_SUCCESS();124    ASSERT_GT(retVal, -1);125    ASSERT_NE((int)svflk.l_type, F_WRLCK); // File should not be write locked.126 127    retVal = LIBC_NAMESPACE::fcntl(fd, SETLK_CMD, &svflk);128    ASSERT_ERRNO_SUCCESS();129    ASSERT_GT(retVal, -1);130 131    ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));132  }133 134  void GetLkWrite() {135    using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;136    constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkwrite.test";137    const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);138 139    struct flock flk = {};140    struct flock svflk = {};141    int retVal;142    int fd =143        LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);144    ASSERT_ERRNO_SUCCESS();145    ASSERT_GT(fd, 0);146 147    flk.l_type = F_WRLCK;148    flk.l_start = 0;149    flk.l_whence = SEEK_SET;150    flk.l_len = 0;151 152    // copy flk into svflk153    svflk = flk;154 155    retVal = LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &svflk);156    ASSERT_ERRNO_SUCCESS();157    ASSERT_GT(retVal, -1);158    ASSERT_NE((int)svflk.l_type, F_RDLCK); // File should not be read locked.159 160    retVal = LIBC_NAMESPACE::fcntl(fd, SETLK_CMD, &svflk);161    ASSERT_ERRNO_SUCCESS();162    ASSERT_GT(retVal, -1);163 164    ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));165  }166 167  void UseAfterClose() {168    using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;169    constexpr const char *TEST_FILE_NAME =170        "testdata/fcntl_use_after_close.test";171    const auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);172    int fd =173        LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);174    ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));175 176    flock flk = {};177    flk.l_type = F_RDLCK;178    flk.l_start = 0;179    flk.l_whence = SEEK_SET;180    flk.l_len = 50;181    ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, GETLK_CMD, &flk));182    ASSERT_ERRNO_EQ(EBADF);183  }184};185 186#define COMMON_LOCK_TESTS(NAME, GETLK_CMD, SETLK_CMD)                          \187  using NAME = LibcFcntlCommonLockTests<GETLK_CMD, SETLK_CMD>;                 \188  TEST_F(NAME, GetLkRead) { GetLkRead(); }                                     \189  TEST_F(NAME, GetLkWrite) { GetLkWrite(); }                                   \190  TEST_F(NAME, UseAfterClose) { UseAfterClose(); }                             \191  static_assert(true, "Require semicolon.")192 193COMMON_LOCK_TESTS(LlvmLibcFcntlProcessAssociatedLockTest, F_GETLK, F_SETLK);194COMMON_LOCK_TESTS(LlvmLibcFcntlOpenFileDescriptionLockTest, F_OFD_GETLK,195                  F_OFD_SETLK);196 197TEST_F(LlvmLibcFcntlTest, UseAfterClose) {198  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;199  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_use_after_close.test";200  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);201  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);202  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));203  ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, F_GETFL));204  ASSERT_ERRNO_EQ(EBADF);205}206 207TEST_F(LlvmLibcFcntlTest, SetGetOwnerTest) {208  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;209  pid_t pid = LIBC_NAMESPACE::getpid();210  ASSERT_GT(pid, -1);211  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_set_get_owner.test";212  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);213  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);214  ASSERT_ERRNO_SUCCESS();215  ASSERT_GT(fd, 0);216  int ret = LIBC_NAMESPACE::fcntl(fd, F_SETOWN, pid);217  ASSERT_ERRNO_SUCCESS();218  ASSERT_GT(ret, -1);219  int ret2 = LIBC_NAMESPACE::fcntl(fd, F_GETOWN);220  ASSERT_ERRNO_SUCCESS();221  ASSERT_EQ(ret2, pid);222  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));223}224