1 //===-- Unittests for fgets -----------------------------------------------===//
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/stdio/fclose.h"
10 #include "src/stdio/feof.h"
11 #include "src/stdio/ferror.h"
12 #include "src/stdio/fgets.h"
13 #include "src/stdio/fopen.h"
14 #include "src/stdio/fwrite.h"
15 #include "test/UnitTest/Test.h"
16
17 #include "src/errno/libc_errno.h"
18
TEST(LlvmLibcFgetsTest,WriteAndReadCharacters)19 TEST(LlvmLibcFgetsTest, WriteAndReadCharacters) {
20 constexpr char FILENAME[] = "testdata/fgets.test";
21 ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w");
22 ASSERT_FALSE(file == nullptr);
23 constexpr char CONTENT[] = "123456789\n"
24 "1234567\n"
25 "123456\n"
26 "1";
27 constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
28
29 char buff[8];
30 char *output;
31
32 ASSERT_EQ(WRITE_SIZE, LIBC_NAMESPACE::fwrite(CONTENT, 1, WRITE_SIZE, file));
33 // This is a write-only file so reads should fail.
34 ASSERT_TRUE(LIBC_NAMESPACE::fgets(buff, 8, file) == nullptr);
35 // This is an error and not a real EOF.
36 ASSERT_EQ(LIBC_NAMESPACE::feof(file), 0);
37 ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0);
38 LIBC_NAMESPACE::libc_errno = 0;
39
40 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
41
42 file = LIBC_NAMESPACE::fopen(FILENAME, "r");
43 ASSERT_FALSE(file == nullptr);
44
45 // The GPU build relies on the host C library, so this check may be different.
46 #ifndef LIBC_TARGET_ARCH_IS_GPU
47 // If we request just 1 byte, it should return just a null byte and not
48 // advance the read head. This is implementation defined.
49 output = LIBC_NAMESPACE::fgets(buff, 1, file);
50 ASSERT_TRUE(output == buff);
51 ASSERT_EQ(buff[0], '\0');
52 ASSERT_ERRNO_SUCCESS();
53
54 // If we request less than 1 byte, it should do nothing and return nullptr.
55 // This is also implementation defined.
56 output = LIBC_NAMESPACE::fgets(buff, 0, file);
57 ASSERT_TRUE(output == nullptr);
58 #endif
59
60 const char *output_arr[] = {
61 "1234567", "89\n", "1234567", "\n", "123456\n", "1",
62 };
63
64 constexpr size_t ARR_SIZE = sizeof(output_arr) / sizeof(char *);
65
66 for (size_t i = 0; i < ARR_SIZE; ++i) {
67 output = LIBC_NAMESPACE::fgets(buff, 8, file);
68
69 // This pointer comparison is intentional, fgets should return a pointer to
70 // buff when it succeeds.
71 ASSERT_TRUE(output == buff);
72 ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
73
74 EXPECT_STREQ(buff, output_arr[i]);
75 }
76
77 // This should have hit the end of the file, but that isn't an error unless it
78 // fails to read anything.
79 ASSERT_NE(LIBC_NAMESPACE::feof(file), 0);
80 ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
81 ASSERT_ERRNO_SUCCESS();
82
83 // Reading more should be an EOF, but not an error.
84 output = LIBC_NAMESPACE::fgets(buff, 8, file);
85 ASSERT_TRUE(output == nullptr);
86 ASSERT_NE(LIBC_NAMESPACE::feof(file), 0);
87 ASSERT_ERRNO_SUCCESS();
88
89 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
90 }
91