xref: /llvm-project/libc/test/src/stdio/fgets_test.cpp (revision c63112a9118277a20ae440f3f69189c0937e8f4d)
12d522833SMichael Jones //===-- Unittests for fgets -----------------------------------------------===//
22d522833SMichael Jones //
32d522833SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42d522833SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
52d522833SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62d522833SMichael Jones //
72d522833SMichael Jones //===----------------------------------------------------------------------===//
82d522833SMichael Jones 
92d522833SMichael Jones #include "src/stdio/fclose.h"
102d522833SMichael Jones #include "src/stdio/feof.h"
112d522833SMichael Jones #include "src/stdio/ferror.h"
122d522833SMichael Jones #include "src/stdio/fgets.h"
132d522833SMichael Jones #include "src/stdio/fopen.h"
142d522833SMichael Jones #include "src/stdio/fwrite.h"
15af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
162d522833SMichael Jones 
1704a9c625SMichael Jones #include "src/errno/libc_errno.h"
182d522833SMichael Jones 
192d522833SMichael Jones TEST(LlvmLibcFgetsTest, WriteAndReadCharacters) {
202d522833SMichael Jones   constexpr char FILENAME[] = "testdata/fgets.test";
21b6bc9d72SGuillaume Chatelet   ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w");
222d522833SMichael Jones   ASSERT_FALSE(file == nullptr);
232d522833SMichael Jones   constexpr char CONTENT[] = "123456789\n"
242d522833SMichael Jones                              "1234567\n"
252d522833SMichael Jones                              "123456\n"
262d522833SMichael Jones                              "1";
272d522833SMichael Jones   constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
282d522833SMichael Jones 
292d522833SMichael Jones   char buff[8];
302d522833SMichael Jones   char *output;
312d522833SMichael Jones 
32b6bc9d72SGuillaume Chatelet   ASSERT_EQ(WRITE_SIZE, LIBC_NAMESPACE::fwrite(CONTENT, 1, WRITE_SIZE, file));
332d522833SMichael Jones   // This is a write-only file so reads should fail.
34b6bc9d72SGuillaume Chatelet   ASSERT_TRUE(LIBC_NAMESPACE::fgets(buff, 8, file) == nullptr);
352d522833SMichael Jones   // This is an error and not a real EOF.
36b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::feof(file), 0);
37b6bc9d72SGuillaume Chatelet   ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0);
383eb1e6d8Smichaelrj-google   LIBC_NAMESPACE::libc_errno = 0;
392d522833SMichael Jones 
40b6bc9d72SGuillaume Chatelet   ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
412d522833SMichael Jones 
42b6bc9d72SGuillaume Chatelet   file = LIBC_NAMESPACE::fopen(FILENAME, "r");
432d522833SMichael Jones   ASSERT_FALSE(file == nullptr);
442d522833SMichael Jones 
45*95c0e033SJoseph Huber   // The GPU build relies on the host C library, so this check may be different.
46*95c0e033SJoseph Huber #ifndef LIBC_TARGET_ARCH_IS_GPU
472d522833SMichael Jones   // If we request just 1 byte, it should return just a null byte and not
482d522833SMichael Jones   // advance the read head. This is implementation defined.
49b6bc9d72SGuillaume Chatelet   output = LIBC_NAMESPACE::fgets(buff, 1, file);
502d522833SMichael Jones   ASSERT_TRUE(output == buff);
512d522833SMichael Jones   ASSERT_EQ(buff[0], '\0');
5273874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
532d522833SMichael Jones 
542d522833SMichael Jones   // If we request less than 1 byte, it should do nothing and return nullptr.
552d522833SMichael Jones   // This is also implementation defined.
56b6bc9d72SGuillaume Chatelet   output = LIBC_NAMESPACE::fgets(buff, 0, file);
572d522833SMichael Jones   ASSERT_TRUE(output == nullptr);
58*95c0e033SJoseph Huber #endif
592d522833SMichael Jones 
602d522833SMichael Jones   const char *output_arr[] = {
612d522833SMichael Jones       "1234567", "89\n", "1234567", "\n", "123456\n", "1",
622d522833SMichael Jones   };
632d522833SMichael Jones 
642d522833SMichael Jones   constexpr size_t ARR_SIZE = sizeof(output_arr) / sizeof(char *);
652d522833SMichael Jones 
662d522833SMichael Jones   for (size_t i = 0; i < ARR_SIZE; ++i) {
67b6bc9d72SGuillaume Chatelet     output = LIBC_NAMESPACE::fgets(buff, 8, file);
682d522833SMichael Jones 
692d522833SMichael Jones     // This pointer comparison is intentional, fgets should return a pointer to
702d522833SMichael Jones     // buff when it succeeds.
712d522833SMichael Jones     ASSERT_TRUE(output == buff);
72b6bc9d72SGuillaume Chatelet     ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
732d522833SMichael Jones 
742d522833SMichael Jones     EXPECT_STREQ(buff, output_arr[i]);
752d522833SMichael Jones   }
762d522833SMichael Jones 
772d522833SMichael Jones   // This should have hit the end of the file, but that isn't an error unless it
782d522833SMichael Jones   // fails to read anything.
79b6bc9d72SGuillaume Chatelet   ASSERT_NE(LIBC_NAMESPACE::feof(file), 0);
80b6bc9d72SGuillaume Chatelet   ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
8173874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
822d522833SMichael Jones 
832d522833SMichael Jones   // Reading more should be an EOF, but not an error.
84b6bc9d72SGuillaume Chatelet   output = LIBC_NAMESPACE::fgets(buff, 8, file);
852d522833SMichael Jones   ASSERT_TRUE(output == nullptr);
86b6bc9d72SGuillaume Chatelet   ASSERT_NE(LIBC_NAMESPACE::feof(file), 0);
8773874f7aSGuillaume Chatelet   ASSERT_ERRNO_SUCCESS();
882d522833SMichael Jones 
89b6bc9d72SGuillaume Chatelet   ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
902d522833SMichael Jones }
91