xref: /aosp_15_r20/external/llvm-libc/test/src/stdio/fileop_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker //===-- Unittests for file operations like fopen, flcose etc --------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker 
9*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/clearerr.h"
10*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fclose.h"
11*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/feof.h"
12*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/ferror.h"
13*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fflush.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fileno.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fopen.h"
16*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fputs.h"
17*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fread.h"
18*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fseek.h"
19*71db0c75SAndroid Build Coastguard Worker #include "src/stdio/fwrite.h"
20*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/ErrnoSetterMatcher.h"
21*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
22*71db0c75SAndroid Build Coastguard Worker 
23*71db0c75SAndroid Build Coastguard Worker #include "hdr/stdio_macros.h"
24*71db0c75SAndroid Build Coastguard Worker #include "src/errno/libc_errno.h"
25*71db0c75SAndroid Build Coastguard Worker 
26*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::EQ;
27*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::NE;
28*71db0c75SAndroid Build Coastguard Worker using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::returns;
29*71db0c75SAndroid Build Coastguard Worker 
TEST(LlvmLibcFILETest,SimpleFileOperations)30*71db0c75SAndroid Build Coastguard Worker TEST(LlvmLibcFILETest, SimpleFileOperations) {
31*71db0c75SAndroid Build Coastguard Worker   constexpr char FILENAME[] = "testdata/simple_operations.test";
32*71db0c75SAndroid Build Coastguard Worker   ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w");
33*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
34*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fileno(file), 3);
35*71db0c75SAndroid Build Coastguard Worker   constexpr char CONTENT[] = "1234567890987654321";
36*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(CONTENT) - 1,
37*71db0c75SAndroid Build Coastguard Worker             LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file));
38*71db0c75SAndroid Build Coastguard Worker 
39*71db0c75SAndroid Build Coastguard Worker   // This is not a readable file.
40*71db0c75SAndroid Build Coastguard Worker   char read_data[sizeof(CONTENT)];
41*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT), file),
42*71db0c75SAndroid Build Coastguard Worker               returns(EQ(size_t(0))).with_errno(NE(0)));
43*71db0c75SAndroid Build Coastguard Worker   ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0);
44*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
45*71db0c75SAndroid Build Coastguard Worker 
46*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::clearerr(file);
47*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
48*71db0c75SAndroid Build Coastguard Worker 
49*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
50*71db0c75SAndroid Build Coastguard Worker 
51*71db0c75SAndroid Build Coastguard Worker   file = LIBC_NAMESPACE::fopen(FILENAME, "r");
52*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
53*71db0c75SAndroid Build Coastguard Worker 
54*71db0c75SAndroid Build Coastguard Worker   constexpr size_t READ_SIZE = 5;
55*71db0c75SAndroid Build Coastguard Worker   char data[READ_SIZE];
56*71db0c75SAndroid Build Coastguard Worker   data[READ_SIZE - 1] = '\0';
57*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
58*71db0c75SAndroid Build Coastguard Worker   ASSERT_STREQ(data, "1234");
59*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fseek(file, 5, SEEK_CUR), 0);
60*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
61*71db0c75SAndroid Build Coastguard Worker   ASSERT_STREQ(data, "0987");
62*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fseek(file, -5, SEEK_CUR), 0);
63*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
64*71db0c75SAndroid Build Coastguard Worker   ASSERT_STREQ(data, "9098");
65*71db0c75SAndroid Build Coastguard Worker 
66*71db0c75SAndroid Build Coastguard Worker   // Reading another time should trigger eof.
67*71db0c75SAndroid Build Coastguard Worker   ASSERT_NE(sizeof(CONTENT),
68*71db0c75SAndroid Build Coastguard Worker             LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT), file));
69*71db0c75SAndroid Build Coastguard Worker   ASSERT_NE(LIBC_NAMESPACE::feof(file), 0);
70*71db0c75SAndroid Build Coastguard Worker 
71*71db0c75SAndroid Build Coastguard Worker   // Should be an error to write.
72*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT), file),
73*71db0c75SAndroid Build Coastguard Worker               returns(EQ(size_t(0))).with_errno(NE(0)));
74*71db0c75SAndroid Build Coastguard Worker   ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0);
75*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
76*71db0c75SAndroid Build Coastguard Worker 
77*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::clearerr(file);
78*71db0c75SAndroid Build Coastguard Worker 
79*71db0c75SAndroid Build Coastguard Worker   // Should be an error to puts.
80*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(LIBC_NAMESPACE::fputs(CONTENT, file),
81*71db0c75SAndroid Build Coastguard Worker               returns(EQ(EOF)).with_errno(NE(0)));
82*71db0c75SAndroid Build Coastguard Worker   ASSERT_NE(LIBC_NAMESPACE::ferror(file), 0);
83*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
84*71db0c75SAndroid Build Coastguard Worker 
85*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::clearerr(file);
86*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
87*71db0c75SAndroid Build Coastguard Worker 
88*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
89*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(LIBC_NAMESPACE::fwrite("nothing", 1, 1, file),
90*71db0c75SAndroid Build Coastguard Worker               returns(EQ(0)).with_errno(NE(0)));
91*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
92*71db0c75SAndroid Build Coastguard Worker 
93*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0);
94*71db0c75SAndroid Build Coastguard Worker 
95*71db0c75SAndroid Build Coastguard Worker   // Now try puts.
96*71db0c75SAndroid Build Coastguard Worker   file = LIBC_NAMESPACE::fopen(FILENAME, "w");
97*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
98*71db0c75SAndroid Build Coastguard Worker   // fputs returns a negative value on error (EOF) or any non-negative value on
99*71db0c75SAndroid Build Coastguard Worker   // success. This assert checks that the return value is non-negative.
100*71db0c75SAndroid Build Coastguard Worker   ASSERT_GE(LIBC_NAMESPACE::fputs(CONTENT, file), 0);
101*71db0c75SAndroid Build Coastguard Worker 
102*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::clearerr(file);
103*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::ferror(file), 0);
104*71db0c75SAndroid Build Coastguard Worker 
105*71db0c75SAndroid Build Coastguard Worker   // This is not a readable file.
106*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
107*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(LIBC_NAMESPACE::fread(data, 1, 1, file),
108*71db0c75SAndroid Build Coastguard Worker               returns(EQ(0)).with_errno(NE(0)));
109*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
110*71db0c75SAndroid Build Coastguard Worker 
111*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(0, LIBC_NAMESPACE::fclose(file));
112*71db0c75SAndroid Build Coastguard Worker 
113*71db0c75SAndroid Build Coastguard Worker   file = LIBC_NAMESPACE::fopen(FILENAME, "r");
114*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
115*71db0c75SAndroid Build Coastguard Worker 
116*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fread(read_data, 1, sizeof(CONTENT) - 1, file),
117*71db0c75SAndroid Build Coastguard Worker             sizeof(CONTENT) - 1);
118*71db0c75SAndroid Build Coastguard Worker   read_data[sizeof(CONTENT) - 1] = '\0';
119*71db0c75SAndroid Build Coastguard Worker   ASSERT_STREQ(read_data, CONTENT);
120*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0);
121*71db0c75SAndroid Build Coastguard Worker 
122*71db0c75SAndroid Build Coastguard Worker   // Check that the other functions correctly set libc_errno.
123*71db0c75SAndroid Build Coastguard Worker 
124*71db0c75SAndroid Build Coastguard Worker   // LIBC_NAMESPACE::libc_errno = 0;
125*71db0c75SAndroid Build Coastguard Worker   // ASSERT_NE(LIBC_NAMESPACE::fseek(file, 0, SEEK_SET), 0);
126*71db0c75SAndroid Build Coastguard Worker   // ASSERT_ERRNO_FAILURE();
127*71db0c75SAndroid Build Coastguard Worker 
128*71db0c75SAndroid Build Coastguard Worker   // LIBC_NAMESPACE::libc_errno = 0;
129*71db0c75SAndroid Build Coastguard Worker   // ASSERT_NE(LIBC_NAMESPACE::fclose(file), 0);
130*71db0c75SAndroid Build Coastguard Worker   // ASSERT_ERRNO_FAILURE();
131*71db0c75SAndroid Build Coastguard Worker 
132*71db0c75SAndroid Build Coastguard Worker   // LIBC_NAMESPACE::libc_errno = 0;
133*71db0c75SAndroid Build Coastguard Worker   // ASSERT_EQ(LIBC_NAMESPACE::fopen("INVALID FILE NAME", "r"),
134*71db0c75SAndroid Build Coastguard Worker   //           static_cast<FILE *>(nullptr));
135*71db0c75SAndroid Build Coastguard Worker   // ASSERT_ERRNO_FAILURE();
136*71db0c75SAndroid Build Coastguard Worker }
137*71db0c75SAndroid Build Coastguard Worker 
TEST(LlvmLibcFILETest,FFlush)138*71db0c75SAndroid Build Coastguard Worker TEST(LlvmLibcFILETest, FFlush) {
139*71db0c75SAndroid Build Coastguard Worker   constexpr char FILENAME[] = "testdata/fflush.test";
140*71db0c75SAndroid Build Coastguard Worker   ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w+");
141*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
142*71db0c75SAndroid Build Coastguard Worker   constexpr char CONTENT[] = "1234567890987654321";
143*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(sizeof(CONTENT),
144*71db0c75SAndroid Build Coastguard Worker             LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT), file));
145*71db0c75SAndroid Build Coastguard Worker 
146*71db0c75SAndroid Build Coastguard Worker   // Flushing at this point should write the data to disk. So, we should be
147*71db0c75SAndroid Build Coastguard Worker   // able to read it back.
148*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(0, LIBC_NAMESPACE::fflush(file));
149*71db0c75SAndroid Build Coastguard Worker 
150*71db0c75SAndroid Build Coastguard Worker   char data[sizeof(CONTENT)];
151*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fseek(file, 0, SEEK_SET), 0);
152*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fread(data, 1, sizeof(CONTENT), file),
153*71db0c75SAndroid Build Coastguard Worker             sizeof(CONTENT));
154*71db0c75SAndroid Build Coastguard Worker   ASSERT_STREQ(data, CONTENT);
155*71db0c75SAndroid Build Coastguard Worker 
156*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0);
157*71db0c75SAndroid Build Coastguard Worker }
158*71db0c75SAndroid Build Coastguard Worker 
TEST(LlvmLibcFILETest,FOpenFWriteSizeGreaterThanOne)159*71db0c75SAndroid Build Coastguard Worker TEST(LlvmLibcFILETest, FOpenFWriteSizeGreaterThanOne) {
160*71db0c75SAndroid Build Coastguard Worker   using MyStruct = struct {
161*71db0c75SAndroid Build Coastguard Worker     char c;
162*71db0c75SAndroid Build Coastguard Worker     unsigned long long i;
163*71db0c75SAndroid Build Coastguard Worker   };
164*71db0c75SAndroid Build Coastguard Worker   constexpr MyStruct WRITE_DATA[] = {{'a', 1}, {'b', 2}, {'c', 3}};
165*71db0c75SAndroid Build Coastguard Worker   constexpr size_t WRITE_NMEMB = sizeof(WRITE_DATA) / sizeof(MyStruct);
166*71db0c75SAndroid Build Coastguard Worker   constexpr char FILENAME[] = "testdata/fread_fwrite.test";
167*71db0c75SAndroid Build Coastguard Worker 
168*71db0c75SAndroid Build Coastguard Worker   LIBC_NAMESPACE::libc_errno = 0;
169*71db0c75SAndroid Build Coastguard Worker   FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w");
170*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
171*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(size_t(0), LIBC_NAMESPACE::fwrite(WRITE_DATA, 0, 1, file));
172*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(
173*71db0c75SAndroid Build Coastguard Worker       LIBC_NAMESPACE::fwrite(WRITE_DATA, sizeof(MyStruct), WRITE_NMEMB, file),
174*71db0c75SAndroid Build Coastguard Worker       returns(EQ(WRITE_NMEMB)).with_errno(EQ(0)));
175*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0);
176*71db0c75SAndroid Build Coastguard Worker 
177*71db0c75SAndroid Build Coastguard Worker   file = LIBC_NAMESPACE::fopen(FILENAME, "r");
178*71db0c75SAndroid Build Coastguard Worker   ASSERT_FALSE(file == nullptr);
179*71db0c75SAndroid Build Coastguard Worker   MyStruct read_data[WRITE_NMEMB];
180*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(size_t(0), LIBC_NAMESPACE::fread(read_data, 0, 1, file));
181*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(
182*71db0c75SAndroid Build Coastguard Worker       LIBC_NAMESPACE::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file),
183*71db0c75SAndroid Build Coastguard Worker       returns(EQ(WRITE_NMEMB)).with_errno(EQ(0)));
184*71db0c75SAndroid Build Coastguard Worker   // Trying to read more should fetch nothing.
185*71db0c75SAndroid Build Coastguard Worker   ASSERT_THAT(
186*71db0c75SAndroid Build Coastguard Worker       LIBC_NAMESPACE::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file),
187*71db0c75SAndroid Build Coastguard Worker       returns(EQ(0)).with_errno(EQ(0)));
188*71db0c75SAndroid Build Coastguard Worker   EXPECT_NE(LIBC_NAMESPACE::feof(file), 0);
189*71db0c75SAndroid Build Coastguard Worker   EXPECT_EQ(LIBC_NAMESPACE::ferror(file), 0);
190*71db0c75SAndroid Build Coastguard Worker   ASSERT_EQ(LIBC_NAMESPACE::fclose(file), 0);
191*71db0c75SAndroid Build Coastguard Worker   // Verify that the data which was read is correct.
192*71db0c75SAndroid Build Coastguard Worker   for (size_t i = 0; i < WRITE_NMEMB; ++i) {
193*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(read_data[i].c, WRITE_DATA[i].c);
194*71db0c75SAndroid Build Coastguard Worker     ASSERT_EQ(read_data[i].i, WRITE_DATA[i].i);
195*71db0c75SAndroid Build Coastguard Worker   }
196*71db0c75SAndroid Build Coastguard Worker }
197