11ceafe5eSSiva Chandra Reddy //===-- Unittests for ungetc ----------------------------------------------===// 21ceafe5eSSiva Chandra Reddy // 31ceafe5eSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41ceafe5eSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 51ceafe5eSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61ceafe5eSSiva Chandra Reddy // 71ceafe5eSSiva Chandra Reddy //===----------------------------------------------------------------------===// 81ceafe5eSSiva Chandra Reddy 9*c63112a9Slntue #include "src/stdio/ungetc.h" 10*c63112a9Slntue 11*c63112a9Slntue #include "hdr/stdio_macros.h" 121ceafe5eSSiva Chandra Reddy #include "src/stdio/fclose.h" 131ceafe5eSSiva Chandra Reddy #include "src/stdio/fopen.h" 141ceafe5eSSiva Chandra Reddy #include "src/stdio/fread.h" 151ceafe5eSSiva Chandra Reddy #include "src/stdio/fseek.h" 161ceafe5eSSiva Chandra Reddy #include "src/stdio/fwrite.h" 17af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 181ceafe5eSSiva Chandra Reddy 191ceafe5eSSiva Chandra Reddy TEST(LlvmLibcUngetcTest, UngetAndReadBack) { 201ceafe5eSSiva Chandra Reddy constexpr char FILENAME[] = "testdata/ungetc_test.test"; 21b6bc9d72SGuillaume Chatelet ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); 221ceafe5eSSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 231ceafe5eSSiva Chandra Reddy constexpr char CONTENT[] = "abcdef"; 241ceafe5eSSiva Chandra Reddy constexpr size_t CONTENT_SIZE = sizeof(CONTENT); 25b6bc9d72SGuillaume Chatelet ASSERT_EQ(CONTENT_SIZE, 26b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fwrite(CONTENT, 1, CONTENT_SIZE, file)); 27ddc30ff8SJoseph Huber #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 281ceafe5eSSiva Chandra Reddy // Cannot unget to an un-readable file. 29b6bc9d72SGuillaume Chatelet ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc('1', file)); 30ddc30ff8SJoseph Huber #endif 31b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 321ceafe5eSSiva Chandra Reddy 33b6bc9d72SGuillaume Chatelet file = LIBC_NAMESPACE::fopen(FILENAME, "r+"); 341ceafe5eSSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 35ddc30ff8SJoseph Huber // Calling with an EOF should always return EOF without doing anything. 36ddc30ff8SJoseph Huber ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc(EOF, file)); 371ceafe5eSSiva Chandra Reddy char c; 38b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(&c, 1, 1, file), size_t(1)); 391ceafe5eSSiva Chandra Reddy ASSERT_EQ(c, CONTENT[0]); 40b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::ungetc(int(c), file), int(c)); 411ceafe5eSSiva Chandra Reddy 421ceafe5eSSiva Chandra Reddy char data[CONTENT_SIZE]; 43b6bc9d72SGuillaume Chatelet ASSERT_EQ(CONTENT_SIZE, LIBC_NAMESPACE::fread(data, 1, CONTENT_SIZE, file)); 441ceafe5eSSiva Chandra Reddy ASSERT_STREQ(CONTENT, data); 451ceafe5eSSiva Chandra Reddy 46b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, 0, SEEK_SET)); 471ceafe5eSSiva Chandra Reddy // ungetc should not fail after a seek operation. 481ceafe5eSSiva Chandra Reddy int unget_char = 'z'; 49b6bc9d72SGuillaume Chatelet ASSERT_EQ(unget_char, LIBC_NAMESPACE::ungetc(unget_char, file)); 50ddc30ff8SJoseph Huber #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 511ceafe5eSSiva Chandra Reddy // Another unget should fail. 52b6bc9d72SGuillaume Chatelet ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc(unget_char, file)); 53ddc30ff8SJoseph Huber #endif 541ceafe5eSSiva Chandra Reddy // ungetting a char at the beginning of the file will allow us to fetch 551ceafe5eSSiva Chandra Reddy // one additional character. 561ceafe5eSSiva Chandra Reddy char new_data[CONTENT_SIZE + 1]; 571ceafe5eSSiva Chandra Reddy ASSERT_EQ(CONTENT_SIZE + 1, 58b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fread(new_data, 1, CONTENT_SIZE + 1, file)); 591ceafe5eSSiva Chandra Reddy ASSERT_STREQ("zabcdef", new_data); 601ceafe5eSSiva Chandra Reddy 61b6bc9d72SGuillaume Chatelet ASSERT_EQ(size_t(1), LIBC_NAMESPACE::fwrite("x", 1, 1, file)); 62ddc30ff8SJoseph Huber #ifndef LIBC_TARGET_ARCH_IS_GPU // Behavior varies between libc implementations. 631ceafe5eSSiva Chandra Reddy // unget should fail after a write operation. 64b6bc9d72SGuillaume Chatelet ASSERT_EQ(EOF, LIBC_NAMESPACE::ungetc('1', file)); 65ddc30ff8SJoseph Huber #endif 661ceafe5eSSiva Chandra Reddy 67b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 681ceafe5eSSiva Chandra Reddy } 69