1 //===-- Unittests for target platform file implementation -----------------===// 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/__support/File/file.h" 10 #include "test/UnitTest/Test.h" 11 12 #include "hdr/stdio_macros.h" // For SEEK_* macros 13 14 using File = LIBC_NAMESPACE::File; 15 constexpr char TEXT[] = "Hello, File"; 16 constexpr size_t TEXT_SIZE = sizeof(TEXT) - 1; // Ignore the null terminator 17 18 LIBC_INLINE File *openfile(const char *file_name, const char *mode) { 19 auto error_or_file = LIBC_NAMESPACE::openfile(file_name, mode); 20 return error_or_file.has_value() ? error_or_file.value() : nullptr; 21 } 22 23 TEST(LlvmLibcPlatformFileTest, CreateWriteCloseAndReadBack) { 24 constexpr char FILENAME[] = "testdata/create_write_close_and_readback.test"; 25 File *file = openfile(FILENAME, "w"); 26 ASSERT_FALSE(file == nullptr); 27 ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); 28 ASSERT_EQ(file->close(), 0); 29 30 file = openfile(FILENAME, "r"); 31 ASSERT_FALSE(file == nullptr); 32 char data[sizeof(TEXT)]; 33 ASSERT_EQ(file->read(data, TEXT_SIZE).value, TEXT_SIZE); 34 data[TEXT_SIZE] = '\0'; 35 ASSERT_STREQ(data, TEXT); 36 37 // Reading more data should trigger EOF. 38 ASSERT_EQ(file->read(data, TEXT_SIZE).value, size_t(0)); 39 ASSERT_TRUE(file->iseof()); 40 41 ASSERT_EQ(file->close(), 0); 42 } 43 44 TEST(LlvmLibcPlatformFileTest, CreateWriteSeekAndReadBack) { 45 constexpr char FILENAME[] = "testdata/create_write_seek_and_readback.test"; 46 File *file = openfile(FILENAME, "w+"); 47 ASSERT_FALSE(file == nullptr); 48 ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); 49 50 ASSERT_EQ(file->seek(0, SEEK_SET).value(), 0); 51 52 char data[sizeof(TEXT)]; 53 ASSERT_EQ(file->read(data, TEXT_SIZE).value, TEXT_SIZE); 54 data[TEXT_SIZE] = '\0'; 55 ASSERT_STREQ(data, TEXT); 56 57 // Reading more data should trigger EOF. 58 ASSERT_EQ(file->read(data, TEXT_SIZE).value, size_t(0)); 59 ASSERT_TRUE(file->iseof()); 60 61 ASSERT_EQ(file->close(), 0); 62 } 63 64 TEST(LlvmLibcPlatformFileTest, CreateAppendCloseAndReadBack) { 65 constexpr char FILENAME[] = "testdata/create_append_close_and_readback.test"; 66 File *file = openfile(FILENAME, "w"); 67 ASSERT_FALSE(file == nullptr); 68 ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); 69 ASSERT_EQ(file->close(), 0); 70 71 file = openfile(FILENAME, "a"); 72 ASSERT_FALSE(file == nullptr); 73 constexpr char APPEND_TEXT[] = " Append Text"; 74 constexpr size_t APPEND_TEXT_SIZE = sizeof(APPEND_TEXT) - 1; 75 ASSERT_EQ(file->write(APPEND_TEXT, APPEND_TEXT_SIZE).value, APPEND_TEXT_SIZE); 76 ASSERT_EQ(file->close(), 0); 77 78 file = openfile(FILENAME, "r"); 79 ASSERT_FALSE(file == nullptr); 80 constexpr size_t READ_SIZE = TEXT_SIZE + APPEND_TEXT_SIZE; 81 char data[READ_SIZE + 1]; 82 ASSERT_EQ(file->read(data, READ_SIZE).value, READ_SIZE); 83 data[READ_SIZE] = '\0'; 84 ASSERT_STREQ(data, "Hello, File Append Text"); 85 86 // Reading more data should trigger EOF. 87 ASSERT_EQ(file->read(data, READ_SIZE).value, size_t(0)); 88 ASSERT_TRUE(file->iseof()); 89 90 ASSERT_EQ(file->close(), 0); 91 } 92 93 TEST(LlvmLibcPlatformFileTest, CreateAppendSeekAndReadBack) { 94 constexpr char FILENAME[] = "testdata/create_append_seek_and_readback.test"; 95 File *file = openfile(FILENAME, "w"); 96 ASSERT_FALSE(file == nullptr); 97 ASSERT_EQ(file->write(TEXT, TEXT_SIZE).value, TEXT_SIZE); 98 ASSERT_EQ(file->close(), 0); 99 100 file = openfile(FILENAME, "a+"); 101 ASSERT_FALSE(file == nullptr); 102 constexpr char APPEND_TEXT[] = " Append Text"; 103 constexpr size_t APPEND_TEXT_SIZE = sizeof(APPEND_TEXT) - 1; 104 ASSERT_EQ(file->write(APPEND_TEXT, APPEND_TEXT_SIZE).value, APPEND_TEXT_SIZE); 105 106 ASSERT_EQ(file->seek(-static_cast<off_t>(APPEND_TEXT_SIZE), SEEK_END).value(), 107 0); 108 char data[APPEND_TEXT_SIZE + 1]; 109 ASSERT_EQ(file->read(data, APPEND_TEXT_SIZE).value, APPEND_TEXT_SIZE); 110 data[APPEND_TEXT_SIZE] = '\0'; 111 ASSERT_STREQ(data, APPEND_TEXT); 112 113 // Reading more data should trigger EOF. 114 ASSERT_EQ(file->read(data, APPEND_TEXT_SIZE).value, size_t(0)); 115 ASSERT_TRUE(file->iseof()); 116 117 ASSERT_EQ(file->close(), 0); 118 } 119 120 TEST(LlvmLibcPlatformFileTest, LargeFile) { 121 constexpr size_t DATA_SIZE = File::DEFAULT_BUFFER_SIZE >> 2; 122 constexpr char BYTE = 123; 123 char write_data[DATA_SIZE]; 124 for (size_t i = 0; i < DATA_SIZE; ++i) 125 write_data[i] = BYTE; 126 127 constexpr char FILENAME[] = "testdata/large_file.test"; 128 File *file = openfile(FILENAME, "w"); 129 ASSERT_FALSE(file == nullptr); 130 131 constexpr int REPEAT = 5; 132 for (int i = 0; i < REPEAT; ++i) { 133 ASSERT_EQ(file->write(write_data, DATA_SIZE).value, DATA_SIZE); 134 } 135 ASSERT_EQ(file->close(), 0); 136 137 file = openfile(FILENAME, "r"); 138 ASSERT_FALSE(file == nullptr); 139 constexpr size_t READ_SIZE = DATA_SIZE * REPEAT; 140 char data[READ_SIZE] = {0}; 141 ASSERT_EQ(file->read(data, READ_SIZE).value, READ_SIZE); 142 143 for (size_t i = 0; i < READ_SIZE; ++i) 144 ASSERT_EQ(data[i], BYTE); 145 146 // Reading more data should trigger EOF. 147 ASSERT_EQ(file->read(data, 1).value, size_t(0)); 148 ASSERT_TRUE(file->iseof()); 149 150 ASSERT_EQ(file->close(), 0); 151 } 152 153 TEST(LlvmLibcPlatformFileTest, ReadSeekCurAndRead) { 154 constexpr char FILENAME[] = "testdata/read_seek_cur_and_read.test"; 155 File *file = openfile(FILENAME, "w"); 156 ASSERT_FALSE(file == nullptr); 157 constexpr char CONTENT[] = "1234567890987654321"; 158 ASSERT_EQ(sizeof(CONTENT) - 1, 159 file->write(CONTENT, sizeof(CONTENT) - 1).value); 160 ASSERT_EQ(0, file->close()); 161 162 file = openfile(FILENAME, "r"); 163 ASSERT_FALSE(file == nullptr); 164 165 constexpr size_t READ_SIZE = 5; 166 char data[READ_SIZE]; 167 data[READ_SIZE - 1] = '\0'; 168 ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); 169 ASSERT_STREQ(data, "1234"); 170 ASSERT_EQ(file->seek(5, SEEK_CUR).value(), 0); 171 ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); 172 ASSERT_STREQ(data, "0987"); 173 ASSERT_EQ(file->seek(-5, SEEK_CUR).value(), 0); 174 ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); 175 ASSERT_STREQ(data, "9098"); 176 177 ASSERT_EQ(file->close(), 0); 178 } 179 180 TEST(LlvmLibcPlatformFileTest, IncorrectOperation) { 181 constexpr char FILENAME[] = "testdata/incorrect_operation.test"; 182 char data[1] = {123}; 183 184 File *file = openfile(FILENAME, "w"); 185 ASSERT_FALSE(file == nullptr); 186 ASSERT_EQ(file->read(data, 1).value, size_t(0)); // Cannot read 187 ASSERT_FALSE(file->iseof()); 188 ASSERT_TRUE(file->error()); 189 ASSERT_EQ(file->close(), 0); 190 191 file = openfile(FILENAME, "r"); 192 ASSERT_FALSE(file == nullptr); 193 ASSERT_EQ(file->write(data, 1).value, size_t(0)); // Cannot write 194 ASSERT_FALSE(file->iseof()); 195 ASSERT_TRUE(file->error()); 196 ASSERT_EQ(file->close(), 0); 197 198 file = openfile(FILENAME, "a"); 199 ASSERT_FALSE(file == nullptr); 200 ASSERT_EQ(file->read(data, 1).value, size_t(0)); // Cannot read 201 ASSERT_FALSE(file->iseof()); 202 ASSERT_TRUE(file->error()); 203 ASSERT_EQ(file->close(), 0); 204 } 205