1441606f5SSiva Chandra Reddy //===-- Unittests for file operations like fopen, flcose etc --------------===// 2441606f5SSiva Chandra Reddy // 3441606f5SSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4441606f5SSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 5441606f5SSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6441606f5SSiva Chandra Reddy // 7441606f5SSiva Chandra Reddy //===----------------------------------------------------------------------===// 8441606f5SSiva Chandra Reddy 99db0037bSSiva Chandra Reddy #include "src/stdio/clearerr.h" 10441606f5SSiva Chandra Reddy #include "src/stdio/fclose.h" 119db0037bSSiva Chandra Reddy #include "src/stdio/feof.h" 129db0037bSSiva Chandra Reddy #include "src/stdio/ferror.h" 1322f9dca1SSiva Chandra Reddy #include "src/stdio/fflush.h" 1427d7bb86SNick Desaulniers #include "src/stdio/fileno.h" 15441606f5SSiva Chandra Reddy #include "src/stdio/fopen.h" 16a9e0dbefSMichael Jones #include "src/stdio/fputs.h" 17441606f5SSiva Chandra Reddy #include "src/stdio/fread.h" 18441606f5SSiva Chandra Reddy #include "src/stdio/fseek.h" 19441606f5SSiva Chandra Reddy #include "src/stdio/fwrite.h" 2062a3d84fSSiva Chandra #include "test/UnitTest/ErrnoSetterMatcher.h" 21af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 22441606f5SSiva Chandra Reddy 23*c63112a9Slntue #include "hdr/stdio_macros.h" 2404a9c625SMichael Jones #include "src/errno/libc_errno.h" 25441606f5SSiva Chandra Reddy 26b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::EQ; 27b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::NE; 28b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::returns; 2962a3d84fSSiva Chandra 309db0037bSSiva Chandra Reddy TEST(LlvmLibcFILETest, SimpleFileOperations) { 31441606f5SSiva Chandra Reddy constexpr char FILENAME[] = "testdata/simple_operations.test"; 32b6bc9d72SGuillaume Chatelet ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); 33441606f5SSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 34ca04b56aSShourya Goel ASSERT_EQ(LIBC_NAMESPACE::fileno(file), 3); 35441606f5SSiva Chandra Reddy constexpr char CONTENT[] = "1234567890987654321"; 36441606f5SSiva Chandra Reddy ASSERT_EQ(sizeof(CONTENT) - 1, 37b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file)); 389db0037bSSiva Chandra Reddy 399db0037bSSiva Chandra Reddy // This is not a readable file. 409db0037bSSiva Chandra Reddy char read_data[sizeof(CONTENT)]; 41b6bc9d72SGuillaume Chatelet ASSERT_THAT(LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT), file), 4262a3d84fSSiva Chandra returns(EQ(size_t(0))).with_errno(NE(0))); 43b6bc9d72SGuillaume Chatelet ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0); 443eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 459db0037bSSiva Chandra Reddy 46b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::clearerr(file); 47b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0); 489db0037bSSiva Chandra Reddy 49b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 50441606f5SSiva Chandra Reddy 51b6bc9d72SGuillaume Chatelet file = LIBC_NAMESPACE::fopen(FILENAME, "r"); 52441606f5SSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 53441606f5SSiva Chandra Reddy 54441606f5SSiva Chandra Reddy constexpr size_t READ_SIZE = 5; 55441606f5SSiva Chandra Reddy char data[READ_SIZE]; 56441606f5SSiva Chandra Reddy data[READ_SIZE - 1] = '\0'; 57b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1); 58441606f5SSiva Chandra Reddy ASSERT_STREQ(data, "1234"); 59b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fseek(file, 5, SEEK_CUR), 0); 60b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1); 61441606f5SSiva Chandra Reddy ASSERT_STREQ(data, "0987"); 62b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fseek(file, -5, SEEK_CUR), 0); 63b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1); 64441606f5SSiva Chandra Reddy ASSERT_STREQ(data, "9098"); 65441606f5SSiva Chandra Reddy 669db0037bSSiva Chandra Reddy // Reading another time should trigger eof. 679db0037bSSiva Chandra Reddy ASSERT_NE(sizeof(CONTENT), 68b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT), file)); 69b6bc9d72SGuillaume Chatelet ASSERT_NE(LIBC_NAMESPACE::feof(file), 0); 709db0037bSSiva Chandra Reddy 719db0037bSSiva Chandra Reddy // Should be an error to write. 72b6bc9d72SGuillaume Chatelet ASSERT_THAT(LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT), file), 7362a3d84fSSiva Chandra returns(EQ(size_t(0))).with_errno(NE(0))); 74b6bc9d72SGuillaume Chatelet ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0); 753eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 769db0037bSSiva Chandra Reddy 77b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::clearerr(file); 78a9e0dbefSMichael Jones 79a9e0dbefSMichael Jones // Should be an error to puts. 80b6bc9d72SGuillaume Chatelet ASSERT_THAT(LIBC_NAMESPACE::fputs(CONTENT, file), 8162a3d84fSSiva Chandra returns(EQ(EOF)).with_errno(NE(0))); 82b6bc9d72SGuillaume Chatelet ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0); 833eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 84a9e0dbefSMichael Jones 85b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::clearerr(file); 86b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0); 879db0037bSSiva Chandra Reddy 883eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 89b6bc9d72SGuillaume Chatelet ASSERT_THAT(LIBC_NAMESPACE::fwrite("nothing", 1, 1, file), 9062a3d84fSSiva Chandra returns(EQ(0)).with_errno(NE(0))); 913eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 929beb8d11SMichael Jones 93b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0); 94a9e0dbefSMichael Jones 95a9e0dbefSMichael Jones // Now try puts. 96b6bc9d72SGuillaume Chatelet file = LIBC_NAMESPACE::fopen(FILENAME, "w"); 97a9e0dbefSMichael Jones ASSERT_FALSE(file == nullptr); 98a9e0dbefSMichael Jones // fputs returns a negative value on error (EOF) or any non-negative value on 99a9e0dbefSMichael Jones // success. This assert checks that the return value is non-negative. 100b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::fputs(CONTENT, file), 0); 101a9e0dbefSMichael Jones 102b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::clearerr(file); 103b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0); 104a9e0dbefSMichael Jones 1059beb8d11SMichael Jones // This is not a readable file. 1063eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 107b6bc9d72SGuillaume Chatelet ASSERT_THAT(LIBC_NAMESPACE::fread(data, 1, 1, file), 10862a3d84fSSiva Chandra returns(EQ(0)).with_errno(NE(0))); 1093eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 1109beb8d11SMichael Jones 111b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file)); 112a9e0dbefSMichael Jones 113b6bc9d72SGuillaume Chatelet file = LIBC_NAMESPACE::fopen(FILENAME, "r"); 114a9e0dbefSMichael Jones ASSERT_FALSE(file == nullptr); 115a9e0dbefSMichael Jones 116b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT) - 1, file), 117a9e0dbefSMichael Jones sizeof(CONTENT) - 1); 118a9e0dbefSMichael Jones read_data[sizeof(CONTENT) - 1] = '\0'; 119a9e0dbefSMichael Jones ASSERT_STREQ(read_data, CONTENT); 120b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0); 1219beb8d11SMichael Jones 12204a9c625SMichael Jones // Check that the other functions correctly set libc_errno. 1239beb8d11SMichael Jones 1243eb1e6d8Smichaelrj-google // LIBC_NAMESPACE::libc_errno = 0; 125b6bc9d72SGuillaume Chatelet // ASSERT_NE(LIBC_NAMESPACE::fseek(file, 0, SEEK_SET), 0); 12673874f7aSGuillaume Chatelet // ASSERT_ERRNO_FAILURE(); 1279beb8d11SMichael Jones 1283eb1e6d8Smichaelrj-google // LIBC_NAMESPACE::libc_errno = 0; 129b6bc9d72SGuillaume Chatelet // ASSERT_NE(LIBC_NAMESPACE::fclose(file), 0); 13073874f7aSGuillaume Chatelet // ASSERT_ERRNO_FAILURE(); 1319beb8d11SMichael Jones 1323eb1e6d8Smichaelrj-google // LIBC_NAMESPACE::libc_errno = 0; 133b6bc9d72SGuillaume Chatelet // ASSERT_EQ(LIBC_NAMESPACE::fopen("INVALID FILE NAME", "r"), 134816b5e54SMichael Jones // static_cast<FILE *>(nullptr)); 13573874f7aSGuillaume Chatelet // ASSERT_ERRNO_FAILURE(); 136441606f5SSiva Chandra Reddy } 13722f9dca1SSiva Chandra Reddy 1389db0037bSSiva Chandra Reddy TEST(LlvmLibcFILETest, FFlush) { 13922f9dca1SSiva Chandra Reddy constexpr char FILENAME[] = "testdata/fflush.test"; 140b6bc9d72SGuillaume Chatelet ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w+"); 14122f9dca1SSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 14222f9dca1SSiva Chandra Reddy constexpr char CONTENT[] = "1234567890987654321"; 14322f9dca1SSiva Chandra Reddy ASSERT_EQ(sizeof(CONTENT), 144b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT), file)); 14522f9dca1SSiva Chandra Reddy 14622f9dca1SSiva Chandra Reddy // Flushing at this point should write the data to disk. So, we should be 14722f9dca1SSiva Chandra Reddy // able to read it back. 148b6bc9d72SGuillaume Chatelet ASSERT_EQ(0, LIBC_NAMESPACE::fflush(file)); 14922f9dca1SSiva Chandra Reddy 15022f9dca1SSiva Chandra Reddy char data[sizeof(CONTENT)]; 151b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fseek(file, 0, SEEK_SET), 0); 152b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, sizeof(CONTENT), file), 15322f9dca1SSiva Chandra Reddy sizeof(CONTENT)); 15422f9dca1SSiva Chandra Reddy ASSERT_STREQ(data, CONTENT); 15522f9dca1SSiva Chandra Reddy 156b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0); 15722f9dca1SSiva Chandra Reddy } 15853c251bdSSiva Chandra Reddy 15953c251bdSSiva Chandra Reddy TEST(LlvmLibcFILETest, FOpenFWriteSizeGreaterThanOne) { 16053c251bdSSiva Chandra Reddy using MyStruct = struct { 16153c251bdSSiva Chandra Reddy char c; 16253c251bdSSiva Chandra Reddy unsigned long long i; 16353c251bdSSiva Chandra Reddy }; 16453c251bdSSiva Chandra Reddy constexpr MyStruct WRITE_DATA[] = {{'a', 1}, {'b', 2}, {'c', 3}}; 16553c251bdSSiva Chandra Reddy constexpr size_t WRITE_NMEMB = sizeof(WRITE_DATA) / sizeof(MyStruct); 16653c251bdSSiva Chandra Reddy constexpr char FILENAME[] = "testdata/fread_fwrite.test"; 16753c251bdSSiva Chandra Reddy 1683eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 169b6bc9d72SGuillaume Chatelet FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); 17053c251bdSSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 171b6bc9d72SGuillaume Chatelet ASSERT_EQ(size_t(0), LIBC_NAMESPACE::fwrite(WRITE_DATA, 0, 1, file)); 17262a3d84fSSiva Chandra ASSERT_THAT( 173b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fwrite(WRITE_DATA, sizeof(MyStruct), WRITE_NMEMB, file), 17462a3d84fSSiva Chandra returns(EQ(WRITE_NMEMB)).with_errno(EQ(0))); 175b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0); 17653c251bdSSiva Chandra Reddy 177b6bc9d72SGuillaume Chatelet file = LIBC_NAMESPACE::fopen(FILENAME, "r"); 17853c251bdSSiva Chandra Reddy ASSERT_FALSE(file == nullptr); 17953c251bdSSiva Chandra Reddy MyStruct read_data[WRITE_NMEMB]; 180b6bc9d72SGuillaume Chatelet ASSERT_EQ(size_t(0), LIBC_NAMESPACE::fread(read_data, 0, 1, file)); 18162a3d84fSSiva Chandra ASSERT_THAT( 182b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file), 18362a3d84fSSiva Chandra returns(EQ(WRITE_NMEMB)).with_errno(EQ(0))); 18453c251bdSSiva Chandra Reddy // Trying to read more should fetch nothing. 18562a3d84fSSiva Chandra ASSERT_THAT( 186b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file), 18762a3d84fSSiva Chandra returns(EQ(0)).with_errno(EQ(0))); 188b6bc9d72SGuillaume Chatelet EXPECT_NE(LIBC_NAMESPACE::feof(file), 0); 189b6bc9d72SGuillaume Chatelet EXPECT_EQ(LIBC_NAMESPACE::ferror(file), 0); 190b6bc9d72SGuillaume Chatelet ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0); 19153c251bdSSiva Chandra Reddy // Verify that the data which was read is correct. 19253c251bdSSiva Chandra Reddy for (size_t i = 0; i < WRITE_NMEMB; ++i) { 19353c251bdSSiva Chandra Reddy ASSERT_EQ(read_data[i].c, WRITE_DATA[i].c); 19453c251bdSSiva Chandra Reddy ASSERT_EQ(read_data[i].i, WRITE_DATA[i].i); 19553c251bdSSiva Chandra Reddy } 19653c251bdSSiva Chandra Reddy } 197