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 <stdio.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(path: 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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(file_name: FILENAME, mode: "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(-APPEND_TEXT_SIZE, SEEK_END).value(), 0); |
107 | char data[APPEND_TEXT_SIZE + 1]; |
108 | ASSERT_EQ(file->read(data, APPEND_TEXT_SIZE).value, APPEND_TEXT_SIZE); |
109 | data[APPEND_TEXT_SIZE] = '\0'; |
110 | ASSERT_STREQ(data, APPEND_TEXT); |
111 | |
112 | // Reading more data should trigger EOF. |
113 | ASSERT_EQ(file->read(data, APPEND_TEXT_SIZE).value, size_t(0)); |
114 | ASSERT_TRUE(file->iseof()); |
115 | |
116 | ASSERT_EQ(file->close(), 0); |
117 | } |
118 | |
119 | TEST(LlvmLibcPlatformFileTest, LargeFile) { |
120 | constexpr size_t DATA_SIZE = File::DEFAULT_BUFFER_SIZE >> 2; |
121 | constexpr char BYTE = 123; |
122 | char write_data[DATA_SIZE]; |
123 | for (size_t i = 0; i < DATA_SIZE; ++i) |
124 | write_data[i] = BYTE; |
125 | |
126 | constexpr char FILENAME[] = "testdata/large_file.test" ; |
127 | File *file = openfile(file_name: FILENAME, mode: "w" ); |
128 | ASSERT_FALSE(file == nullptr); |
129 | |
130 | constexpr int REPEAT = 5; |
131 | for (int i = 0; i < REPEAT; ++i) { |
132 | ASSERT_EQ(file->write(write_data, DATA_SIZE).value, DATA_SIZE); |
133 | } |
134 | ASSERT_EQ(file->close(), 0); |
135 | |
136 | file = openfile(file_name: FILENAME, mode: "r" ); |
137 | ASSERT_FALSE(file == nullptr); |
138 | constexpr size_t READ_SIZE = DATA_SIZE * REPEAT; |
139 | char data[READ_SIZE] = {0}; |
140 | ASSERT_EQ(file->read(data, READ_SIZE).value, READ_SIZE); |
141 | |
142 | for (size_t i = 0; i < READ_SIZE; ++i) |
143 | ASSERT_EQ(data[i], BYTE); |
144 | |
145 | // Reading more data should trigger EOF. |
146 | ASSERT_EQ(file->read(data, 1).value, size_t(0)); |
147 | ASSERT_TRUE(file->iseof()); |
148 | |
149 | ASSERT_EQ(file->close(), 0); |
150 | } |
151 | |
152 | TEST(LlvmLibcPlatformFileTest, ReadSeekCurAndRead) { |
153 | constexpr char FILENAME[] = "testdata/read_seek_cur_and_read.test" ; |
154 | File *file = openfile(file_name: FILENAME, mode: "w" ); |
155 | ASSERT_FALSE(file == nullptr); |
156 | constexpr char CONTENT[] = "1234567890987654321" ; |
157 | ASSERT_EQ(sizeof(CONTENT) - 1, |
158 | file->write(CONTENT, sizeof(CONTENT) - 1).value); |
159 | ASSERT_EQ(0, file->close()); |
160 | |
161 | file = openfile(file_name: FILENAME, mode: "r" ); |
162 | ASSERT_FALSE(file == nullptr); |
163 | |
164 | constexpr size_t READ_SIZE = 5; |
165 | char data[READ_SIZE]; |
166 | data[READ_SIZE - 1] = '\0'; |
167 | ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); |
168 | ASSERT_STREQ(data, "1234" ); |
169 | ASSERT_EQ(file->seek(5, SEEK_CUR).value(), 0); |
170 | ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); |
171 | ASSERT_STREQ(data, "0987" ); |
172 | ASSERT_EQ(file->seek(-5, SEEK_CUR).value(), 0); |
173 | ASSERT_EQ(file->read(data, READ_SIZE - 1).value, READ_SIZE - 1); |
174 | ASSERT_STREQ(data, "9098" ); |
175 | |
176 | ASSERT_EQ(file->close(), 0); |
177 | } |
178 | |
179 | TEST(LlvmLibcPlatformFileTest, IncorrectOperation) { |
180 | constexpr char FILENAME[] = "testdata/incorrect_operation.test" ; |
181 | char data[1] = {123}; |
182 | |
183 | File *file = openfile(file_name: FILENAME, mode: "w" ); |
184 | ASSERT_FALSE(file == nullptr); |
185 | ASSERT_EQ(file->read(data, 1).value, size_t(0)); // Cannot read |
186 | ASSERT_FALSE(file->iseof()); |
187 | ASSERT_TRUE(file->error()); |
188 | ASSERT_EQ(file->close(), 0); |
189 | |
190 | file = openfile(file_name: FILENAME, mode: "r" ); |
191 | ASSERT_FALSE(file == nullptr); |
192 | ASSERT_EQ(file->write(data, 1).value, size_t(0)); // Cannot write |
193 | ASSERT_FALSE(file->iseof()); |
194 | ASSERT_TRUE(file->error()); |
195 | ASSERT_EQ(file->close(), 0); |
196 | |
197 | file = openfile(file_name: FILENAME, mode: "a" ); |
198 | ASSERT_FALSE(file == nullptr); |
199 | ASSERT_EQ(file->read(data, 1).value, size_t(0)); // Cannot read |
200 | ASSERT_FALSE(file->iseof()); |
201 | ASSERT_TRUE(file->error()); |
202 | ASSERT_EQ(file->close(), 0); |
203 | } |
204 | |