xref: /llvm-project/libc/test/src/__support/File/platform_file_test.cpp (revision c63112a9118277a20ae440f3f69189c0937e8f4d)
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