1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 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 <fcntl.h>
18*795d594fSAndroid Build Coastguard Worker #include <string.h>
19*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include <iosfwd>
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <string>
24*795d594fSAndroid Build Coastguard Worker #include <vector>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/common_art_test.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
31*795d594fSAndroid Build Coastguard Worker #include "odr_fs_utils.h"
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker namespace art {
34*795d594fSAndroid Build Coastguard Worker namespace odrefresh {
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker class OdrFsUtilsTest : public CommonArtTest {};
37*795d594fSAndroid Build Coastguard Worker namespace {
38*795d594fSAndroid Build Coastguard Worker
CreateFile(const char * file_path,size_t bytes)39*795d594fSAndroid Build Coastguard Worker static bool CreateFile(const char* file_path, size_t bytes) {
40*795d594fSAndroid Build Coastguard Worker std::unique_ptr<File> fp(OS::CreateEmptyFile(file_path));
41*795d594fSAndroid Build Coastguard Worker if (!fp) {
42*795d594fSAndroid Build Coastguard Worker return false;
43*795d594fSAndroid Build Coastguard Worker }
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Worker std::vector<char> buffer(bytes, 0xa5);
46*795d594fSAndroid Build Coastguard Worker if (!fp->WriteFully(buffer.data(), buffer.size())) {
47*795d594fSAndroid Build Coastguard Worker fp->Erase();
48*795d594fSAndroid Build Coastguard Worker return false;
49*795d594fSAndroid Build Coastguard Worker }
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker if (fp->FlushClose() != 0) {
52*795d594fSAndroid Build Coastguard Worker fp->Erase();
53*795d594fSAndroid Build Coastguard Worker return false;
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker return true;
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker } // namespace
60*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,RemoveDirectory)61*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, RemoveDirectory) {
62*795d594fSAndroid Build Coastguard Worker ScratchDir scratch_dir(/*keep_files=*/false);
63*795d594fSAndroid Build Coastguard Worker
64*795d594fSAndroid Build Coastguard Worker // Create some sub-directories and files
65*795d594fSAndroid Build Coastguard Worker const std::string dir_paths[] = {
66*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/a",
67*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/b",
68*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/b/c",
69*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/d"
70*795d594fSAndroid Build Coastguard Worker };
71*795d594fSAndroid Build Coastguard Worker for (const auto& dir_path : dir_paths) {
72*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, mkdir(dir_path.c_str(), S_IRWXU));
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker const std::string file_paths[] = {
76*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/zero.txt",
77*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/a/one.txt",
78*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/b/two.txt",
79*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/b/c/three.txt",
80*795d594fSAndroid Build Coastguard Worker scratch_dir.GetPath() + "/b/c/four.txt",
81*795d594fSAndroid Build Coastguard Worker };
82*795d594fSAndroid Build Coastguard Worker for (const auto& file_path : file_paths) {
83*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateFile(file_path.c_str(), 4096));
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker
86*795d594fSAndroid Build Coastguard Worker // Remove directory, all files and sub-directories
87*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(RemoveDirectory(scratch_dir.GetPath()));
88*795d594fSAndroid Build Coastguard Worker
89*795d594fSAndroid Build Coastguard Worker // Check nothing we created remains.
90*795d594fSAndroid Build Coastguard Worker for (const auto& dir_path : dir_paths) {
91*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(OS::DirectoryExists(dir_path.c_str()));
92*795d594fSAndroid Build Coastguard Worker }
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker for (const auto& file_path : file_paths) {
95*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(OS::FileExists(file_path.c_str(), true));
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
98*795d594fSAndroid Build Coastguard Worker // And the original directory is also gone
99*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(OS::DirectoryExists(scratch_dir.GetPath().c_str()));
100*795d594fSAndroid Build Coastguard Worker }
101*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,EnsureDirectoryExistsBadPath)102*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsBadPath) {
103*795d594fSAndroid Build Coastguard Worker // Pick a path where not even a root test runner can write.
104*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(EnsureDirectoryExists("/proc/unlikely/to/be/writable"));
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,EnsureDirectoryExistsEmptyPath)107*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsEmptyPath) {
108*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(EnsureDirectoryExists(""));
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,EnsureDirectoryExistsRelativePath)111*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsRelativePath) {
112*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(EnsureDirectoryExists("a/b/c"));
113*795d594fSAndroid Build Coastguard Worker }
114*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,EnsureDirectoryExistsSubDirs)115*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, EnsureDirectoryExistsSubDirs) {
116*795d594fSAndroid Build Coastguard Worker ScratchDir scratch_dir(/*keep_files=*/false);
117*795d594fSAndroid Build Coastguard Worker
118*795d594fSAndroid Build Coastguard Worker const char* relative_sub_dirs[] = {"a", "b/c", "d/e/f/"};
119*795d594fSAndroid Build Coastguard Worker for (const char* relative_sub_dir : relative_sub_dirs) {
120*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EnsureDirectoryExists(scratch_dir.GetPath() + "/" + relative_sub_dir));
121*795d594fSAndroid Build Coastguard Worker }
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,DISABLED_GetUsedSpace)124*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, DISABLED_GetUsedSpace) {
125*795d594fSAndroid Build Coastguard Worker static constexpr size_t kFirstFileBytes = 1;
126*795d594fSAndroid Build Coastguard Worker static constexpr size_t kSecondFileBytes = 16111;
127*795d594fSAndroid Build Coastguard Worker static constexpr size_t kBytesPerBlock = 512;
128*795d594fSAndroid Build Coastguard Worker
129*795d594fSAndroid Build Coastguard Worker ScratchDir scratch_dir(/*keep_files=*/false);
130*795d594fSAndroid Build Coastguard Worker
131*795d594fSAndroid Build Coastguard Worker const std::string first_file_path = scratch_dir.GetPath() + "/1.dat";
132*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateFile(first_file_path.c_str(), kFirstFileBytes));
133*795d594fSAndroid Build Coastguard Worker
134*795d594fSAndroid Build Coastguard Worker struct stat sb;
135*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0, stat(first_file_path.c_str(), &sb));
136*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(kFirstFileBytes, static_cast<decltype(kFirstFileBytes)>(sb.st_size));
137*795d594fSAndroid Build Coastguard Worker
138*795d594fSAndroid Build Coastguard Worker uint64_t bytes_used = 0;
139*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath(), &bytes_used));
140*795d594fSAndroid Build Coastguard Worker
141*795d594fSAndroid Build Coastguard Worker const std::string second_file_path = scratch_dir.GetPath() + "/2.dat";
142*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateFile(second_file_path.c_str(), kSecondFileBytes));
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath(), &bytes_used));
145*795d594fSAndroid Build Coastguard Worker uint64_t expected_bytes_used = RoundUp(kFirstFileBytes, sb.st_blocks * kBytesPerBlock) +
146*795d594fSAndroid Build Coastguard Worker RoundUp(kSecondFileBytes, sb.st_blocks * kBytesPerBlock);
147*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(expected_bytes_used, bytes_used);
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker const std::string sub_dir_path = scratch_dir.GetPath() + "/sub";
150*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(EnsureDirectoryExists(sub_dir_path));
151*795d594fSAndroid Build Coastguard Worker for (size_t i = 1; i < 32768; i *= 17) {
152*795d594fSAndroid Build Coastguard Worker const std::string path = android::base::StringPrintf("%s/%zu", sub_dir_path.c_str(), i);
153*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(CreateFile(path.c_str(), i));
154*795d594fSAndroid Build Coastguard Worker expected_bytes_used += RoundUp(i, sb.st_blocks * kBytesPerBlock);
155*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(GetUsedSpace(scratch_dir.GetPath(), &bytes_used));
156*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(expected_bytes_used, bytes_used);
157*795d594fSAndroid Build Coastguard Worker }
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker
TEST_F(OdrFsUtilsTest,GetUsedSpaceBadPath)160*795d594fSAndroid Build Coastguard Worker TEST_F(OdrFsUtilsTest, GetUsedSpaceBadPath) {
161*795d594fSAndroid Build Coastguard Worker ScratchDir scratch_dir(/*keep_files=*/false);
162*795d594fSAndroid Build Coastguard Worker const std::string bad_path = scratch_dir.GetPath() + "/bad_path";
163*795d594fSAndroid Build Coastguard Worker uint64_t bytes_used = ~0ull;
164*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(GetUsedSpace(bad_path, &bytes_used));
165*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(0ull, bytes_used);
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker } // namespace odrefresh
169*795d594fSAndroid Build Coastguard Worker } // namespace art
170