xref: /aosp_15_r20/external/libbrillo/brillo/files/safe_fd_test.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright 2019 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include "brillo/files/safe_fd.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <fcntl.h>
8*1a96fba6SXin Li #include <sys/stat.h>
9*1a96fba6SXin Li 
10*1a96fba6SXin Li #include <base/files/file_util.h>
11*1a96fba6SXin Li #include <brillo/files/file_util_test.h>
12*1a96fba6SXin Li #include <brillo/syslog_logging.h>
13*1a96fba6SXin Li #include <gtest/gtest.h>
14*1a96fba6SXin Li 
15*1a96fba6SXin Li namespace brillo {
16*1a96fba6SXin Li 
17*1a96fba6SXin Li class SafeFDTest : public FileTest {};
18*1a96fba6SXin Li 
TEST_F(SafeFDTest,SafeFD)19*1a96fba6SXin Li TEST_F(SafeFDTest, SafeFD) {
20*1a96fba6SXin Li   EXPECT_FALSE(SafeFD().is_valid());
21*1a96fba6SXin Li }
22*1a96fba6SXin Li 
TEST_F(SafeFDTest,SafeFD_Move)23*1a96fba6SXin Li TEST_F(SafeFDTest, SafeFD_Move) {
24*1a96fba6SXin Li   SafeFD moved_root = std::move(root_);
25*1a96fba6SXin Li   EXPECT_FALSE(root_.is_valid());
26*1a96fba6SXin Li   ASSERT_TRUE(moved_root.is_valid());
27*1a96fba6SXin Li 
28*1a96fba6SXin Li   SafeFD moved_root2(std::move(moved_root));
29*1a96fba6SXin Li   EXPECT_FALSE(moved_root.is_valid());
30*1a96fba6SXin Li   ASSERT_TRUE(moved_root2.is_valid());
31*1a96fba6SXin Li }
32*1a96fba6SXin Li 
TEST_F(SafeFDTest,Root)33*1a96fba6SXin Li TEST_F(SafeFDTest, Root) {
34*1a96fba6SXin Li   SafeFD::SafeFDResult result = SafeFD::Root();
35*1a96fba6SXin Li   EXPECT_TRUE(result.first.is_valid());
36*1a96fba6SXin Li   EXPECT_EQ(result.second, SafeFD::Error::kNoError);
37*1a96fba6SXin Li }
38*1a96fba6SXin Li 
TEST_F(SafeFDTest,reset)39*1a96fba6SXin Li TEST_F(SafeFDTest, reset) {
40*1a96fba6SXin Li   root_.reset();
41*1a96fba6SXin Li   EXPECT_FALSE(root_.is_valid());
42*1a96fba6SXin Li }
43*1a96fba6SXin Li 
TEST_F(SafeFDTest,UnsafeReset)44*1a96fba6SXin Li TEST_F(SafeFDTest, UnsafeReset) {
45*1a96fba6SXin Li   int fd =
46*1a96fba6SXin Li       HANDLE_EINTR(open(temp_dir_path_.data(),
47*1a96fba6SXin Li                         O_NONBLOCK | O_DIRECTORY | O_RDONLY | O_CLOEXEC, 0777));
48*1a96fba6SXin Li   ASSERT_GE(fd, 0);
49*1a96fba6SXin Li 
50*1a96fba6SXin Li   {
51*1a96fba6SXin Li     SafeFD safe_fd;
52*1a96fba6SXin Li     safe_fd.UnsafeReset(fd);
53*1a96fba6SXin Li     EXPECT_EQ(safe_fd.get(), fd);
54*1a96fba6SXin Li   }
55*1a96fba6SXin Li 
56*1a96fba6SXin Li   // Verify the file descriptor is closed.
57*1a96fba6SXin Li   int result = fcntl(fd, F_GETFD);
58*1a96fba6SXin Li   int error = errno;
59*1a96fba6SXin Li   EXPECT_EQ(result, -1);
60*1a96fba6SXin Li   EXPECT_EQ(error, EBADF);
61*1a96fba6SXin Li }
62*1a96fba6SXin Li 
TEST_F(SafeFDTest,Write_Success)63*1a96fba6SXin Li TEST_F(SafeFDTest, Write_Success) {
64*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
65*1a96fba6SXin Li   {
66*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
67*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
68*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
69*1a96fba6SXin Li 
70*1a96fba6SXin Li     EXPECT_EQ(file.first.Write(random_data.data(), random_data.size()),
71*1a96fba6SXin Li               SafeFD::Error::kNoError);
72*1a96fba6SXin Li   }
73*1a96fba6SXin Li 
74*1a96fba6SXin Li   ExpectFileContains(random_data);
75*1a96fba6SXin Li   ExpectPermissions(file_path_, SafeFD::kDefaultFilePermissions);
76*1a96fba6SXin Li }
77*1a96fba6SXin Li 
TEST_F(SafeFDTest,Write_NotInitialized)78*1a96fba6SXin Li TEST_F(SafeFDTest, Write_NotInitialized) {
79*1a96fba6SXin Li   SafeFD invalid;
80*1a96fba6SXin Li   ASSERT_FALSE(invalid.is_valid());
81*1a96fba6SXin Li 
82*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
83*1a96fba6SXin Li   EXPECT_EQ(invalid.Write(random_data.data(), random_data.size()),
84*1a96fba6SXin Li             SafeFD::Error::kNotInitialized);
85*1a96fba6SXin Li }
86*1a96fba6SXin Li 
TEST_F(SafeFDTest,Write_VerifyTruncate)87*1a96fba6SXin Li TEST_F(SafeFDTest, Write_VerifyTruncate) {
88*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
89*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(random_data));
90*1a96fba6SXin Li 
91*1a96fba6SXin Li   {
92*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
93*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
94*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
95*1a96fba6SXin Li 
96*1a96fba6SXin Li     EXPECT_EQ(file.first.Write("", 0), SafeFD::Error::kNoError);
97*1a96fba6SXin Li   }
98*1a96fba6SXin Li 
99*1a96fba6SXin Li   ExpectFileContains("");
100*1a96fba6SXin Li }
101*1a96fba6SXin Li 
TEST_F(SafeFDTest,Write_Failure)102*1a96fba6SXin Li TEST_F(SafeFDTest, Write_Failure) {
103*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
104*1a96fba6SXin Li   EXPECT_EQ(root_.Write("", 1), SafeFD::Error::kIOError);
105*1a96fba6SXin Li }
106*1a96fba6SXin Li 
TEST_F(SafeFDTest,ReadContents_Success)107*1a96fba6SXin Li TEST_F(SafeFDTest, ReadContents_Success) {
108*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
109*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(random_data));
110*1a96fba6SXin Li 
111*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
112*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kNoError);
113*1a96fba6SXin Li   ASSERT_TRUE(file.first.is_valid());
114*1a96fba6SXin Li 
115*1a96fba6SXin Li   auto result = file.first.ReadContents();
116*1a96fba6SXin Li   EXPECT_EQ(result.second, SafeFD::Error::kNoError);
117*1a96fba6SXin Li   ASSERT_EQ(random_data.size(), result.first.size());
118*1a96fba6SXin Li   EXPECT_EQ(memcmp(random_data.data(), result.first.data(), random_data.size()),
119*1a96fba6SXin Li             0);
120*1a96fba6SXin Li }
121*1a96fba6SXin Li 
TEST_F(SafeFDTest,ReadContents_ExceededMaximum)122*1a96fba6SXin Li TEST_F(SafeFDTest, ReadContents_ExceededMaximum) {
123*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
124*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(random_data));
125*1a96fba6SXin Li 
126*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
127*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kNoError);
128*1a96fba6SXin Li   ASSERT_TRUE(file.first.is_valid());
129*1a96fba6SXin Li 
130*1a96fba6SXin Li   ASSERT_LT(1, random_data.size());
131*1a96fba6SXin Li   auto result = file.first.ReadContents(1);
132*1a96fba6SXin Li   EXPECT_EQ(result.second, SafeFD::Error::kExceededMaximum);
133*1a96fba6SXin Li }
134*1a96fba6SXin Li 
TEST_F(SafeFDTest,ReadContents_NotInitialized)135*1a96fba6SXin Li TEST_F(SafeFDTest, ReadContents_NotInitialized) {
136*1a96fba6SXin Li   SafeFD invalid;
137*1a96fba6SXin Li   ASSERT_FALSE(invalid.is_valid());
138*1a96fba6SXin Li 
139*1a96fba6SXin Li   auto result = invalid.ReadContents();
140*1a96fba6SXin Li   EXPECT_EQ(result.second, SafeFD::Error::kNotInitialized);
141*1a96fba6SXin Li }
142*1a96fba6SXin Li 
TEST_F(SafeFDTest,Read_Success)143*1a96fba6SXin Li TEST_F(SafeFDTest, Read_Success) {
144*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
145*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(random_data));
146*1a96fba6SXin Li 
147*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
148*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kNoError);
149*1a96fba6SXin Li   ASSERT_TRUE(file.first.is_valid());
150*1a96fba6SXin Li 
151*1a96fba6SXin Li   std::vector<char> buffer(random_data.size(), '\0');
152*1a96fba6SXin Li   ASSERT_EQ(file.first.Read(buffer.data(), buffer.size()),
153*1a96fba6SXin Li             SafeFD::Error::kNoError);
154*1a96fba6SXin Li   EXPECT_EQ(memcmp(random_data.data(), buffer.data(), random_data.size()), 0);
155*1a96fba6SXin Li }
156*1a96fba6SXin Li 
TEST_F(SafeFDTest,Read_NotInitialized)157*1a96fba6SXin Li TEST_F(SafeFDTest, Read_NotInitialized) {
158*1a96fba6SXin Li   SafeFD invalid;
159*1a96fba6SXin Li   ASSERT_FALSE(invalid.is_valid());
160*1a96fba6SXin Li 
161*1a96fba6SXin Li   char to_read;
162*1a96fba6SXin Li   EXPECT_EQ(invalid.Read(&to_read, 1), SafeFD::Error::kNotInitialized);
163*1a96fba6SXin Li }
164*1a96fba6SXin Li 
TEST_F(SafeFDTest,Read_IOError)165*1a96fba6SXin Li TEST_F(SafeFDTest, Read_IOError) {
166*1a96fba6SXin Li   std::string random_data = GetRandomSuffix();
167*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(random_data));
168*1a96fba6SXin Li 
169*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
170*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kNoError);
171*1a96fba6SXin Li   ASSERT_TRUE(file.first.is_valid());
172*1a96fba6SXin Li 
173*1a96fba6SXin Li   std::vector<char> buffer(random_data.size() * 2, '\0');
174*1a96fba6SXin Li   ASSERT_EQ(file.first.Read(buffer.data(), buffer.size()),
175*1a96fba6SXin Li             SafeFD::Error::kIOError);
176*1a96fba6SXin Li }
177*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_Success)178*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_Success) {
179*1a96fba6SXin Li   std::string data = GetRandomSuffix();
180*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(data));
181*1a96fba6SXin Li   {
182*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
183*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
184*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
185*1a96fba6SXin Li   }
186*1a96fba6SXin Li   ExpectFileContains(data);
187*1a96fba6SXin Li }
188*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_NotInitialized)189*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_NotInitialized) {
190*1a96fba6SXin Li   SafeFD::SafeFDResult file = SafeFD().OpenExistingFile(file_path_);
191*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kNotInitialized);
192*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
193*1a96fba6SXin Li }
194*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_DoesNotExist)195*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_DoesNotExist) {
196*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
197*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kDoesNotExist);
198*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
199*1a96fba6SXin Li }
200*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_IOError)201*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_IOError) {
202*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
203*1a96fba6SXin Li   EXPECT_EQ(chmod(file_path_.value().c_str(), 0000), 0) << strerror(errno);
204*1a96fba6SXin Li 
205*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(file_path_);
206*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kIOError);
207*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
208*1a96fba6SXin Li }
209*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_SymlinkDetected)210*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_SymlinkDetected) {
211*1a96fba6SXin Li   ASSERT_TRUE(SetupSymlinks());
212*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
213*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.OpenExistingFile(symlink_file_path_);
214*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kSymlinkDetected);
215*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
216*1a96fba6SXin Li }
217*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingFile_WrongType)218*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingFile_WrongType) {
219*1a96fba6SXin Li   ASSERT_TRUE(SetupSymlinks());
220*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
221*1a96fba6SXin Li   SafeFD::SafeFDResult file =
222*1a96fba6SXin Li       root_.OpenExistingFile(symlink_dir_path_.Append(kFileName));
223*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kWrongType);
224*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
225*1a96fba6SXin Li }
226*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingDir_Success)227*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingDir_Success) {
228*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
229*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kNoError);
230*1a96fba6SXin Li   ASSERT_TRUE(dir.first.is_valid());
231*1a96fba6SXin Li }
232*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingDir_NotInitialized)233*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingDir_NotInitialized) {
234*1a96fba6SXin Li   SafeFD::SafeFDResult dir = SafeFD().OpenExistingDir(temp_dir_.GetPath());
235*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kNotInitialized);
236*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
237*1a96fba6SXin Li }
238*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingDir_DoesNotExist)239*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingDir_DoesNotExist) {
240*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(sub_dir_path_);
241*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kDoesNotExist);
242*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
243*1a96fba6SXin Li }
244*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingDir_IOError)245*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingDir_IOError) {
246*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
247*1a96fba6SXin Li   ASSERT_EQ(chmod(sub_dir_path_.value().c_str(), 0000), 0) << strerror(errno);
248*1a96fba6SXin Li 
249*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(sub_dir_path_);
250*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kIOError);
251*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
252*1a96fba6SXin Li }
253*1a96fba6SXin Li 
TEST_F(SafeFDTest,OpenExistingDir_WrongType)254*1a96fba6SXin Li TEST_F(SafeFDTest, OpenExistingDir_WrongType) {
255*1a96fba6SXin Li   ASSERT_TRUE(SetupSymlinks());
256*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(symlink_dir_path_);
257*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kWrongType);
258*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
259*1a96fba6SXin Li }
260*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_DoesNotExistSuccess)261*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_DoesNotExistSuccess) {
262*1a96fba6SXin Li   {
263*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
264*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
265*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
266*1a96fba6SXin Li   }
267*1a96fba6SXin Li 
268*1a96fba6SXin Li   ExpectPermissions(file_path_, SafeFD::kDefaultFilePermissions);
269*1a96fba6SXin Li }
270*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_LeadingSelfDirSuccess)271*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_LeadingSelfDirSuccess) {
272*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
273*1a96fba6SXin Li 
274*1a96fba6SXin Li   SafeFD::Error err;
275*1a96fba6SXin Li   SafeFD dir;
276*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(sub_dir_path_);
277*1a96fba6SXin Li   ASSERT_EQ(err, SafeFD::Error::kNoError);
278*1a96fba6SXin Li 
279*1a96fba6SXin Li   {
280*1a96fba6SXin Li     SafeFD file;
281*1a96fba6SXin Li     std::tie(file, err) = dir.MakeFile(file_path_.BaseName());
282*1a96fba6SXin Li     EXPECT_EQ(err, SafeFD::Error::kNoError);
283*1a96fba6SXin Li     ASSERT_TRUE(file.is_valid());
284*1a96fba6SXin Li   }
285*1a96fba6SXin Li 
286*1a96fba6SXin Li   ExpectPermissions(file_path_, SafeFD::kDefaultFilePermissions);
287*1a96fba6SXin Li }
288*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_ExistsSuccess)289*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_ExistsSuccess) {
290*1a96fba6SXin Li   std::string data = GetRandomSuffix();
291*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(data));
292*1a96fba6SXin Li   {
293*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
294*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
295*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
296*1a96fba6SXin Li   }
297*1a96fba6SXin Li   ExpectPermissions(file_path_, SafeFD::kDefaultFilePermissions);
298*1a96fba6SXin Li   ExpectFileContains(data);
299*1a96fba6SXin Li }
300*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_IOError)301*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_IOError) {
302*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
303*1a96fba6SXin Li   ASSERT_EQ(mkfifo(file_path_.value().c_str(), 0), 0);
304*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
305*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kIOError);
306*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
307*1a96fba6SXin Li }
308*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_SymlinkDetected)309*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_SymlinkDetected) {
310*1a96fba6SXin Li   ASSERT_TRUE(SetupSymlinks());
311*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.MakeFile(symlink_file_path_);
312*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kSymlinkDetected);
313*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
314*1a96fba6SXin Li }
315*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_WrongType)316*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_WrongType) {
317*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
318*1a96fba6SXin Li   SafeFD::SafeFDResult file = root_.MakeFile(sub_dir_path_);
319*1a96fba6SXin Li   EXPECT_EQ(file.second, SafeFD::Error::kWrongType);
320*1a96fba6SXin Li   ASSERT_FALSE(file.first.is_valid());
321*1a96fba6SXin Li }
322*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_WrongGID)323*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_WrongGID) {
324*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
325*1a96fba6SXin Li   ASSERT_EQ(chown(file_path_.value().c_str(), getuid(), 0), 0)
326*1a96fba6SXin Li       << strerror(errno);
327*1a96fba6SXin Li   {
328*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
329*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kWrongGID);
330*1a96fba6SXin Li     ASSERT_FALSE(file.first.is_valid());
331*1a96fba6SXin Li   }
332*1a96fba6SXin Li }
333*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_WrongPermissions)334*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_WrongPermissions) {
335*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
336*1a96fba6SXin Li   ASSERT_EQ(chmod(file_path_.value().c_str(), 0777), 0) << strerror(errno);
337*1a96fba6SXin Li   {
338*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
339*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kWrongPermissions);
340*1a96fba6SXin Li     ASSERT_FALSE(file.first.is_valid());
341*1a96fba6SXin Li   }
342*1a96fba6SXin Li   ASSERT_EQ(chmod(file_path_.value().c_str(), SafeFD::kDefaultFilePermissions),
343*1a96fba6SXin Li             0)
344*1a96fba6SXin Li       << strerror(errno);
345*1a96fba6SXin Li 
346*1a96fba6SXin Li   EXPECT_EQ(chmod(sub_dir_path_.value().c_str(), 0777), 0) << strerror(errno);
347*1a96fba6SXin Li   {
348*1a96fba6SXin Li     SafeFD::SafeFDResult file = root_.MakeFile(file_path_);
349*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kWrongPermissions);
350*1a96fba6SXin Li     ASSERT_FALSE(file.first.is_valid());
351*1a96fba6SXin Li   }
352*1a96fba6SXin Li }
353*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeDir_DoesNotExistSuccess)354*1a96fba6SXin Li TEST_F(SafeFDTest, MakeDir_DoesNotExistSuccess) {
355*1a96fba6SXin Li   {
356*1a96fba6SXin Li     SafeFD::SafeFDResult dir = root_.MakeDir(sub_dir_path_);
357*1a96fba6SXin Li     EXPECT_EQ(dir.second, SafeFD::Error::kNoError);
358*1a96fba6SXin Li     ASSERT_TRUE(dir.first.is_valid());
359*1a96fba6SXin Li   }
360*1a96fba6SXin Li 
361*1a96fba6SXin Li   ExpectPermissions(sub_dir_path_, SafeFD::kDefaultDirPermissions);
362*1a96fba6SXin Li }
363*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeFile_SingleComponentSuccess)364*1a96fba6SXin Li TEST_F(SafeFDTest, MakeFile_SingleComponentSuccess) {
365*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
366*1a96fba6SXin Li 
367*1a96fba6SXin Li   SafeFD::Error err;
368*1a96fba6SXin Li   SafeFD dir;
369*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
370*1a96fba6SXin Li   ASSERT_EQ(err, SafeFD::Error::kNoError);
371*1a96fba6SXin Li 
372*1a96fba6SXin Li   {
373*1a96fba6SXin Li     SafeFD subdir;
374*1a96fba6SXin Li     std::tie(subdir, err) = dir.MakeDir(base::FilePath(kSubdirName));
375*1a96fba6SXin Li     EXPECT_EQ(err, SafeFD::Error::kNoError);
376*1a96fba6SXin Li     ASSERT_TRUE(subdir.is_valid());
377*1a96fba6SXin Li   }
378*1a96fba6SXin Li 
379*1a96fba6SXin Li   ExpectPermissions(sub_dir_path_, SafeFD::kDefaultDirPermissions);
380*1a96fba6SXin Li }
381*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeDir_ExistsSuccess)382*1a96fba6SXin Li TEST_F(SafeFDTest, MakeDir_ExistsSuccess) {
383*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
384*1a96fba6SXin Li   {
385*1a96fba6SXin Li     SafeFD::SafeFDResult dir = root_.MakeDir(sub_dir_path_);
386*1a96fba6SXin Li     EXPECT_EQ(dir.second, SafeFD::Error::kNoError);
387*1a96fba6SXin Li     ASSERT_TRUE(dir.first.is_valid());
388*1a96fba6SXin Li   }
389*1a96fba6SXin Li 
390*1a96fba6SXin Li   ExpectPermissions(sub_dir_path_, SafeFD::kDefaultDirPermissions);
391*1a96fba6SXin Li }
392*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeDir_WrongType)393*1a96fba6SXin Li TEST_F(SafeFDTest, MakeDir_WrongType) {
394*1a96fba6SXin Li   ASSERT_TRUE(SetupSymlinks());
395*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.MakeDir(symlink_dir_path_);
396*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kWrongType);
397*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
398*1a96fba6SXin Li }
399*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeDir_WrongGID)400*1a96fba6SXin Li TEST_F(SafeFDTest, MakeDir_WrongGID) {
401*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
402*1a96fba6SXin Li   ASSERT_EQ(chown(sub_dir_path_.value().c_str(), getuid(), 0), 0)
403*1a96fba6SXin Li       << strerror(errno);
404*1a96fba6SXin Li   {
405*1a96fba6SXin Li     SafeFD::SafeFDResult dir = root_.MakeDir(sub_dir_path_);
406*1a96fba6SXin Li     EXPECT_EQ(dir.second, SafeFD::Error::kWrongGID);
407*1a96fba6SXin Li     ASSERT_FALSE(dir.first.is_valid());
408*1a96fba6SXin Li   }
409*1a96fba6SXin Li }
410*1a96fba6SXin Li 
TEST_F(SafeFDTest,MakeDir_WrongPermissions)411*1a96fba6SXin Li TEST_F(SafeFDTest, MakeDir_WrongPermissions) {
412*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
413*1a96fba6SXin Li   ASSERT_EQ(chmod(sub_dir_path_.value().c_str(), 0777), 0) << strerror(errno);
414*1a96fba6SXin Li 
415*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.MakeDir(sub_dir_path_);
416*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kWrongPermissions);
417*1a96fba6SXin Li   ASSERT_FALSE(dir.first.is_valid());
418*1a96fba6SXin Li }
419*1a96fba6SXin Li 
TEST_F(SafeFDTest,Link_Success)420*1a96fba6SXin Li TEST_F(SafeFDTest, Link_Success) {
421*1a96fba6SXin Li   std::string data = GetRandomSuffix();
422*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(data));
423*1a96fba6SXin Li 
424*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
425*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
426*1a96fba6SXin Li 
427*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
428*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
429*1a96fba6SXin Li 
430*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, kFileName, kFileName),
431*1a96fba6SXin Li             SafeFD::Error::kNoError);
432*1a96fba6SXin Li 
433*1a96fba6SXin Li   SafeFD::SafeFDResult new_file = dir.first.OpenExistingFile(
434*1a96fba6SXin Li       base::FilePath(kFileName), O_RDONLY | O_CLOEXEC);
435*1a96fba6SXin Li   EXPECT_EQ(new_file.second, SafeFD::Error::kNoError);
436*1a96fba6SXin Li   std::pair<std::vector<char>, SafeFD::Error> contents =
437*1a96fba6SXin Li       new_file.first.ReadContents();
438*1a96fba6SXin Li   EXPECT_EQ(contents.second, SafeFD::Error::kNoError);
439*1a96fba6SXin Li   EXPECT_EQ(data.size(), contents.first.size());
440*1a96fba6SXin Li   EXPECT_EQ(memcmp(data.data(), contents.first.data(), data.size()), 0);
441*1a96fba6SXin Li }
442*1a96fba6SXin Li 
TEST_F(SafeFDTest,Link_NotInitialized)443*1a96fba6SXin Li TEST_F(SafeFDTest, Link_NotInitialized) {
444*1a96fba6SXin Li   std::string data = GetRandomSuffix();
445*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(data));
446*1a96fba6SXin Li 
447*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
448*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
449*1a96fba6SXin Li 
450*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
451*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
452*1a96fba6SXin Li 
453*1a96fba6SXin Li   EXPECT_EQ(SafeFD().Link(subdir.first, kFileName, kFileName),
454*1a96fba6SXin Li             SafeFD::Error::kNotInitialized);
455*1a96fba6SXin Li 
456*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(SafeFD(), kFileName, kFileName),
457*1a96fba6SXin Li             SafeFD::Error::kNotInitialized);
458*1a96fba6SXin Li }
459*1a96fba6SXin Li 
TEST_F(SafeFDTest,Link_BadArgument)460*1a96fba6SXin Li TEST_F(SafeFDTest, Link_BadArgument) {
461*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
462*1a96fba6SXin Li 
463*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
464*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
465*1a96fba6SXin Li 
466*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
467*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
468*1a96fba6SXin Li 
469*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, "a/a", kFileName),
470*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
471*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, ".", kFileName),
472*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
473*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, "..", kFileName),
474*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
475*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, kFileName, "a/a"),
476*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
477*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, kFileName, "."),
478*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
479*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, kFileName, ".."),
480*1a96fba6SXin Li             SafeFD::Error::kBadArgument);
481*1a96fba6SXin Li }
482*1a96fba6SXin Li 
TEST_F(SafeFDTest,Link_IOError)483*1a96fba6SXin Li TEST_F(SafeFDTest, Link_IOError) {
484*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
485*1a96fba6SXin Li 
486*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
487*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
488*1a96fba6SXin Li 
489*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
490*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
491*1a96fba6SXin Li 
492*1a96fba6SXin Li   EXPECT_EQ(dir.first.Link(subdir.first, kFileName, kFileName),
493*1a96fba6SXin Li             SafeFD::Error::kIOError);
494*1a96fba6SXin Li }
495*1a96fba6SXin Li 
TEST_F(SafeFDTest,Unlink_Success)496*1a96fba6SXin Li TEST_F(SafeFDTest, Unlink_Success) {
497*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
498*1a96fba6SXin Li 
499*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
500*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
501*1a96fba6SXin Li 
502*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Unlink(kFileName), SafeFD::Error::kNoError);
503*1a96fba6SXin Li   EXPECT_FALSE(base::PathExists(file_path_));
504*1a96fba6SXin Li }
505*1a96fba6SXin Li 
TEST_F(SafeFDTest,Unlink_NotInitialized)506*1a96fba6SXin Li TEST_F(SafeFDTest, Unlink_NotInitialized) {
507*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
508*1a96fba6SXin Li 
509*1a96fba6SXin Li   EXPECT_EQ(SafeFD().Unlink(kFileName), SafeFD::Error::kNotInitialized);
510*1a96fba6SXin Li }
511*1a96fba6SXin Li 
TEST_F(SafeFDTest,Unlink_BadArgument)512*1a96fba6SXin Li TEST_F(SafeFDTest, Unlink_BadArgument) {
513*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
514*1a96fba6SXin Li 
515*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
516*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
517*1a96fba6SXin Li 
518*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Unlink("a/a"), SafeFD::Error::kBadArgument);
519*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Unlink("."), SafeFD::Error::kBadArgument);
520*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Unlink(".."), SafeFD::Error::kBadArgument);
521*1a96fba6SXin Li }
522*1a96fba6SXin Li 
TEST_F(SafeFDTest,Unlink_IOError_Nonexistent)523*1a96fba6SXin Li TEST_F(SafeFDTest, Unlink_IOError_Nonexistent) {
524*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
525*1a96fba6SXin Li 
526*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
527*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
528*1a96fba6SXin Li 
529*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Unlink(kFileName), SafeFD::Error::kIOError);
530*1a96fba6SXin Li }
531*1a96fba6SXin Li 
TEST_F(SafeFDTest,Unlink_IOError_IsADir)532*1a96fba6SXin Li TEST_F(SafeFDTest, Unlink_IOError_IsADir) {
533*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
534*1a96fba6SXin Li 
535*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
536*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
537*1a96fba6SXin Li 
538*1a96fba6SXin Li   EXPECT_EQ(dir.first.Unlink(kSubdirName), SafeFD::Error::kIOError);
539*1a96fba6SXin Li }
540*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_Recursive_Success)541*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_Recursive_Success) {
542*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
543*1a96fba6SXin Li 
544*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
545*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
546*1a96fba6SXin Li 
547*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir(kSubdirName, true /*recursive*/),
548*1a96fba6SXin Li             SafeFD::Error::kNoError);
549*1a96fba6SXin Li   EXPECT_FALSE(base::PathExists(file_path_));
550*1a96fba6SXin Li   EXPECT_FALSE(base::PathExists(sub_dir_path_));
551*1a96fba6SXin Li }
552*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_Recursive_SuccessMaxRecursion)553*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_Recursive_SuccessMaxRecursion) {
554*1a96fba6SXin Li   SafeFD::Error err;
555*1a96fba6SXin Li   SafeFD dir;
556*1a96fba6SXin Li 
557*1a96fba6SXin Li   // Create directory with the maximum depth.
558*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
559*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
560*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
561*1a96fba6SXin Li   for (size_t x = 0; x < SafeFD::kDefaultMaxPathDepth; ++x) {
562*1a96fba6SXin Li     std::tie(dir, err) = dir.MakeDir(base::FilePath(kSubdirName));
563*1a96fba6SXin Li     EXPECT_EQ(err, SafeFD::Error::kNoError);
564*1a96fba6SXin Li     ASSERT_TRUE(dir.is_valid());
565*1a96fba6SXin Li   }
566*1a96fba6SXin Li 
567*1a96fba6SXin Li   // Check if recursive Rmdir succeeds (i.e. there isn't a stack overflow).
568*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
569*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
570*1a96fba6SXin Li 
571*1a96fba6SXin Li   EXPECT_EQ(dir.Rmdir(kSubdirName, true /*recursive*/),
572*1a96fba6SXin Li             SafeFD::Error::kNoError);
573*1a96fba6SXin Li   EXPECT_FALSE(base::PathExists(file_path_));
574*1a96fba6SXin Li   EXPECT_FALSE(base::PathExists(sub_dir_path_));
575*1a96fba6SXin Li }
576*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_NotInitialized)577*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_NotInitialized) {
578*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
579*1a96fba6SXin Li 
580*1a96fba6SXin Li   EXPECT_EQ(SafeFD().Rmdir(kSubdirName, true /*recursive*/),
581*1a96fba6SXin Li             SafeFD::Error::kNotInitialized);
582*1a96fba6SXin Li }
583*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_BadArgument)584*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_BadArgument) {
585*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
586*1a96fba6SXin Li 
587*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
588*1a96fba6SXin Li   EXPECT_EQ(dir.second, SafeFD::Error::kNoError);
589*1a96fba6SXin Li 
590*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir("a/a"), SafeFD::Error::kBadArgument);
591*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir("."), SafeFD::Error::kBadArgument);
592*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir(".."), SafeFD::Error::kBadArgument);
593*1a96fba6SXin Li }
594*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_ExceededMaximum)595*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_ExceededMaximum) {
596*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
597*1a96fba6SXin Li   ASSERT_TRUE(base::CreateDirectory(sub_dir_path_.Append(kSubdirName)));
598*1a96fba6SXin Li 
599*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
600*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
601*1a96fba6SXin Li 
602*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir(kSubdirName, true /*recursive*/, 1),
603*1a96fba6SXin Li             SafeFD::Error::kExceededMaximum);
604*1a96fba6SXin Li }
605*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_IOError)606*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_IOError) {
607*1a96fba6SXin Li   SafeFD::SafeFDResult dir = root_.OpenExistingDir(temp_dir_.GetPath());
608*1a96fba6SXin Li   ASSERT_EQ(dir.second, SafeFD::Error::kNoError);
609*1a96fba6SXin Li 
610*1a96fba6SXin Li   // Dir doesn't exist.
611*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir(kSubdirName), SafeFD::Error::kIOError);
612*1a96fba6SXin Li 
613*1a96fba6SXin Li   // Dir not empty.
614*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
615*1a96fba6SXin Li   EXPECT_EQ(dir.first.Rmdir(kSubdirName), SafeFD::Error::kIOError);
616*1a96fba6SXin Li }
617*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_WrongType)618*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_WrongType) {
619*1a96fba6SXin Li   ASSERT_TRUE(WriteFile(""));
620*1a96fba6SXin Li 
621*1a96fba6SXin Li   SafeFD::SafeFDResult subdir = root_.OpenExistingDir(sub_dir_path_);
622*1a96fba6SXin Li   ASSERT_EQ(subdir.second, SafeFD::Error::kNoError);
623*1a96fba6SXin Li 
624*1a96fba6SXin Li   EXPECT_EQ(subdir.first.Rmdir(kFileName), SafeFD::Error::kWrongType);
625*1a96fba6SXin Li }
626*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_Recursive_KeepGoing)627*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_Recursive_KeepGoing) {
628*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
629*1a96fba6SXin Li 
630*1a96fba6SXin Li   ASSERT_TRUE(base::CreateDirectory(sub_dir_path_.Append(kSubdirName)));
631*1a96fba6SXin Li 
632*1a96fba6SXin Li   // Give us something to iterate over.
633*1a96fba6SXin Li   constexpr int kNumSentinel = 25;
634*1a96fba6SXin Li   for (int i = 0; i < kNumSentinel; i++) {
635*1a96fba6SXin Li     SafeFD::SafeFDResult file =
636*1a96fba6SXin Li         root_.MakeFile(sub_dir_path_.Append(GetRandomSuffix()));
637*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
638*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
639*1a96fba6SXin Li   }
640*1a96fba6SXin Li 
641*1a96fba6SXin Li   // Recursively delete with a max level that is too small. Capture errno.
642*1a96fba6SXin Li   SafeFD::Error result = root_.Rmdir(kSubdirName, true /*recursive*/,
643*1a96fba6SXin Li                                      1 /*max_depth*/, true /*keep_going*/);
644*1a96fba6SXin Li   int rmdir_errno = errno;
645*1a96fba6SXin Li 
646*1a96fba6SXin Li   EXPECT_EQ(result, SafeFD::Error::kExceededMaximum);
647*1a96fba6SXin Li 
648*1a96fba6SXin Li   // If we keep going, the last operation will be the post-order unlink of
649*1a96fba6SXin Li   // the top-level directory. This has to fail with ENOTEMPTY since we did
650*1a96fba6SXin Li   // not delete the too-deep sub-directories. This particular behavior
651*1a96fba6SXin Li   // should not be part of the API contract and this can be relaxed if the
652*1a96fba6SXin Li   // implementation is changed.
653*1a96fba6SXin Li   EXPECT_EQ(rmdir_errno, ENOTEMPTY);
654*1a96fba6SXin Li 
655*1a96fba6SXin Li   // The deep directory must still exist.
656*1a96fba6SXin Li   ASSERT_TRUE(
657*1a96fba6SXin Li       base::DeleteFile(sub_dir_path_.Append(kSubdirName), false /*recursive*/));
658*1a96fba6SXin Li 
659*1a96fba6SXin Li   // We cannot control the iteration order so even if we incorrectly
660*1a96fba6SXin Li   // stopped early the directory might still be empty if the deep
661*1a96fba6SXin Li   // directories were last in the iteration order. But a non-empty
662*1a96fba6SXin Li   // directory is always incorrect.
663*1a96fba6SXin Li   ASSERT_TRUE(base::IsDirectoryEmpty(sub_dir_path_));
664*1a96fba6SXin Li }
665*1a96fba6SXin Li 
TEST_F(SafeFDTest,Rmdir_Recursive_StopOnError)666*1a96fba6SXin Li TEST_F(SafeFDTest, Rmdir_Recursive_StopOnError) {
667*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
668*1a96fba6SXin Li 
669*1a96fba6SXin Li   ASSERT_TRUE(base::CreateDirectory(sub_dir_path_.Append(kSubdirName)));
670*1a96fba6SXin Li 
671*1a96fba6SXin Li   // Give us something to iterate over.
672*1a96fba6SXin Li   constexpr int kNumSentinel = 25;
673*1a96fba6SXin Li   for (int i = 0; i < kNumSentinel; i++) {
674*1a96fba6SXin Li     SafeFD::SafeFDResult file =
675*1a96fba6SXin Li         root_.MakeFile(sub_dir_path_.Append(GetRandomSuffix()));
676*1a96fba6SXin Li     EXPECT_EQ(file.second, SafeFD::Error::kNoError);
677*1a96fba6SXin Li     ASSERT_TRUE(file.first.is_valid());
678*1a96fba6SXin Li   }
679*1a96fba6SXin Li 
680*1a96fba6SXin Li   // Recursively delete with a max level that is too small. Capture errno.
681*1a96fba6SXin Li   SafeFD::Error result = root_.Rmdir(kSubdirName, true /*recursive*/,
682*1a96fba6SXin Li                                      1 /*max_depth*/, false /*keep_going*/);
683*1a96fba6SXin Li   int rmdir_errno = errno;
684*1a96fba6SXin Li 
685*1a96fba6SXin Li   EXPECT_EQ(result, SafeFD::Error::kExceededMaximum);
686*1a96fba6SXin Li 
687*1a96fba6SXin Li   // If we stop on encountering a too-deep directory, we never actually
688*1a96fba6SXin Li   // make any libc calls that encounter errors. This particular behavior
689*1a96fba6SXin Li   // should not be part of the API contract and this can be relaxed if the
690*1a96fba6SXin Li   // implementation is changed.
691*1a96fba6SXin Li   EXPECT_EQ(rmdir_errno, 0);
692*1a96fba6SXin Li 
693*1a96fba6SXin Li   // The deep directory must still exist.
694*1a96fba6SXin Li   ASSERT_TRUE(
695*1a96fba6SXin Li       base::DeleteFile(sub_dir_path_.Append(kSubdirName), false /*recursive*/));
696*1a96fba6SXin Li }
697*1a96fba6SXin Li 
698*1a96fba6SXin Li }  // namespace brillo
699