xref: /aosp_15_r20/external/libbrillo/brillo/files/file_util_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/file_util_test.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <base/files/file_util.h>
8*1a96fba6SXin Li #include <base/rand_util.h>
9*1a96fba6SXin Li #include <base/stl_util.h>
10*1a96fba6SXin Li #include <base/strings/string_number_conversions.h>
11*1a96fba6SXin Li #include <brillo/files/file_util.h>
12*1a96fba6SXin Li #include <brillo/files/safe_fd.h>
13*1a96fba6SXin Li 
14*1a96fba6SXin Li namespace brillo {
15*1a96fba6SXin Li 
16*1a96fba6SXin Li #define TO_STRING_HELPER(x)      \
17*1a96fba6SXin Li   case brillo::SafeFD::Error::x: \
18*1a96fba6SXin Li     return #x;
to_string(brillo::SafeFD::Error err)19*1a96fba6SXin Li std::string to_string(brillo::SafeFD::Error err) {
20*1a96fba6SXin Li   switch (err) {
21*1a96fba6SXin Li     TO_STRING_HELPER(kNoError)
22*1a96fba6SXin Li     TO_STRING_HELPER(kBadArgument)
23*1a96fba6SXin Li     TO_STRING_HELPER(kNotInitialized)
24*1a96fba6SXin Li     TO_STRING_HELPER(kIOError)
25*1a96fba6SXin Li     TO_STRING_HELPER(kDoesNotExist)
26*1a96fba6SXin Li     TO_STRING_HELPER(kSymlinkDetected)
27*1a96fba6SXin Li     TO_STRING_HELPER(kWrongType)
28*1a96fba6SXin Li     TO_STRING_HELPER(kWrongUID)
29*1a96fba6SXin Li     TO_STRING_HELPER(kWrongGID)
30*1a96fba6SXin Li     TO_STRING_HELPER(kWrongPermissions)
31*1a96fba6SXin Li     TO_STRING_HELPER(kExceededMaximum)
32*1a96fba6SXin Li     default:
33*1a96fba6SXin Li       return std::string("unknown (") + std::to_string(static_cast<int>(err)) +
34*1a96fba6SXin Li              ")";
35*1a96fba6SXin Li   }
36*1a96fba6SXin Li }
37*1a96fba6SXin Li #undef TO_STRING_HELPER
38*1a96fba6SXin Li 
operator <<(std::ostream & os,const brillo::SafeFD::Error err)39*1a96fba6SXin Li std::ostream& operator<<(std::ostream& os, const brillo::SafeFD::Error err) {
40*1a96fba6SXin Li   return os << to_string(err);  // whatever needed to print bar to os
41*1a96fba6SXin Li }
42*1a96fba6SXin Li 
GetRandomSuffix()43*1a96fba6SXin Li std::string GetRandomSuffix() {
44*1a96fba6SXin Li   const int kBufferSize = 6;
45*1a96fba6SXin Li   unsigned char buffer[kBufferSize];
46*1a96fba6SXin Li   base::RandBytes(buffer, base::size(buffer));
47*1a96fba6SXin Li   return base::HexEncode(buffer, base::size(buffer));
48*1a96fba6SXin Li }
49*1a96fba6SXin Li 
SetUpTestCase()50*1a96fba6SXin Li void FileTest::SetUpTestCase() {
51*1a96fba6SXin Li   umask(0);
52*1a96fba6SXin Li }
53*1a96fba6SXin Li 
FileTest()54*1a96fba6SXin Li FileTest::FileTest() {
55*1a96fba6SXin Li   CHECK(temp_dir_.CreateUniqueTempDir()) << strerror(errno);
56*1a96fba6SXin Li   sub_dir_path_ = temp_dir_.GetPath().Append(kSubdirName);
57*1a96fba6SXin Li   file_path_ = sub_dir_path_.Append(kFileName);
58*1a96fba6SXin Li 
59*1a96fba6SXin Li   std::string path = temp_dir_.GetPath().value();
60*1a96fba6SXin Li   temp_dir_path_.reserve(path.size() + 1);
61*1a96fba6SXin Li   temp_dir_path_.assign(temp_dir_.GetPath().value().begin(),
62*1a96fba6SXin Li                         temp_dir_.GetPath().value().end());
63*1a96fba6SXin Li   temp_dir_path_.push_back('\0');
64*1a96fba6SXin Li 
65*1a96fba6SXin Li   CHECK_EQ(chmod(temp_dir_path_.data(), SafeFD::kDefaultDirPermissions), 0);
66*1a96fba6SXin Li   SafeFD::SetRootPathForTesting(temp_dir_path_.data());
67*1a96fba6SXin Li   root_ = SafeFD::Root().first;
68*1a96fba6SXin Li   CHECK(root_.is_valid());
69*1a96fba6SXin Li }
70*1a96fba6SXin Li 
SetupSubdir()71*1a96fba6SXin Li bool FileTest::SetupSubdir() {
72*1a96fba6SXin Li   if (!base::CreateDirectory(sub_dir_path_)) {
73*1a96fba6SXin Li     PLOG(ERROR) << "Failed to create '" << sub_dir_path_.value() << "'";
74*1a96fba6SXin Li     return false;
75*1a96fba6SXin Li   }
76*1a96fba6SXin Li   if (chmod(sub_dir_path_.value().c_str(), SafeFD::kDefaultDirPermissions) !=
77*1a96fba6SXin Li       0) {
78*1a96fba6SXin Li     PLOG(ERROR) << "Failed to set permissions of '" << sub_dir_path_.value()
79*1a96fba6SXin Li                 << "'";
80*1a96fba6SXin Li     return false;
81*1a96fba6SXin Li   }
82*1a96fba6SXin Li   return true;
83*1a96fba6SXin Li }
84*1a96fba6SXin Li 
SetupSymlinks()85*1a96fba6SXin Li bool FileTest::SetupSymlinks() {
86*1a96fba6SXin Li   symlink_file_path_ = temp_dir_.GetPath().Append(kSymbolicFileName);
87*1a96fba6SXin Li   symlink_dir_path_ = temp_dir_.GetPath().Append(kSymbolicDirName);
88*1a96fba6SXin Li   if (!base::CreateSymbolicLink(file_path_, symlink_file_path_)) {
89*1a96fba6SXin Li     PLOG(ERROR) << "Failed to create symlink to '" << symlink_file_path_.value()
90*1a96fba6SXin Li                 << "'";
91*1a96fba6SXin Li     return false;
92*1a96fba6SXin Li   }
93*1a96fba6SXin Li   if (!base::CreateSymbolicLink(temp_dir_.GetPath(), symlink_dir_path_)) {
94*1a96fba6SXin Li     PLOG(ERROR) << "Failed to create symlink to'" << symlink_dir_path_.value()
95*1a96fba6SXin Li                 << "'";
96*1a96fba6SXin Li     return false;
97*1a96fba6SXin Li   }
98*1a96fba6SXin Li   return true;
99*1a96fba6SXin Li }
100*1a96fba6SXin Li 
WriteFile(const std::string & contents)101*1a96fba6SXin Li bool FileTest::WriteFile(const std::string& contents) {
102*1a96fba6SXin Li   if (!SetupSubdir()) {
103*1a96fba6SXin Li     return false;
104*1a96fba6SXin Li   }
105*1a96fba6SXin Li   if (contents.length() !=
106*1a96fba6SXin Li       base::WriteFile(file_path_, contents.c_str(), contents.length())) {
107*1a96fba6SXin Li     PLOG(ERROR) << "base::WriteFile failed";
108*1a96fba6SXin Li     return false;
109*1a96fba6SXin Li   }
110*1a96fba6SXin Li   if (chmod(file_path_.value().c_str(), SafeFD::kDefaultFilePermissions) != 0) {
111*1a96fba6SXin Li     PLOG(ERROR) << "chmod failed";
112*1a96fba6SXin Li     return false;
113*1a96fba6SXin Li   }
114*1a96fba6SXin Li   return true;
115*1a96fba6SXin Li }
116*1a96fba6SXin Li 
ExpectFileContains(const std::string & contents)117*1a96fba6SXin Li void FileTest::ExpectFileContains(const std::string& contents) {
118*1a96fba6SXin Li   EXPECT_TRUE(base::PathExists(file_path_));
119*1a96fba6SXin Li   std::string new_contents;
120*1a96fba6SXin Li   EXPECT_TRUE(base::ReadFileToString(file_path_, &new_contents));
121*1a96fba6SXin Li   EXPECT_EQ(contents, new_contents);
122*1a96fba6SXin Li }
123*1a96fba6SXin Li 
ExpectPermissions(base::FilePath path,int permissions)124*1a96fba6SXin Li void FileTest::ExpectPermissions(base::FilePath path, int permissions) {
125*1a96fba6SXin Li   int actual_permissions = 0;
126*1a96fba6SXin Li   // This breaks out of the ExpectPermissions() call but not the test case.
127*1a96fba6SXin Li   ASSERT_TRUE(base::GetPosixFilePermissions(path, &actual_permissions));
128*1a96fba6SXin Li   EXPECT_EQ(permissions, actual_permissions);
129*1a96fba6SXin Li }
130*1a96fba6SXin Li 
131*1a96fba6SXin Li // Creates a file with a random name in the temporary directory.
GetTempName()132*1a96fba6SXin Li base::FilePath FileTest::GetTempName() {
133*1a96fba6SXin Li   return temp_dir_.GetPath().Append(GetRandomSuffix());
134*1a96fba6SXin Li }
135*1a96fba6SXin Li 
136*1a96fba6SXin Li constexpr char FileTest::kFileName[];
137*1a96fba6SXin Li constexpr char FileTest::kSubdirName[];
138*1a96fba6SXin Li constexpr char FileTest::kSymbolicFileName[];
139*1a96fba6SXin Li constexpr char FileTest::kSymbolicDirName[];
140*1a96fba6SXin Li 
141*1a96fba6SXin Li class FileUtilTest : public FileTest {};
142*1a96fba6SXin Li 
TEST_F(FileUtilTest,GetFDPath_SimpleSuccess)143*1a96fba6SXin Li TEST_F(FileUtilTest, GetFDPath_SimpleSuccess) {
144*1a96fba6SXin Li   EXPECT_EQ(GetFDPath(root_.get()), temp_dir_.GetPath());
145*1a96fba6SXin Li }
146*1a96fba6SXin Li 
TEST_F(FileUtilTest,GetFDPath_BadFD)147*1a96fba6SXin Li TEST_F(FileUtilTest, GetFDPath_BadFD) {
148*1a96fba6SXin Li   base::FilePath path = GetFDPath(-1);
149*1a96fba6SXin Li   EXPECT_TRUE(path.empty());
150*1a96fba6SXin Li }
151*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeDir_SimpleSuccess)152*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeDir_SimpleSuccess) {
153*1a96fba6SXin Li   SafeFD::Error err;
154*1a96fba6SXin Li   SafeFD dir;
155*1a96fba6SXin Li 
156*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
157*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
158*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
159*1a96fba6SXin Li 
160*1a96fba6SXin Li   SafeFD subdir;
161*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, kSubdirName);
162*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
163*1a96fba6SXin Li   EXPECT_TRUE(subdir.is_valid());
164*1a96fba6SXin Li }
165*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeDir_SuccessAfterRetry)166*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeDir_SuccessAfterRetry) {
167*1a96fba6SXin Li   ASSERT_NE(base::WriteFile(sub_dir_path_, "", 0), -1);
168*1a96fba6SXin Li   SafeFD::Error err;
169*1a96fba6SXin Li   SafeFD dir;
170*1a96fba6SXin Li 
171*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
172*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
173*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
174*1a96fba6SXin Li 
175*1a96fba6SXin Li   SafeFD subdir;
176*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, kSubdirName);
177*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
178*1a96fba6SXin Li   EXPECT_TRUE(subdir.is_valid());
179*1a96fba6SXin Li }
180*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeDir_BadArgument)181*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeDir_BadArgument) {
182*1a96fba6SXin Li   SafeFD::Error err;
183*1a96fba6SXin Li   SafeFD dir;
184*1a96fba6SXin Li 
185*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
186*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
187*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
188*1a96fba6SXin Li 
189*1a96fba6SXin Li   SafeFD subdir;
190*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, ".");
191*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kBadArgument);
192*1a96fba6SXin Li   EXPECT_FALSE(subdir.is_valid());
193*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, "..");
194*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kBadArgument);
195*1a96fba6SXin Li   EXPECT_FALSE(subdir.is_valid());
196*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, "a/a");
197*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kBadArgument);
198*1a96fba6SXin Li   EXPECT_FALSE(subdir.is_valid());
199*1a96fba6SXin Li }
200*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeDir_NotInitialized)201*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeDir_NotInitialized) {
202*1a96fba6SXin Li   SafeFD::Error err;
203*1a96fba6SXin Li   SafeFD dir;
204*1a96fba6SXin Li 
205*1a96fba6SXin Li   SafeFD subdir;
206*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, kSubdirName);
207*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNotInitialized);
208*1a96fba6SXin Li   EXPECT_FALSE(subdir.is_valid());
209*1a96fba6SXin Li }
210*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeDir_IOError)211*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeDir_IOError) {
212*1a96fba6SXin Li   SafeFD::Error err;
213*1a96fba6SXin Li   SafeFD dir;
214*1a96fba6SXin Li 
215*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(temp_dir_.GetPath());
216*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
217*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
218*1a96fba6SXin Li   ASSERT_EQ(chmod(temp_dir_path_.data(), 0000), 0);
219*1a96fba6SXin Li 
220*1a96fba6SXin Li   SafeFD subdir;
221*1a96fba6SXin Li   std::tie(subdir, err) = OpenOrRemakeDir(&dir, kSubdirName);
222*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kIOError);
223*1a96fba6SXin Li   EXPECT_FALSE(subdir.is_valid());
224*1a96fba6SXin Li }
225*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeFile_SimpleSuccess)226*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeFile_SimpleSuccess) {
227*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
228*1a96fba6SXin Li   SafeFD::Error err;
229*1a96fba6SXin Li   SafeFD dir;
230*1a96fba6SXin Li 
231*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(sub_dir_path_);
232*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
233*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
234*1a96fba6SXin Li 
235*1a96fba6SXin Li   SafeFD file;
236*1a96fba6SXin Li   std::tie(file, err) = OpenOrRemakeFile(&dir, kFileName);
237*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
238*1a96fba6SXin Li   EXPECT_TRUE(file.is_valid());
239*1a96fba6SXin Li }
240*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeFile_SuccessAfterRetry)241*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeFile_SuccessAfterRetry) {
242*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
243*1a96fba6SXin Li   ASSERT_TRUE(base::CreateDirectory(file_path_));
244*1a96fba6SXin Li   SafeFD::Error err;
245*1a96fba6SXin Li   SafeFD dir;
246*1a96fba6SXin Li 
247*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(sub_dir_path_);
248*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
249*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
250*1a96fba6SXin Li 
251*1a96fba6SXin Li   SafeFD file;
252*1a96fba6SXin Li   std::tie(file, err) = OpenOrRemakeFile(&dir, kFileName);
253*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
254*1a96fba6SXin Li   EXPECT_TRUE(file.is_valid());
255*1a96fba6SXin Li }
256*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeFile_NotInitialized)257*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeFile_NotInitialized) {
258*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
259*1a96fba6SXin Li   SafeFD::Error err;
260*1a96fba6SXin Li   SafeFD dir;
261*1a96fba6SXin Li 
262*1a96fba6SXin Li   SafeFD file;
263*1a96fba6SXin Li   std::tie(file, err) = OpenOrRemakeFile(&dir, kFileName);
264*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNotInitialized);
265*1a96fba6SXin Li   EXPECT_FALSE(file.is_valid());
266*1a96fba6SXin Li }
267*1a96fba6SXin Li 
TEST_F(FileUtilTest,OpenOrRemakeFile_IOError)268*1a96fba6SXin Li TEST_F(FileUtilTest, OpenOrRemakeFile_IOError) {
269*1a96fba6SXin Li   ASSERT_TRUE(SetupSubdir());
270*1a96fba6SXin Li   SafeFD::Error err;
271*1a96fba6SXin Li   SafeFD dir;
272*1a96fba6SXin Li 
273*1a96fba6SXin Li   std::tie(dir, err) = root_.OpenExistingDir(sub_dir_path_);
274*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kNoError);
275*1a96fba6SXin Li   ASSERT_TRUE(dir.is_valid());
276*1a96fba6SXin Li   ASSERT_EQ(chmod(sub_dir_path_.value().c_str(), 0000), 0);
277*1a96fba6SXin Li 
278*1a96fba6SXin Li   SafeFD file;
279*1a96fba6SXin Li   std::tie(file, err) = OpenOrRemakeFile(&dir, kFileName);
280*1a96fba6SXin Li   EXPECT_EQ(err, SafeFD::Error::kIOError);
281*1a96fba6SXin Li   EXPECT_FALSE(file.is_valid());
282*1a96fba6SXin Li }
283*1a96fba6SXin Li 
284*1a96fba6SXin Li }  // namespace brillo
285