xref: /aosp_15_r20/external/llvm-libc/test/src/stdio/fgets_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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