1 //===-- Unittests for ungetc ----------------------------------------------===// 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/ungetc.h" 10 11 #include "hdr/stdio_macros.h" 12 #include "src/stdio/fclose.h" 13 #include "src/stdio/fopen.h" 14 #include "src/stdio/fread.h" 15 #include "src/stdio/fseek.h" 16 #include "src/stdio/fwrite.h" 17 #include "test/UnitTest/Test.h" 18 19 TEST(LlvmLibcUngetcTest, UngetAndReadBack) { 20 constexpr char FILENAME[] = "testdata/ungetc_test.test"; 21 ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); 22 ASSERT_FALSE(file == nullptr); 23 constexpr char CONTENT[] = "abcdef"; 24 constexpr size_t CONTENT_SIZE = sizeof(CONTENT); 25 ASSERT_EQ(CONTENT_SIZE, 26 LIBC_NAMESPACE::fwrite(CONTENT, 1, CONTENT_SIZE, file)); 27 #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 28 // Cannot unget to an un-readable file. 29 ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc('1', file)); 30 #endif 31 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 32 33 file = LIBC_NAMESPACE::fopen(FILENAME, "r+"); 34 ASSERT_FALSE(file == nullptr); 35 // Calling with an EOF should always return EOF without doing anything. 36 ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc(EOF, file)); 37 char c; 38 ASSERT_EQ(LIBC_NAMESPACE::fread(&c, 1, 1, file), size_t(1)); 39 ASSERT_EQ(c, CONTENT[0]); 40 ASSERT_EQ(LIBC_NAMESPACE::ungetc(int(c), file), int(c)); 41 42 char data[CONTENT_SIZE]; 43 ASSERT_EQ(CONTENT_SIZE, LIBC_NAMESPACE::fread(data, 1, CONTENT_SIZE, file)); 44 ASSERT_STREQ(CONTENT, data); 45 46 ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, 0, SEEK_SET)); 47 // ungetc should not fail after a seek operation. 48 int unget_char = 'z'; 49 ASSERT_EQ(unget_char, LIBC_NAMESPACE::ungetc(unget_char, file)); 50 #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 51 // Another unget should fail. 52 ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc(unget_char, file)); 53 #endif 54 // ungetting a char at the beginning of the file will allow us to fetch 55 // one additional character. 56 char new_data[CONTENT_SIZE + 1]; 57 ASSERT_EQ(CONTENT_SIZE + 1, 58 LIBC_NAMESPACE::fread(new_data, 1, CONTENT_SIZE + 1, file)); 59 ASSERT_STREQ("zabcdef", new_data); 60 61 ASSERT_EQ(size_t(1), LIBC_NAMESPACE::fwrite("x", 1, 1, file)); 62 #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 63 // unget should fail after a write operation. 64 ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc('1', file)); 65 #endif 66 67 ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 68 } 69