xref: /aosp_15_r20/art/artd/file_utils_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "file_utils.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <fcntl.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
21*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include <filesystem>
24*795d594fSAndroid Build Coastguard Worker #include <memory>
25*795d594fSAndroid Build Coastguard Worker #include <string>
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/FsPermission.h"
28*795d594fSAndroid Build Coastguard Worker #include "android-base/errors.h"
29*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
30*795d594fSAndroid Build Coastguard Worker #include "android-base/result-gmock.h"
31*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/common_art_test.h"
33*795d594fSAndroid Build Coastguard Worker #include "gmock/gmock.h"
34*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker namespace art {
37*795d594fSAndroid Build Coastguard Worker namespace artd {
38*795d594fSAndroid Build Coastguard Worker namespace {
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::FsPermission;
41*795d594fSAndroid Build Coastguard Worker using ::android::base::Error;
42*795d594fSAndroid Build Coastguard Worker using ::android::base::ReadFileToString;
43*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
44*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFd;
45*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFile;
46*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::HasError;
47*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::HasValue;
48*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::Ok;
49*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::WithMessage;
50*795d594fSAndroid Build Coastguard Worker using ::testing::ContainsRegex;
51*795d594fSAndroid Build Coastguard Worker using ::testing::IsEmpty;
52*795d594fSAndroid Build Coastguard Worker using ::testing::NotNull;
53*795d594fSAndroid Build Coastguard Worker 
CheckContent(const std::string & path,const std::string & expected_content)54*795d594fSAndroid Build Coastguard Worker void CheckContent(const std::string& path, const std::string& expected_content) {
55*795d594fSAndroid Build Coastguard Worker   std::string actual_content;
56*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(ReadFileToString(path, &actual_content));
57*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(actual_content, expected_content);
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker // A file that will always fail on `Keep`.
61*795d594fSAndroid Build Coastguard Worker class UnkeepableFile : public NewFile {
62*795d594fSAndroid Build Coastguard Worker  public:
Create(const std::string & path,const FsPermission & fs_permission)63*795d594fSAndroid Build Coastguard Worker   static Result<std::unique_ptr<UnkeepableFile>> Create(const std::string& path,
64*795d594fSAndroid Build Coastguard Worker                                                         const FsPermission& fs_permission) {
65*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<NewFile> new_file = OR_RETURN(NewFile::Create(path, fs_permission));
66*795d594fSAndroid Build Coastguard Worker     return std::unique_ptr<UnkeepableFile>(new UnkeepableFile(std::move(*new_file)));
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker 
Keep()69*795d594fSAndroid Build Coastguard Worker   Result<void> Keep() override { return Error() << "Unkeepable file"; }
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker  private:
UnkeepableFile(NewFile && other)72*795d594fSAndroid Build Coastguard Worker   explicit UnkeepableFile(NewFile&& other) : NewFile(std::move(other)) {}
73*795d594fSAndroid Build Coastguard Worker };
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker class FileUtilsTest : public CommonArtTest {
76*795d594fSAndroid Build Coastguard Worker  protected:
SetUp()77*795d594fSAndroid Build Coastguard Worker   void SetUp() override {
78*795d594fSAndroid Build Coastguard Worker     CommonArtTest::SetUp();
79*795d594fSAndroid Build Coastguard Worker     scratch_dir_ = std::make_unique<ScratchDir>();
80*795d594fSAndroid Build Coastguard Worker     struct stat st;
81*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(stat(scratch_dir_->GetPath().c_str(), &st), 0);
82*795d594fSAndroid Build Coastguard Worker     fs_permission_ = FsPermission{.uid = static_cast<int32_t>(st.st_uid),
83*795d594fSAndroid Build Coastguard Worker                                   .gid = static_cast<int32_t>(st.st_gid)};
84*795d594fSAndroid Build Coastguard Worker   }
85*795d594fSAndroid Build Coastguard Worker 
TearDown()86*795d594fSAndroid Build Coastguard Worker   void TearDown() override {
87*795d594fSAndroid Build Coastguard Worker     scratch_dir_.reset();
88*795d594fSAndroid Build Coastguard Worker     CommonArtTest::TearDown();
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker   FsPermission fs_permission_;
92*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ScratchDir> scratch_dir_;
93*795d594fSAndroid Build Coastguard Worker };
94*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCreate)95*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCreate) {
96*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/file.tmp";
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   Result<std::unique_ptr<NewFile>> new_file = NewFile::Create(path, fs_permission_);
99*795d594fSAndroid Build Coastguard Worker   ASSERT_THAT(new_file, HasValue(NotNull()));
100*795d594fSAndroid Build Coastguard Worker   EXPECT_GE((*new_file)->Fd(), 0);
101*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ((*new_file)->FinalPath(), path);
102*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT((*new_file)->TempPath(), Not(IsEmpty()));
103*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT((*new_file)->TempId(), Not(IsEmpty()));
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists((*new_file)->FinalPath()));
106*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(std::filesystem::exists((*new_file)->TempPath()));
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCreateNonExistentDir)109*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCreateNonExistentDir) {
110*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/non_existent_dir/file.tmp";
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::Create(path, fs_permission_),
113*795d594fSAndroid Build Coastguard Worker               HasError(WithMessage(
114*795d594fSAndroid Build Coastguard Worker                   ContainsRegex("Failed to create temp file for .*/non_existent_dir/file.tmp"))));
115*795d594fSAndroid Build Coastguard Worker }
116*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileExplicitCleanup)117*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileExplicitCleanup) {
118*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/file.tmp";
119*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file = OR_FATAL(NewFile::Create(path, fs_permission_));
120*795d594fSAndroid Build Coastguard Worker   new_file->Cleanup();
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(path));
123*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file->TempPath()));
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileImplicitCleanup)126*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileImplicitCleanup) {
127*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/file.tmp";
128*795d594fSAndroid Build Coastguard Worker   std::string temp_path;
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   // Cleanup on object destruction.
131*795d594fSAndroid Build Coastguard Worker   {
132*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<NewFile> new_file = OR_FATAL(NewFile::Create(path, fs_permission_));
133*795d594fSAndroid Build Coastguard Worker     temp_path = new_file->TempPath();
134*795d594fSAndroid Build Coastguard Worker   }
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(path));
137*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(temp_path));
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommit)140*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommit) {
141*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/file.tmp";
142*795d594fSAndroid Build Coastguard Worker   std::string temp_path;
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker   {
145*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<NewFile> new_file = OR_FATAL(NewFile::Create(path, fs_permission_));
146*795d594fSAndroid Build Coastguard Worker     temp_path = new_file->TempPath();
147*795d594fSAndroid Build Coastguard Worker     new_file->CommitOrAbandon();
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker 
150*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(std::filesystem::exists(path));
151*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(temp_path));
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllNoOldFile)154*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllNoOldFile) {
155*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
156*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
159*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
162*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}), Ok());
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker   // New files are committed.
167*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "new_file_1");
168*795d594fSAndroid Build Coastguard Worker   CheckContent(file_2_path, "new_file_2");
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   // New files are no longer at the temporary paths.
171*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
172*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
173*795d594fSAndroid Build Coastguard Worker }
174*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllReplacesOldFiles)175*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllReplacesOldFiles) {
176*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
177*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_1", file_1_path));
180*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_2", file_2_path));
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
183*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
186*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}), Ok());
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker   // New files are committed.
191*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "new_file_1");
192*795d594fSAndroid Build Coastguard Worker   CheckContent(file_2_path, "new_file_2");
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   // New files are no longer at the temporary paths.
195*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
196*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllReplacesLessOldFiles)199*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllReplacesLessOldFiles) {
200*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
201*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_1", file_1_path));  // No old_file_2.
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
206*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
209*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}), Ok());
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker   // New files are committed.
214*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "new_file_1");
215*795d594fSAndroid Build Coastguard Worker   CheckContent(file_2_path, "new_file_2");
216*795d594fSAndroid Build Coastguard Worker 
217*795d594fSAndroid Build Coastguard Worker   // New files are no longer at the temporary paths.
218*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
219*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllReplacesMoreOldFiles)222*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllReplacesMoreOldFiles) {
223*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
224*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
225*795d594fSAndroid Build Coastguard Worker   std::string file_3_path = scratch_dir_->GetPath() + "/file_3";
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_1", file_1_path));
228*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_2", file_2_path));
229*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_3", file_3_path));  // Extra file.
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
232*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
235*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}, {file_3_path}),
238*795d594fSAndroid Build Coastguard Worker               Ok());
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker   // New files are committed.
241*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "new_file_1");
242*795d594fSAndroid Build Coastguard Worker   CheckContent(file_2_path, "new_file_2");
243*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(file_3_path));  // Extra file removed.
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker   // New files are no longer at the temporary paths.
246*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
247*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllFailedToKeep)250*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllFailedToKeep) {
251*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
252*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
253*795d594fSAndroid Build Coastguard Worker   std::string file_3_path = scratch_dir_->GetPath() + "/file_3";
254*795d594fSAndroid Build Coastguard Worker 
255*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_1", file_1_path));
256*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_2", file_2_path));
257*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_3", file_3_path));  // Extra file.
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
260*795d594fSAndroid Build Coastguard Worker   // Unkeepable file.
261*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 =
262*795d594fSAndroid Build Coastguard Worker       OR_FATAL(UnkeepableFile::Create(file_2_path, fs_permission_));
263*795d594fSAndroid Build Coastguard Worker 
264*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
265*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}, {file_3_path}),
268*795d594fSAndroid Build Coastguard Worker               HasError(WithMessage("Unkeepable file")));
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   // Old files are fine.
271*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "old_file_1");
272*795d594fSAndroid Build Coastguard Worker   CheckContent(file_2_path, "old_file_2");
273*795d594fSAndroid Build Coastguard Worker   CheckContent(file_3_path, "old_file_3");
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   // New files are abandoned.
276*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
277*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllFailedToCommit)280*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllFailedToCommit) {
281*795d594fSAndroid Build Coastguard Worker   std::string dir_1_path = scratch_dir_->GetPath() + "/dir_1";
282*795d594fSAndroid Build Coastguard Worker   std::string dir_2_path = scratch_dir_->GetPath() + "/dir_2";
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(std::filesystem::create_directory(dir_1_path));
285*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(std::filesystem::create_directory(dir_2_path));
286*795d594fSAndroid Build Coastguard Worker 
287*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = dir_1_path + "/file_1";
288*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = dir_2_path + "/file_2";
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
291*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
292*795d594fSAndroid Build Coastguard Worker 
293*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
294*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker   {
297*795d594fSAndroid Build Coastguard Worker     // Make `new_file_2` fail to commit.
298*795d594fSAndroid Build Coastguard Worker     auto scoped_inaccessible = ScopedInaccessible(dir_2_path);
299*795d594fSAndroid Build Coastguard Worker     std::filesystem::permissions(
300*795d594fSAndroid Build Coastguard Worker         dir_2_path, std::filesystem::perms::owner_exec, std::filesystem::perm_options::add);
301*795d594fSAndroid Build Coastguard Worker     auto scoped_unroot = ScopedUnroot();
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker     EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}),
304*795d594fSAndroid Build Coastguard Worker                 HasError(WithMessage(ContainsRegex("Failed to move file .*file_2.*"))));
305*795d594fSAndroid Build Coastguard Worker   }
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker   // Files are abandoned at best effort. File 1 is abandoned, but file 2 cannot be abandoned due to
308*795d594fSAndroid Build Coastguard Worker   // permission denied.
309*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
310*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->FinalPath()));
311*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(std::filesystem::exists(new_file_2->TempPath()));
312*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->FinalPath()));
313*795d594fSAndroid Build Coastguard Worker }
314*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,NewFileCommitAllFailedToMoveOldFile)315*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, NewFileCommitAllFailedToMoveOldFile) {
316*795d594fSAndroid Build Coastguard Worker   std::string file_1_path = scratch_dir_->GetPath() + "/file_1";
317*795d594fSAndroid Build Coastguard Worker   std::string file_2_path = scratch_dir_->GetPath() + "/file_2";
318*795d594fSAndroid Build Coastguard Worker   std::filesystem::create_directory(file_2_path);
319*795d594fSAndroid Build Coastguard Worker   std::string file_3_path = scratch_dir_->GetPath() + "/file_3";
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_1", file_1_path));
322*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("old_file_3", file_3_path));  // Extra file.
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_1 = OR_FATAL(NewFile::Create(file_1_path, fs_permission_));
325*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<NewFile> new_file_2 = OR_FATAL(NewFile::Create(file_2_path, fs_permission_));
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_1", new_file_1->Fd()));
328*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFd("new_file_2", new_file_2->Fd()));
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker   // file_2 is not movable because it is a directory.
331*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(NewFile::CommitAllOrAbandon({new_file_1.get(), new_file_2.get()}, {file_3_path}),
332*795d594fSAndroid Build Coastguard Worker               HasError(WithMessage(ContainsRegex("Old file '.*/file_2' is a directory"))));
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker   // Old files are fine.
335*795d594fSAndroid Build Coastguard Worker   CheckContent(file_1_path, "old_file_1");
336*795d594fSAndroid Build Coastguard Worker   EXPECT_TRUE(std::filesystem::is_directory(file_2_path));
337*795d594fSAndroid Build Coastguard Worker   CheckContent(file_3_path, "old_file_3");
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   // New files are abandoned.
340*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_1->TempPath()));
341*795d594fSAndroid Build Coastguard Worker   EXPECT_FALSE(std::filesystem::exists(new_file_2->TempPath()));
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,BuildTempPath)344*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, BuildTempPath) {
345*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(NewFile::BuildTempPath("/a/b/original_path", "123456"),
346*795d594fSAndroid Build Coastguard Worker             "/a/b/original_path.123456.tmp");
347*795d594fSAndroid Build Coastguard Worker }
348*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,OpenFileForReading)349*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, OpenFileForReading) {
350*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/foo";
351*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(WriteStringToFile("foo", path));
352*795d594fSAndroid Build Coastguard Worker 
353*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(OpenFileForReading(path), HasValue(NotNull()));
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,OpenFileForReadingFailed)356*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, OpenFileForReadingFailed) {
357*795d594fSAndroid Build Coastguard Worker   std::string path = scratch_dir_->GetPath() + "/foo";
358*795d594fSAndroid Build Coastguard Worker 
359*795d594fSAndroid Build Coastguard Worker   EXPECT_THAT(OpenFileForReading(path),
360*795d594fSAndroid Build Coastguard Worker               HasError(WithMessage(ContainsRegex("Failed to open file .*/foo"))));
361*795d594fSAndroid Build Coastguard Worker }
362*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,FileFsPermissionToMode)363*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, FileFsPermissionToMode) {
364*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(FileFsPermissionToMode(FsPermission{}), S_IRUSR | S_IWUSR | S_IRGRP);
365*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(FileFsPermissionToMode(FsPermission{.isOtherReadable = true}),
366*795d594fSAndroid Build Coastguard Worker             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
367*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(FileFsPermissionToMode(FsPermission{.isOtherExecutable = true}),
368*795d594fSAndroid Build Coastguard Worker             S_IRUSR | S_IWUSR | S_IRGRP | S_IXOTH);
369*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(
370*795d594fSAndroid Build Coastguard Worker       FileFsPermissionToMode(FsPermission{.isOtherReadable = true, .isOtherExecutable = true}),
371*795d594fSAndroid Build Coastguard Worker       S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IXOTH);
372*795d594fSAndroid Build Coastguard Worker }
373*795d594fSAndroid Build Coastguard Worker 
TEST_F(FileUtilsTest,DirFsPermissionToMode)374*795d594fSAndroid Build Coastguard Worker TEST_F(FileUtilsTest, DirFsPermissionToMode) {
375*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(DirFsPermissionToMode(FsPermission{}), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP);
376*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(DirFsPermissionToMode(FsPermission{.isOtherReadable = true}),
377*795d594fSAndroid Build Coastguard Worker             S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH);
378*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(DirFsPermissionToMode(FsPermission{.isOtherExecutable = true}),
379*795d594fSAndroid Build Coastguard Worker             S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IXOTH);
380*795d594fSAndroid Build Coastguard Worker   EXPECT_EQ(DirFsPermissionToMode(FsPermission{.isOtherReadable = true, .isOtherExecutable = true}),
381*795d594fSAndroid Build Coastguard Worker             S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker 
384*795d594fSAndroid Build Coastguard Worker }  // namespace
385*795d594fSAndroid Build Coastguard Worker }  // namespace artd
386*795d594fSAndroid Build Coastguard Worker }  // namespace art
387