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