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 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