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