1 //===-- Unittests for setvbuf ---------------------------------------------===// 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/fopen.h" 11 #include "src/stdio/fread.h" 12 #include "src/stdio/fwrite.h" 13 #include "src/stdio/setvbuf.h" 14 #include "test/UnitTest/Test.h" 15 16 #include "hdr/stdio_macros.h" 17 #include "src/errno/libc_errno.h" 18 19 TEST(LlvmLibcSetvbufTest, SetNBFBuffer) { 20 // The idea in this test is that we open a file for writing and reading, and 21 // then set a NBF buffer to the write handle. Since it is NBF, the data 22 // written using the write handle should be immediately readable by the read 23 // handle. 24 constexpr char FILENAME[] = "testdata/setvbuf_nbf.test"; 25 26 ::FILE *fw = LIBC_NAMESPACE::fopen(FILENAME, "w"); 27 ASSERT_FALSE(fw == nullptr); 28 char buffer[BUFSIZ]; 29 ASSERT_EQ(LIBC_NAMESPACE::setvbuf(fw, buffer, _IONBF, BUFSIZ), 0); 30 31 ::FILE *fr = LIBC_NAMESPACE::fopen(FILENAME, "r"); 32 ASSERT_FALSE(fr == nullptr); 33 34 constexpr char CONTENT[] = "abcdef"; 35 constexpr size_t CONTENT_SIZE = sizeof(CONTENT); 36 for (size_t i = 0; i < CONTENT_SIZE; ++i) { 37 ASSERT_EQ(size_t(1), LIBC_NAMESPACE::fwrite(CONTENT + i, 1, 1, fw)); 38 char c; 39 ASSERT_EQ(size_t(1), LIBC_NAMESPACE::fread(&c, 1, 1, fr)); 40 ASSERT_EQ(c, CONTENT[i]); 41 } 42 43 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fw)); 44 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fr)); 45 46 // Make sure NBF buffer has no effect for reading. 47 fr = LIBC_NAMESPACE::fopen(FILENAME, "r"); 48 char data[CONTENT_SIZE]; 49 ASSERT_EQ(LIBC_NAMESPACE::setvbuf(fr, buffer, _IONBF, BUFSIZ), 0); 50 ASSERT_EQ(CONTENT_SIZE, LIBC_NAMESPACE::fread(data, 1, CONTENT_SIZE, fr)); 51 ASSERT_STREQ(CONTENT, data); 52 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fr)); 53 } 54 55 TEST(LlvmLibcSetvbufTest, SetLBFBuffer) { 56 // The idea in this test is that we open a file for writing and reading, and 57 // then set a LBF buffer to the write handle. Since it is LBF, the data 58 // written using the write handle should be available right after a '\n' is 59 // written. 60 constexpr char FILENAME[] = "testdata/setvbuf_lbf.test"; 61 62 ::FILE *fw = LIBC_NAMESPACE::fopen(FILENAME, "w"); 63 ASSERT_FALSE(fw == nullptr); 64 char buffer[BUFSIZ]; 65 ASSERT_EQ(LIBC_NAMESPACE::setvbuf(fw, buffer, _IOLBF, BUFSIZ), 0); 66 67 ::FILE *fr = LIBC_NAMESPACE::fopen(FILENAME, "r"); 68 ASSERT_FALSE(fr == nullptr); 69 70 constexpr char CONTENT[] = "abcdef\n"; 71 constexpr size_t CONTENT_SIZE = sizeof(CONTENT); 72 ASSERT_EQ(CONTENT_SIZE, LIBC_NAMESPACE::fwrite(CONTENT, 1, CONTENT_SIZE, fw)); 73 74 // Note that CONTENT_SIZE worth of data written also includes the 75 // null-terminator '\0'. But, since it is after the new line character, 76 // it should not be availabe for reading. 77 char data[CONTENT_SIZE]; 78 ASSERT_EQ(CONTENT_SIZE - 1, LIBC_NAMESPACE::fread(data, 1, CONTENT_SIZE, fr)); 79 char c; 80 ASSERT_EQ(size_t(0), LIBC_NAMESPACE::fread(&c, 1, 1, fr)); 81 82 data[CONTENT_SIZE - 1] = '\0'; 83 ASSERT_STREQ(CONTENT, data); 84 85 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fw)); 86 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fr)); 87 88 // Make sure LBF buffer has no effect for reading. 89 fr = LIBC_NAMESPACE::fopen(FILENAME, "r"); 90 ASSERT_EQ(LIBC_NAMESPACE::setvbuf(fr, buffer, _IOLBF, BUFSIZ), 0); 91 ASSERT_EQ(CONTENT_SIZE, LIBC_NAMESPACE::fread(data, 1, CONTENT_SIZE, fr)); 92 ASSERT_STREQ(CONTENT, data); 93 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(fr)); 94 } 95 96 TEST(LlvmLibcSetbufTest, InvalidBufferMode) { 97 constexpr char FILENAME[] = "testdata/setvbuf_invalid_bufmode.test"; 98 ::FILE *f = LIBC_NAMESPACE::fopen(FILENAME, "w"); 99 ASSERT_FALSE(f == nullptr); 100 char buf[BUFSIZ]; 101 ASSERT_NE(LIBC_NAMESPACE::setvbuf(f, buf, _IOFBF + _IOLBF + _IONBF, BUFSIZ), 102 0); 103 ASSERT_ERRNO_EQ(EINVAL); 104 105 LIBC_NAMESPACE::libc_errno = 0; 106 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(f)); 107 } 108