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