1 //===-- Unittest for fdopen -----------------------------------------------===//
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/stdio/fdopen.h"
11 #include "hdr/fcntl_macros.h"
12 #include "src/errno/libc_errno.h"
13 #include "src/fcntl/open.h"
14 #include "src/stdio/fclose.h"
15 #include "src/stdio/fgets.h"
16 #include "src/stdio/fputs.h"
17 #include "src/unistd/close.h"
18 #include "test/UnitTest/ErrnoSetterMatcher.h"
19 #include "test/UnitTest/Test.h"
21 #include <sys/stat.h> // For S_IRWXU
23 TEST(LlvmLibcStdioFdopenTest
, WriteAppendRead
) {
24 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds
;
25 LIBC_NAMESPACE::libc_errno
= 0;
26 constexpr const char *TEST_FILE_NAME
= "testdata/write_read_append.test";
27 auto TEST_FILE
= libc_make_test_file_path(TEST_FILE_NAME
);
28 int fd
= LIBC_NAMESPACE::open(TEST_FILE
, O_CREAT
| O_TRUNC
| O_RDWR
, S_IRWXU
);
29 auto *fp
= LIBC_NAMESPACE::fdopen(fd
, "w");
30 ASSERT_ERRNO_SUCCESS();
31 ASSERT_TRUE(nullptr != fp
);
32 constexpr const char HELLO
[] = "Hello";
33 LIBC_NAMESPACE::fputs(HELLO
, fp
);
34 LIBC_NAMESPACE::fclose(fp
);
35 ASSERT_ERRNO_SUCCESS();
37 constexpr const char LLVM
[] = "LLVM";
38 int fd2
= LIBC_NAMESPACE::open(TEST_FILE
, O_CREAT
| O_RDWR
);
39 auto *fp2
= LIBC_NAMESPACE::fdopen(fd2
, "a");
40 ASSERT_ERRNO_SUCCESS();
41 ASSERT_TRUE(nullptr != fp2
);
42 LIBC_NAMESPACE::fputs(LLVM
, fp2
);
43 LIBC_NAMESPACE::fclose(fp2
);
44 ASSERT_ERRNO_SUCCESS();
46 int fd3
= LIBC_NAMESPACE::open(TEST_FILE
, O_CREAT
| O_RDWR
);
47 auto *fp3
= LIBC_NAMESPACE::fdopen(fd3
, "r");
49 LIBC_NAMESPACE::fgets(buffer
, sizeof(buffer
), fp3
);
50 ASSERT_STREQ("HelloLLVM", buffer
);
51 LIBC_NAMESPACE::fclose(fp3
);
52 ASSERT_ERRNO_SUCCESS();
55 TEST(LlvmLibcStdioFdopenTest
, InvalidFd
) {
56 LIBC_NAMESPACE::libc_errno
= 0;
57 constexpr const char *TEST_FILE_NAME
= "testdata/invalid_fd.test";
58 auto TEST_FILE
= libc_make_test_file_path(TEST_FILE_NAME
);
59 int fd
= LIBC_NAMESPACE::open(TEST_FILE
, O_CREAT
| O_TRUNC
);
60 LIBC_NAMESPACE::close(fd
);
61 // With `fd` already closed, `fdopen` should fail and set the `errno` to EBADF
62 auto *fp
= LIBC_NAMESPACE::fdopen(fd
, "r");
63 ASSERT_ERRNO_EQ(EBADF
);
64 ASSERT_TRUE(nullptr == fp
);
67 TEST(LlvmLibcStdioFdopenTest
, InvalidMode
) {
68 LIBC_NAMESPACE::libc_errno
= 0;
69 constexpr const char *TEST_FILE_NAME
= "testdata/invalid_mode.test";
70 auto TEST_FILE
= libc_make_test_file_path(TEST_FILE_NAME
);
71 int fd
= LIBC_NAMESPACE::open(TEST_FILE
, O_CREAT
| O_RDONLY
, S_IRWXU
);
72 ASSERT_ERRNO_SUCCESS();
75 // `Mode` must be one of "r", "w" or "a"
76 auto *fp
= LIBC_NAMESPACE::fdopen(fd
, "m+");
77 ASSERT_ERRNO_EQ(EINVAL
);
78 ASSERT_TRUE(nullptr == fp
);
80 // If the mode argument is invalid, then `fdopen` returns a nullptr and sets
81 // the `errno` to EINVAL. In this case the `mode` param can only be "r" or
83 auto *fp2
= LIBC_NAMESPACE::fdopen(fd
, "w");
84 ASSERT_ERRNO_EQ(EINVAL
);
85 ASSERT_TRUE(nullptr == fp2
);
86 LIBC_NAMESPACE::libc_errno
= 0;
87 LIBC_NAMESPACE::close(fd
);
88 ASSERT_ERRNO_SUCCESS();