1*9190c2a8SAndroid Build Coastguard Worker /*
2*9190c2a8SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*9190c2a8SAndroid Build Coastguard Worker *
4*9190c2a8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*9190c2a8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*9190c2a8SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*9190c2a8SAndroid Build Coastguard Worker *
8*9190c2a8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*9190c2a8SAndroid Build Coastguard Worker *
10*9190c2a8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*9190c2a8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*9190c2a8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9190c2a8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*9190c2a8SAndroid Build Coastguard Worker * limitations under the License.
15*9190c2a8SAndroid Build Coastguard Worker */
16*9190c2a8SAndroid Build Coastguard Worker
17*9190c2a8SAndroid Build Coastguard Worker #include <android-base/file.h>
18*9190c2a8SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
19*9190c2a8SAndroid Build Coastguard Worker #include <sys/select.h>
20*9190c2a8SAndroid Build Coastguard Worker
21*9190c2a8SAndroid Build Coastguard Worker #include <unistd.h>
22*9190c2a8SAndroid Build Coastguard Worker
23*9190c2a8SAndroid Build Coastguard Worker #include <optional>
24*9190c2a8SAndroid Build Coastguard Worker #include <thread>
25*9190c2a8SAndroid Build Coastguard Worker
26*9190c2a8SAndroid Build Coastguard Worker #include "IncFsTestBase.h"
27*9190c2a8SAndroid Build Coastguard Worker
28*9190c2a8SAndroid Build Coastguard Worker using namespace android::incfs;
29*9190c2a8SAndroid Build Coastguard Worker using namespace std::literals;
30*9190c2a8SAndroid Build Coastguard Worker namespace ab = android::base;
31*9190c2a8SAndroid Build Coastguard Worker
32*9190c2a8SAndroid Build Coastguard Worker struct ScopedUnmount {
33*9190c2a8SAndroid Build Coastguard Worker std::string path_;
ScopedUnmountScopedUnmount34*9190c2a8SAndroid Build Coastguard Worker explicit ScopedUnmount(std::string&& path) : path_(std::move(path)) {}
~ScopedUnmountScopedUnmount35*9190c2a8SAndroid Build Coastguard Worker ~ScopedUnmount() { unmount(path_); }
36*9190c2a8SAndroid Build Coastguard Worker };
37*9190c2a8SAndroid Build Coastguard Worker
38*9190c2a8SAndroid Build Coastguard Worker class IncFsTest : public IncFsTestBase {
39*9190c2a8SAndroid Build Coastguard Worker protected:
getReadTimeout()40*9190c2a8SAndroid Build Coastguard Worker virtual int32_t getReadTimeout() {
41*9190c2a8SAndroid Build Coastguard Worker return std::chrono::duration_cast<std::chrono::milliseconds>(kDefaultReadTimeout).count();
42*9190c2a8SAndroid Build Coastguard Worker }
43*9190c2a8SAndroid Build Coastguard Worker
metadata(std::string_view sv)44*9190c2a8SAndroid Build Coastguard Worker static IncFsSpan metadata(std::string_view sv) {
45*9190c2a8SAndroid Build Coastguard Worker return {.data = sv.data(), .size = IncFsSize(sv.size())};
46*9190c2a8SAndroid Build Coastguard Worker }
47*9190c2a8SAndroid Build Coastguard Worker
sizeToPages(int size)48*9190c2a8SAndroid Build Coastguard Worker static int sizeToPages(int size) {
49*9190c2a8SAndroid Build Coastguard Worker return (size + INCFS_DATA_FILE_BLOCK_SIZE - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
50*9190c2a8SAndroid Build Coastguard Worker }
51*9190c2a8SAndroid Build Coastguard Worker
writeTestRanges(int id,int size)52*9190c2a8SAndroid Build Coastguard Worker void writeTestRanges(int id, int size) {
53*9190c2a8SAndroid Build Coastguard Worker auto wfd = openForSpecialOps(control_, fileId(id));
54*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(wfd.get(), 0);
55*9190c2a8SAndroid Build Coastguard Worker
56*9190c2a8SAndroid Build Coastguard Worker auto lastPage = sizeToPages(size) - 1;
57*9190c2a8SAndroid Build Coastguard Worker
58*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
59*9190c2a8SAndroid Build Coastguard Worker DataBlock blocks[] = {{
60*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
61*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 1,
62*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
63*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
64*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
65*9190c2a8SAndroid Build Coastguard Worker },
66*9190c2a8SAndroid Build Coastguard Worker {
67*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
68*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 2,
69*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
70*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
71*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
72*9190c2a8SAndroid Build Coastguard Worker },
73*9190c2a8SAndroid Build Coastguard Worker {
74*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
75*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 10,
76*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
77*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
78*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
79*9190c2a8SAndroid Build Coastguard Worker },
80*9190c2a8SAndroid Build Coastguard Worker {
81*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
82*9190c2a8SAndroid Build Coastguard Worker // last data page
83*9190c2a8SAndroid Build Coastguard Worker .pageIndex = lastPage,
84*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
85*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
86*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
87*9190c2a8SAndroid Build Coastguard Worker },
88*9190c2a8SAndroid Build Coastguard Worker {
89*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
90*9190c2a8SAndroid Build Coastguard Worker // first hash page
91*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
92*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
93*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
94*9190c2a8SAndroid Build Coastguard Worker .kind = INCFS_BLOCK_KIND_HASH,
95*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
96*9190c2a8SAndroid Build Coastguard Worker },
97*9190c2a8SAndroid Build Coastguard Worker {
98*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
99*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 2,
100*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
101*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
102*9190c2a8SAndroid Build Coastguard Worker .kind = INCFS_BLOCK_KIND_HASH,
103*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
104*9190c2a8SAndroid Build Coastguard Worker }};
105*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ((int)std::size(blocks), writeBlocks({blocks, std::size(blocks)}));
106*9190c2a8SAndroid Build Coastguard Worker }
107*9190c2a8SAndroid Build Coastguard Worker
writeBlock(int pageIndex)108*9190c2a8SAndroid Build Coastguard Worker void writeBlock(int pageIndex) {
109*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
110*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
111*9190c2a8SAndroid Build Coastguard Worker
112*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
113*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
114*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
115*9190c2a8SAndroid Build Coastguard Worker .pageIndex = pageIndex,
116*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
117*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
118*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
119*9190c2a8SAndroid Build Coastguard Worker };
120*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
121*9190c2a8SAndroid Build Coastguard Worker }
122*9190c2a8SAndroid Build Coastguard Worker
123*9190c2a8SAndroid Build Coastguard Worker template <class ReadStruct>
testWriteBlockAndPageRead()124*9190c2a8SAndroid Build Coastguard Worker void testWriteBlockAndPageRead() {
125*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
126*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control_.logs() >= 0);
127*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
128*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id,
129*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_}));
130*9190c2a8SAndroid Build Coastguard Worker writeBlock(/*pageIndex=*/0);
131*9190c2a8SAndroid Build Coastguard Worker
132*9190c2a8SAndroid Build Coastguard Worker std::thread wait_page_read_thread([&]() {
133*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadStruct> reads;
134*9190c2a8SAndroid Build Coastguard Worker auto res = waitForPageReads(control_, std::chrono::seconds(5), &reads);
135*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(WaitResult::HaveData, res) << (int)res;
136*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(reads.empty());
137*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(&id, &reads[0].id, sizeof(id)));
138*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, int(reads[0].block));
139*9190c2a8SAndroid Build Coastguard Worker if constexpr (std::is_same_v<ReadStruct, ReadInfoWithUid>) {
140*9190c2a8SAndroid Build Coastguard Worker if (features() & Features::v2) {
141*9190c2a8SAndroid Build Coastguard Worker EXPECT_NE(kIncFsNoUid, int(reads[0].uid));
142*9190c2a8SAndroid Build Coastguard Worker } else {
143*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(kIncFsNoUid, int(reads[0].uid));
144*9190c2a8SAndroid Build Coastguard Worker }
145*9190c2a8SAndroid Build Coastguard Worker }
146*9190c2a8SAndroid Build Coastguard Worker });
147*9190c2a8SAndroid Build Coastguard Worker
148*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
149*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd readFd(
150*9190c2a8SAndroid Build Coastguard Worker open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
151*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(readFd >= 0);
152*9190c2a8SAndroid Build Coastguard Worker char buf[INCFS_DATA_FILE_BLOCK_SIZE];
153*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(readFd, buf, sizeof(buf)));
154*9190c2a8SAndroid Build Coastguard Worker wait_page_read_thread.join();
155*9190c2a8SAndroid Build Coastguard Worker }
156*9190c2a8SAndroid Build Coastguard Worker
157*9190c2a8SAndroid Build Coastguard Worker template <class PendingRead>
testWaitForPendingReads()158*9190c2a8SAndroid Build Coastguard Worker void testWaitForPendingReads() {
159*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
160*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
161*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id,
162*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_}));
163*9190c2a8SAndroid Build Coastguard Worker
164*9190c2a8SAndroid Build Coastguard Worker std::thread wait_pending_read_thread([&]() {
165*9190c2a8SAndroid Build Coastguard Worker std::vector<PendingRead> pending_reads;
166*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(WaitResult::HaveData,
167*9190c2a8SAndroid Build Coastguard Worker waitForPendingReads(control_, std::chrono::seconds(10), &pending_reads));
168*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(pending_reads.size(), 0u);
169*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(&id, &pending_reads[0].id, sizeof(id)));
170*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)pending_reads[0].block);
171*9190c2a8SAndroid Build Coastguard Worker if constexpr (std::is_same_v<PendingRead, ReadInfoWithUid>) {
172*9190c2a8SAndroid Build Coastguard Worker if (features() & Features::v2) {
173*9190c2a8SAndroid Build Coastguard Worker EXPECT_NE(kIncFsNoUid, int(pending_reads[0].uid));
174*9190c2a8SAndroid Build Coastguard Worker } else {
175*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(kIncFsNoUid, int(pending_reads[0].uid));
176*9190c2a8SAndroid Build Coastguard Worker }
177*9190c2a8SAndroid Build Coastguard Worker }
178*9190c2a8SAndroid Build Coastguard Worker
179*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
180*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
181*9190c2a8SAndroid Build Coastguard Worker
182*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
183*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
184*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
185*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
186*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
187*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
188*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
189*9190c2a8SAndroid Build Coastguard Worker };
190*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
191*9190c2a8SAndroid Build Coastguard Worker });
192*9190c2a8SAndroid Build Coastguard Worker
193*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
194*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
195*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
196*9190c2a8SAndroid Build Coastguard Worker char buf[INCFS_DATA_FILE_BLOCK_SIZE];
197*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(fd, buf, sizeof(buf)));
198*9190c2a8SAndroid Build Coastguard Worker wait_pending_read_thread.join();
199*9190c2a8SAndroid Build Coastguard Worker }
200*9190c2a8SAndroid Build Coastguard Worker
201*9190c2a8SAndroid Build Coastguard Worker inline static const int test_file_size_ = INCFS_DATA_FILE_BLOCK_SIZE;
202*9190c2a8SAndroid Build Coastguard Worker };
203*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetIncfsFeatures)204*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetIncfsFeatures) {
205*9190c2a8SAndroid Build Coastguard Worker ASSERT_NE(features(), none);
206*9190c2a8SAndroid Build Coastguard Worker }
207*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,FalseIncfsPath)208*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, FalseIncfsPath) {
209*9190c2a8SAndroid Build Coastguard Worker TemporaryDir test_dir;
210*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(isIncFsPath(test_dir.path));
211*9190c2a8SAndroid Build Coastguard Worker }
212*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,TrueIncfsPath)213*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, TrueIncfsPath) {
214*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(isIncFsPath(mount_dir_path_));
215*9190c2a8SAndroid Build Coastguard Worker }
216*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,TrueIncfsPathForBindMount)217*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, TrueIncfsPathForBindMount) {
218*9190c2a8SAndroid Build Coastguard Worker TemporaryDir tmp_dir_to_bind;
219*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
220*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, bindMount(mountPath(test_dir_name_), tmp_dir_to_bind.path));
221*9190c2a8SAndroid Build Coastguard Worker ScopedUnmount su(tmp_dir_to_bind.path);
222*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(isIncFsPath(tmp_dir_to_bind.path));
223*9190c2a8SAndroid Build Coastguard Worker }
224*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,FalseIncfsPathFile)225*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, FalseIncfsPathFile) {
226*9190c2a8SAndroid Build Coastguard Worker TemporaryFile test_file;
227*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(isIncFsFd(test_file.fd));
228*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(isIncFsPath(test_file.path));
229*9190c2a8SAndroid Build Coastguard Worker }
230*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,TrueIncfsPathForBindMountFile)231*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, TrueIncfsPathForBindMountFile) {
232*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
233*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, fileId(1),
234*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_}));
235*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
236*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
237*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
238*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(isIncFsFd(fd.get()));
239*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(isIncFsPath(file_path));
240*9190c2a8SAndroid Build Coastguard Worker }
241*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,Control)242*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, Control) {
243*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control_);
244*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control_, CMD), 0);
245*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control_, PENDING_READS), 0);
246*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control_, LOGS), 0);
247*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ((features() & Features::v2) != 0, IncFs_GetControlFd(control_, BLOCKS_WRITTEN) >= 0);
248*9190c2a8SAndroid Build Coastguard Worker
249*9190c2a8SAndroid Build Coastguard Worker auto fds = control_.releaseFds();
250*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(fds.size(), size_t(4));
251*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(fds[0].get(), 0);
252*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(fds[1].get(), 0);
253*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(fds[2].get(), 0);
254*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control_);
255*9190c2a8SAndroid Build Coastguard Worker EXPECT_LT(IncFs_GetControlFd(control_, CMD), 0);
256*9190c2a8SAndroid Build Coastguard Worker EXPECT_LT(IncFs_GetControlFd(control_, PENDING_READS), 0);
257*9190c2a8SAndroid Build Coastguard Worker EXPECT_LT(IncFs_GetControlFd(control_, LOGS), 0);
258*9190c2a8SAndroid Build Coastguard Worker EXPECT_LT(IncFs_GetControlFd(control_, BLOCKS_WRITTEN), 0);
259*9190c2a8SAndroid Build Coastguard Worker
260*9190c2a8SAndroid Build Coastguard Worker control_.close();
261*9190c2a8SAndroid Build Coastguard Worker EXPECT_FALSE(control_);
262*9190c2a8SAndroid Build Coastguard Worker
263*9190c2a8SAndroid Build Coastguard Worker auto control = IncFs_CreateControl(fds[0].release(), fds[1].release(), fds[2].release(), -1);
264*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control);
265*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control, CMD), 0);
266*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control, PENDING_READS), 0);
267*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(IncFs_GetControlFd(control, LOGS), 0);
268*9190c2a8SAndroid Build Coastguard Worker IncFsFd rawFds[4];
269*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ReleaseControlFds(nullptr, rawFds, 3));
270*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ReleaseControlFds(control, nullptr, 3));
271*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ERANGE, IncFs_ReleaseControlFds(control, rawFds, 2));
272*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, IncFs_ReleaseControlFds(control, rawFds, 4));
273*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(rawFds[0], 0);
274*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(rawFds[1], 0);
275*9190c2a8SAndroid Build Coastguard Worker EXPECT_GE(rawFds[2], 0);
276*9190c2a8SAndroid Build Coastguard Worker ::close(rawFds[0]);
277*9190c2a8SAndroid Build Coastguard Worker ::close(rawFds[1]);
278*9190c2a8SAndroid Build Coastguard Worker ::close(rawFds[2]);
279*9190c2a8SAndroid Build Coastguard Worker if (rawFds[3] >= 0) ::close(rawFds[3]);
280*9190c2a8SAndroid Build Coastguard Worker IncFs_DeleteControl(control);
281*9190c2a8SAndroid Build Coastguard Worker }
282*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,MakeDir)283*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, MakeDir) {
284*9190c2a8SAndroid Build Coastguard Worker const auto dir_path = mountPath(test_dir_name_);
285*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(dir_path));
286*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(makeDir(control_, dir_path), 0);
287*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(dir_path));
288*9190c2a8SAndroid Build Coastguard Worker }
289*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,MakeDirs)290*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, MakeDirs) {
291*9190c2a8SAndroid Build Coastguard Worker const auto dir_path = mountPath(test_dir_name_);
292*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(dir_path));
293*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(makeDirs(control_, dir_path), 0);
294*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(dir_path));
295*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(makeDirs(control_, dir_path), 0);
296*9190c2a8SAndroid Build Coastguard Worker auto nested = dir_path + "/couple/more/nested/levels";
297*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(makeDirs(control_, nested), 0);
298*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(nested));
299*9190c2a8SAndroid Build Coastguard Worker ASSERT_NE(makeDirs(control_, "/"), 0);
300*9190c2a8SAndroid Build Coastguard Worker }
301*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,BindMount)302*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, BindMount) {
303*9190c2a8SAndroid Build Coastguard Worker {
304*9190c2a8SAndroid Build Coastguard Worker TemporaryDir tmp_dir_to_bind;
305*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
306*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, bindMount(mountPath(test_dir_name_), tmp_dir_to_bind.path));
307*9190c2a8SAndroid Build Coastguard Worker ScopedUnmount su(tmp_dir_to_bind.path);
308*9190c2a8SAndroid Build Coastguard Worker const auto test_file = mountPath(test_dir_name_, test_file_name_);
309*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(test_file.c_str())) << "Present: " << test_file;
310*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
311*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, test_file, 0555, fileId(1),
312*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_, .metadata = metadata("md")}));
313*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(test_file.c_str())) << "Missing: " << test_file;
314*9190c2a8SAndroid Build Coastguard Worker const auto file_binded_path = path::join(tmp_dir_to_bind.path, test_file_name_);
315*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(file_binded_path.c_str())) << "Missing: " << file_binded_path;
316*9190c2a8SAndroid Build Coastguard Worker }
317*9190c2a8SAndroid Build Coastguard Worker
318*9190c2a8SAndroid Build Coastguard Worker {
319*9190c2a8SAndroid Build Coastguard Worker // Don't allow binding the root
320*9190c2a8SAndroid Build Coastguard Worker TemporaryDir tmp_dir_to_bind;
321*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(-EINVAL, bindMount(mount_dir_path_, tmp_dir_to_bind.path));
322*9190c2a8SAndroid Build Coastguard Worker }
323*9190c2a8SAndroid Build Coastguard Worker }
324*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,Root)325*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, Root) {
326*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(mount_dir_path_, root(control_)) << "Error: " << errno;
327*9190c2a8SAndroid Build Coastguard Worker }
328*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,RootInvalidControl)329*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, RootInvalidControl) {
330*9190c2a8SAndroid Build Coastguard Worker const TemporaryFile tmp_file;
331*9190c2a8SAndroid Build Coastguard Worker auto control{createControl(tmp_file.fd, -1, -1, -1)};
332*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ("", root(control)) << "Error: " << errno;
333*9190c2a8SAndroid Build Coastguard Worker }
334*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,Open)335*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, Open) {
336*9190c2a8SAndroid Build Coastguard Worker Control control = open(mount_dir_path_);
337*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.cmd() >= 0);
338*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.pendingReads() >= 0);
339*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.logs() >= 0);
340*9190c2a8SAndroid Build Coastguard Worker }
341*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,OpenFail)342*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, OpenFail) {
343*9190c2a8SAndroid Build Coastguard Worker TemporaryDir tmp_dir_to_bind;
344*9190c2a8SAndroid Build Coastguard Worker Control control = open(tmp_dir_to_bind.path);
345*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.cmd() < 0);
346*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.pendingReads() < 0);
347*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(control.logs() < 0);
348*9190c2a8SAndroid Build Coastguard Worker }
349*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,MakeFile)350*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, MakeFile) {
351*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
352*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_dir_name_, test_file_name_);
353*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(file_path));
354*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
355*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, file_path, 0111, fileId(1),
356*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_, .metadata = metadata("md")}));
357*9190c2a8SAndroid Build Coastguard Worker struct stat s;
358*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(file_path.c_str(), &s));
359*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(test_file_size_, (int)s.st_size);
360*9190c2a8SAndroid Build Coastguard Worker }
361*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,MakeFile0)362*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, MakeFile0) {
363*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
364*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_dir_name_, ".info");
365*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(file_path));
366*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
367*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, file_path, 0555, fileId(1),
368*9190c2a8SAndroid Build Coastguard Worker {.size = 0, .metadata = metadata("mdsdfhjasdkfas l;jflaskdjf")}));
369*9190c2a8SAndroid Build Coastguard Worker struct stat s;
370*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(file_path.c_str(), &s));
371*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, (int)s.st_size);
372*9190c2a8SAndroid Build Coastguard Worker }
373*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,MakeMappedFile)374*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, MakeMappedFile) {
375*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
376*9190c2a8SAndroid Build Coastguard Worker
377*9190c2a8SAndroid Build Coastguard Worker constexpr auto file_size = INCFS_DATA_FILE_BLOCK_SIZE * 2;
378*9190c2a8SAndroid Build Coastguard Worker constexpr auto mapped_file_offset = file_size / 2;
379*9190c2a8SAndroid Build Coastguard Worker constexpr auto mapped_file_size = file_size / 3;
380*9190c2a8SAndroid Build Coastguard Worker
381*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_dir_name_, test_file_name_);
382*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(file_path));
383*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
384*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, file_path, 0111, fileId(1),
385*9190c2a8SAndroid Build Coastguard Worker {.size = file_size, .metadata = metadata("md")}));
386*9190c2a8SAndroid Build Coastguard Worker struct stat s = {};
387*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(file_path.c_str(), &s));
388*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(file_size, (int)s.st_size);
389*9190c2a8SAndroid Build Coastguard Worker
390*9190c2a8SAndroid Build Coastguard Worker const auto mapped_file_path = mountPath(test_dir_name_, test_mapped_file_name_);
391*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(mapped_file_path));
392*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
393*9190c2a8SAndroid Build Coastguard Worker makeMappedFile(control_, mapped_file_path, 0111,
394*9190c2a8SAndroid Build Coastguard Worker {.sourceId = fileId(1),
395*9190c2a8SAndroid Build Coastguard Worker .sourceOffset = mapped_file_offset,
396*9190c2a8SAndroid Build Coastguard Worker .size = mapped_file_size}));
397*9190c2a8SAndroid Build Coastguard Worker s = {};
398*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(mapped_file_path.c_str(), &s));
399*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(mapped_file_size, (int)s.st_size);
400*9190c2a8SAndroid Build Coastguard Worker
401*9190c2a8SAndroid Build Coastguard Worker // Check fileId for the source file.
402*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(fileId(1), getFileId(control_, file_path));
403*9190c2a8SAndroid Build Coastguard Worker // Check that there is no fileId for the mapped file.
404*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(kIncFsInvalidFileId, getFileId(control_, mapped_file_path));
405*9190c2a8SAndroid Build Coastguard Worker }
406*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFileId)407*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFileId) {
408*9190c2a8SAndroid Build Coastguard Worker auto id = fileId(1);
409*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
410*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id,
411*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_, .metadata = metadata("md")}));
412*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id, getFileId(control_, mountPath(test_file_name_))) << "errno = " << errno;
413*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(kIncFsInvalidFileId, getFileId(control_, test_file_name_));
414*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(kIncFsInvalidFileId, getFileId(control_, "asdf"));
415*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(kIncFsInvalidFileId, getFileId({}, mountPath(test_file_name_)));
416*9190c2a8SAndroid Build Coastguard Worker }
417*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetMetaData)418*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetMetaData) {
419*9190c2a8SAndroid Build Coastguard Worker const std::string_view md = "abc"sv;
420*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
421*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, fileId(1),
422*9190c2a8SAndroid Build Coastguard Worker {.size = test_file_size_, .metadata = metadata(md)}));
423*9190c2a8SAndroid Build Coastguard Worker {
424*9190c2a8SAndroid Build Coastguard Worker const auto raw_metadata = getMetadata(control_, mountPath(test_file_name_));
425*9190c2a8SAndroid Build Coastguard Worker ASSERT_NE(0u, raw_metadata.size()) << errno;
426*9190c2a8SAndroid Build Coastguard Worker const std::string result(raw_metadata.begin(), raw_metadata.end());
427*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(md, result);
428*9190c2a8SAndroid Build Coastguard Worker }
429*9190c2a8SAndroid Build Coastguard Worker {
430*9190c2a8SAndroid Build Coastguard Worker const auto raw_metadata = getMetadata(control_, fileId(1));
431*9190c2a8SAndroid Build Coastguard Worker ASSERT_NE(0u, raw_metadata.size()) << errno;
432*9190c2a8SAndroid Build Coastguard Worker const std::string result(raw_metadata.begin(), raw_metadata.end());
433*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(md, result);
434*9190c2a8SAndroid Build Coastguard Worker }
435*9190c2a8SAndroid Build Coastguard Worker }
436*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,LinkAndUnlink)437*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, LinkAndUnlink) {
438*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeFile(control_, mountPath(test_file_name_), 0555, fileId(1), {.size = 0}));
439*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
440*9190c2a8SAndroid Build Coastguard Worker const std::string_view test_file = "test1.txt"sv;
441*9190c2a8SAndroid Build Coastguard Worker const auto linked_file_path = mountPath(test_dir_name_, test_file);
442*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(linked_file_path));
443*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, link(control_, mountPath(test_file_name_), linked_file_path));
444*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(exists(linked_file_path));
445*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, unlink(control_, linked_file_path));
446*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(linked_file_path));
447*9190c2a8SAndroid Build Coastguard Worker }
448*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,WriteBlocksAndPageRead)449*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, WriteBlocksAndPageRead) {
450*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(testWriteBlockAndPageRead<ReadInfo>());
451*9190c2a8SAndroid Build Coastguard Worker }
452*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,WriteBlocksAndPageReadWithUid)453*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, WriteBlocksAndPageReadWithUid) {
454*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(testWriteBlockAndPageRead<ReadInfoWithUid>());
455*9190c2a8SAndroid Build Coastguard Worker }
456*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,WaitForPendingReads)457*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, WaitForPendingReads) {
458*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(testWaitForPendingReads<ReadInfo>());
459*9190c2a8SAndroid Build Coastguard Worker }
460*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,WaitForPendingReadsWithUid)461*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, WaitForPendingReadsWithUid) {
462*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(testWaitForPendingReads<ReadInfoWithUid>());
463*9190c2a8SAndroid Build Coastguard Worker }
464*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFilledRangesBad)465*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFilledRangesBad) {
466*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EBADF, IncFs_GetFilledRanges(-1, {}, nullptr));
467*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_GetFilledRanges(0, {}, nullptr));
468*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_GetFilledRangesStartingFrom(0, -1, {}, nullptr));
469*9190c2a8SAndroid Build Coastguard Worker
470*9190c2a8SAndroid Build Coastguard Worker makeFileWithHash(1);
471*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd readFd(
472*9190c2a8SAndroid Build Coastguard Worker open(mountPath(test_file_name_).c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
473*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(readFd.get(), 0);
474*9190c2a8SAndroid Build Coastguard Worker
475*9190c2a8SAndroid Build Coastguard Worker char buffer[1024];
476*9190c2a8SAndroid Build Coastguard Worker IncFsFilledRanges res;
477*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EPERM, IncFs_GetFilledRanges(readFd.get(), {buffer, std::size(buffer)}, &res));
478*9190c2a8SAndroid Build Coastguard Worker }
479*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFilledRanges)480*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFilledRanges) {
481*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
482*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, fileId(1),
483*9190c2a8SAndroid Build Coastguard Worker {.size = 4 * INCFS_DATA_FILE_BLOCK_SIZE}));
484*9190c2a8SAndroid Build Coastguard Worker char buffer[1024];
485*9190c2a8SAndroid Build Coastguard Worker const auto bufferSpan = IncFsSpan{.data = buffer, .size = std::size(buffer)};
486*9190c2a8SAndroid Build Coastguard Worker
487*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
488*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
489*9190c2a8SAndroid Build Coastguard Worker
490*9190c2a8SAndroid Build Coastguard Worker IncFsFilledRanges filledRanges;
491*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), IncFsSpan{}, &filledRanges));
492*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
493*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
494*9190c2a8SAndroid Build Coastguard Worker
495*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
496*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
497*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
498*9190c2a8SAndroid Build Coastguard Worker
499*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 0, bufferSpan, &filledRanges));
500*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
501*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
502*9190c2a8SAndroid Build Coastguard Worker
503*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 1, bufferSpan, &filledRanges));
504*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
505*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
506*9190c2a8SAndroid Build Coastguard Worker
507*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 30, bufferSpan, &filledRanges));
508*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
509*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
510*9190c2a8SAndroid Build Coastguard Worker
511*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsFullyLoaded(fd.get()));
512*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsEverythingFullyLoaded(control_));
513*9190c2a8SAndroid Build Coastguard Worker
514*9190c2a8SAndroid Build Coastguard Worker // write one block
515*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
516*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
517*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
518*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
519*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
520*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
521*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
522*9190c2a8SAndroid Build Coastguard Worker };
523*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
524*9190c2a8SAndroid Build Coastguard Worker
525*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
526*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
527*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
528*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].end);
529*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
530*9190c2a8SAndroid Build Coastguard Worker
531*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 0, bufferSpan, &filledRanges));
532*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
533*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
534*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].end);
535*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
536*9190c2a8SAndroid Build Coastguard Worker
537*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 1, bufferSpan, &filledRanges));
538*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
539*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
540*9190c2a8SAndroid Build Coastguard Worker
541*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 30, bufferSpan, &filledRanges));
542*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
543*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
544*9190c2a8SAndroid Build Coastguard Worker
545*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsFullyLoaded(fd.get()));
546*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsEverythingFullyLoaded(control_));
547*9190c2a8SAndroid Build Coastguard Worker
548*9190c2a8SAndroid Build Coastguard Worker // append one more block next to the first one
549*9190c2a8SAndroid Build Coastguard Worker block.pageIndex = 1;
550*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
551*9190c2a8SAndroid Build Coastguard Worker
552*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
553*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
554*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
555*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
556*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
557*9190c2a8SAndroid Build Coastguard Worker
558*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 0, bufferSpan, &filledRanges));
559*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
560*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
561*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
562*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
563*9190c2a8SAndroid Build Coastguard Worker
564*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 1, bufferSpan, &filledRanges));
565*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
566*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].begin);
567*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
568*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
569*9190c2a8SAndroid Build Coastguard Worker
570*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 30, bufferSpan, &filledRanges));
571*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
572*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
573*9190c2a8SAndroid Build Coastguard Worker
574*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsFullyLoaded(fd.get()));
575*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsEverythingFullyLoaded(control_));
576*9190c2a8SAndroid Build Coastguard Worker
577*9190c2a8SAndroid Build Coastguard Worker // now create a gap between filled blocks
578*9190c2a8SAndroid Build Coastguard Worker block.pageIndex = 3;
579*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
580*9190c2a8SAndroid Build Coastguard Worker
581*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
582*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(2, filledRanges.dataRangesCount);
583*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
584*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
585*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.dataRanges[1].begin);
586*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[1].end);
587*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
588*9190c2a8SAndroid Build Coastguard Worker
589*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 0, bufferSpan, &filledRanges));
590*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(2, filledRanges.dataRangesCount);
591*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
592*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
593*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.dataRanges[1].begin);
594*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[1].end);
595*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
596*9190c2a8SAndroid Build Coastguard Worker
597*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 1, bufferSpan, &filledRanges));
598*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(2, filledRanges.dataRangesCount);
599*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].begin);
600*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].end);
601*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.dataRanges[1].begin);
602*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[1].end);
603*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
604*9190c2a8SAndroid Build Coastguard Worker
605*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 2, bufferSpan, &filledRanges));
606*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
607*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.dataRanges[0].begin);
608*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[0].end);
609*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
610*9190c2a8SAndroid Build Coastguard Worker
611*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 30, bufferSpan, &filledRanges));
612*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
613*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
614*9190c2a8SAndroid Build Coastguard Worker
615*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsFullyLoaded(fd.get()));
616*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENODATA, IncFs_IsEverythingFullyLoaded(control_));
617*9190c2a8SAndroid Build Coastguard Worker
618*9190c2a8SAndroid Build Coastguard Worker // at last fill the whole file and make sure we report it as having a single range
619*9190c2a8SAndroid Build Coastguard Worker block.pageIndex = 2;
620*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
621*9190c2a8SAndroid Build Coastguard Worker
622*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
623*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
624*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
625*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[0].end);
626*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
627*9190c2a8SAndroid Build Coastguard Worker
628*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 0, bufferSpan, &filledRanges));
629*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
630*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
631*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[0].end);
632*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
633*9190c2a8SAndroid Build Coastguard Worker
634*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 1, bufferSpan, &filledRanges));
635*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
636*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].begin);
637*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[0].end);
638*9190c2a8SAndroid Build Coastguard Worker
639*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRangesStartingFrom(fd.get(), 30, bufferSpan, &filledRanges));
640*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRangesCount);
641*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
642*9190c2a8SAndroid Build Coastguard Worker
643*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_IsFullyLoaded(fd.get()));
644*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_IsEverythingFullyLoaded(control_));
645*9190c2a8SAndroid Build Coastguard Worker }
646*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFilledRangesSmallBuffer)647*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFilledRangesSmallBuffer) {
648*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
649*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, fileId(1),
650*9190c2a8SAndroid Build Coastguard Worker {.size = 5 * INCFS_DATA_FILE_BLOCK_SIZE}));
651*9190c2a8SAndroid Build Coastguard Worker char buffer[1024];
652*9190c2a8SAndroid Build Coastguard Worker
653*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
654*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
655*9190c2a8SAndroid Build Coastguard Worker
656*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
657*9190c2a8SAndroid Build Coastguard Worker DataBlock blocks[] = {DataBlock{
658*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
659*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
660*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
661*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
662*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
663*9190c2a8SAndroid Build Coastguard Worker },
664*9190c2a8SAndroid Build Coastguard Worker DataBlock{
665*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
666*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 2,
667*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
668*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
669*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
670*9190c2a8SAndroid Build Coastguard Worker },
671*9190c2a8SAndroid Build Coastguard Worker DataBlock{
672*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
673*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 4,
674*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
675*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
676*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
677*9190c2a8SAndroid Build Coastguard Worker }};
678*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(3, writeBlocks({blocks, 3}));
679*9190c2a8SAndroid Build Coastguard Worker
680*9190c2a8SAndroid Build Coastguard Worker IncFsSpan bufferSpan = {.data = buffer, .size = sizeof(IncFsBlockRange)};
681*9190c2a8SAndroid Build Coastguard Worker IncFsFilledRanges filledRanges;
682*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ERANGE, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
683*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
684*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.dataRanges[0].begin);
685*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.dataRanges[0].end);
686*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
687*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.endIndex);
688*9190c2a8SAndroid Build Coastguard Worker
689*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ERANGE,
690*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFilledRangesStartingFrom(fd.get(), filledRanges.endIndex, bufferSpan,
691*9190c2a8SAndroid Build Coastguard Worker &filledRanges));
692*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
693*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.dataRanges[0].begin);
694*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.dataRanges[0].end);
695*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
696*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.endIndex);
697*9190c2a8SAndroid Build Coastguard Worker
698*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
699*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFilledRangesStartingFrom(fd.get(), filledRanges.endIndex, bufferSpan,
700*9190c2a8SAndroid Build Coastguard Worker &filledRanges));
701*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, filledRanges.dataRangesCount);
702*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, filledRanges.dataRanges[0].begin);
703*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(5, filledRanges.dataRanges[0].end);
704*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRangesCount);
705*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(5, filledRanges.endIndex);
706*9190c2a8SAndroid Build Coastguard Worker }
707*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFilledRangesWithHashes)708*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFilledRangesWithHashes) {
709*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(1);
710*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
711*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(writeTestRanges(1, size));
712*9190c2a8SAndroid Build Coastguard Worker
713*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
714*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
715*9190c2a8SAndroid Build Coastguard Worker
716*9190c2a8SAndroid Build Coastguard Worker char buffer[1024];
717*9190c2a8SAndroid Build Coastguard Worker IncFsSpan bufferSpan = {.data = buffer, .size = sizeof(buffer)};
718*9190c2a8SAndroid Build Coastguard Worker IncFsFilledRanges filledRanges;
719*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFilledRanges(fd.get(), bufferSpan, &filledRanges));
720*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(3, filledRanges.dataRangesCount);
721*9190c2a8SAndroid Build Coastguard Worker auto lastPage = sizeToPages(size) - 1;
722*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(lastPage, filledRanges.dataRanges[2].begin);
723*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(lastPage + 1, filledRanges.dataRanges[2].end);
724*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.hashRangesCount);
725*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, filledRanges.hashRanges[0].begin);
726*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, filledRanges.hashRanges[0].end);
727*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, filledRanges.hashRanges[1].begin);
728*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, filledRanges.hashRanges[1].end);
729*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(sizeToPages(size) + 3, filledRanges.endIndex);
730*9190c2a8SAndroid Build Coastguard Worker }
731*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetFilledRangesCpp)732*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetFilledRangesCpp) {
733*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(1);
734*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
735*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(writeTestRanges(1, size));
736*9190c2a8SAndroid Build Coastguard Worker
737*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
738*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
739*9190c2a8SAndroid Build Coastguard Worker
740*9190c2a8SAndroid Build Coastguard Worker // simply get all ranges
741*9190c2a8SAndroid Build Coastguard Worker auto [res, ranges] = getFilledRanges(fd.get());
742*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(res, 0);
743*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(5), ranges.totalSize());
744*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(3), ranges.dataRanges().size());
745*9190c2a8SAndroid Build Coastguard Worker auto lastPage = sizeToPages(size) - 1;
746*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(lastPage, ranges.dataRanges()[2].begin);
747*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges.dataRanges()[2].size());
748*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(2), ranges.hashRanges().size());
749*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, ranges.hashRanges()[0].begin);
750*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges.hashRanges()[0].size());
751*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, ranges.hashRanges()[1].begin);
752*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges.hashRanges()[1].size());
753*9190c2a8SAndroid Build Coastguard Worker
754*9190c2a8SAndroid Build Coastguard Worker // now check how buffer size limiting works.
755*9190c2a8SAndroid Build Coastguard Worker FilledRanges::RangeBuffer buf(ranges.totalSize() - 1);
756*9190c2a8SAndroid Build Coastguard Worker auto [res2, ranges2] = getFilledRanges(fd.get(), std::move(buf));
757*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(-ERANGE, res2);
758*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(ranges.totalSize() - 1, ranges2.totalSize());
759*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(3), ranges2.dataRanges().size());
760*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(1), ranges2.hashRanges().size());
761*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, ranges2.hashRanges()[0].begin);
762*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges2.hashRanges()[0].size());
763*9190c2a8SAndroid Build Coastguard Worker
764*9190c2a8SAndroid Build Coastguard Worker // and now check the resumption from the previous result
765*9190c2a8SAndroid Build Coastguard Worker auto [res3, ranges3] = getFilledRanges(fd.get(), std::move(ranges2));
766*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, res3);
767*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(ranges.totalSize(), ranges3.totalSize());
768*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(3), ranges3.dataRanges().size());
769*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(size_t(2), ranges3.hashRanges().size());
770*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, ranges3.hashRanges()[0].begin);
771*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges3.hashRanges()[0].size());
772*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, ranges3.hashRanges()[1].begin);
773*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), ranges3.hashRanges()[1].size());
774*9190c2a8SAndroid Build Coastguard Worker
775*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(LoadingState::MissingBlocks, isFullyLoaded(fd.get()));
776*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(LoadingState::MissingBlocks, isEverythingFullyLoaded(control_));
777*9190c2a8SAndroid Build Coastguard Worker
778*9190c2a8SAndroid Build Coastguard Worker {
779*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
780*9190c2a8SAndroid Build Coastguard Worker DataBlock block = {.fileFd = fd.get(),
781*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 1,
782*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
783*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
784*9190c2a8SAndroid Build Coastguard Worker .data = data.data()};
785*9190c2a8SAndroid Build Coastguard Worker for (auto i = 0; i != sizeToPages(size); ++i) {
786*9190c2a8SAndroid Build Coastguard Worker block.pageIndex = i;
787*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
788*9190c2a8SAndroid Build Coastguard Worker }
789*9190c2a8SAndroid Build Coastguard Worker block.kind = INCFS_BLOCK_KIND_HASH;
790*9190c2a8SAndroid Build Coastguard Worker for (auto i = 0; i != 3; ++i) {
791*9190c2a8SAndroid Build Coastguard Worker block.pageIndex = i;
792*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
793*9190c2a8SAndroid Build Coastguard Worker }
794*9190c2a8SAndroid Build Coastguard Worker }
795*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(LoadingState::Full, isFullyLoaded(fd.get()));
796*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(LoadingState::Full, isEverythingFullyLoaded(control_));
797*9190c2a8SAndroid Build Coastguard Worker }
798*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,BlocksWritten)799*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, BlocksWritten) {
800*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
801*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
802*9190c2a8SAndroid Build Coastguard Worker return;
803*9190c2a8SAndroid Build Coastguard Worker }
804*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
805*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
806*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id, {.size = test_file_size_}));
807*9190c2a8SAndroid Build Coastguard Worker
808*9190c2a8SAndroid Build Coastguard Worker IncFsSize blocksWritten = 0;
809*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, IncFs_WaitForFsWrittenBlocksChange(control_, 0, &blocksWritten));
810*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, blocksWritten);
811*9190c2a8SAndroid Build Coastguard Worker
812*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
813*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
814*9190c2a8SAndroid Build Coastguard Worker
815*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
816*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
817*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
818*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
819*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
820*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
821*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
822*9190c2a8SAndroid Build Coastguard Worker };
823*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
824*9190c2a8SAndroid Build Coastguard Worker
825*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, IncFs_WaitForFsWrittenBlocksChange(control_, 0, &blocksWritten));
826*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, blocksWritten);
827*9190c2a8SAndroid Build Coastguard Worker }
828*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,Timeouts)829*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, Timeouts) {
830*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
831*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
832*9190c2a8SAndroid Build Coastguard Worker return;
833*9190c2a8SAndroid Build Coastguard Worker }
834*9190c2a8SAndroid Build Coastguard Worker
835*9190c2a8SAndroid Build Coastguard Worker IncFsUidReadTimeouts timeouts[2] = {{1, 1000, 2000, 3000}, {2, 1000, 3000, 4000}};
836*9190c2a8SAndroid Build Coastguard Worker
837*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_SetUidReadTimeouts(control_, timeouts, std::size(timeouts)));
838*9190c2a8SAndroid Build Coastguard Worker
839*9190c2a8SAndroid Build Coastguard Worker IncFsUidReadTimeouts outTimeouts[3];
840*9190c2a8SAndroid Build Coastguard Worker
841*9190c2a8SAndroid Build Coastguard Worker size_t outSize = 1;
842*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-E2BIG, IncFs_GetUidReadTimeouts(control_, outTimeouts, &outSize));
843*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(2), outSize);
844*9190c2a8SAndroid Build Coastguard Worker
845*9190c2a8SAndroid Build Coastguard Worker outSize = 3;
846*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetUidReadTimeouts(control_, outTimeouts, &outSize));
847*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(2), outSize);
848*9190c2a8SAndroid Build Coastguard Worker
849*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(timeouts, outTimeouts, 2 * sizeof(timeouts[0])));
850*9190c2a8SAndroid Build Coastguard Worker }
851*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,CompletionNoFiles)852*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, CompletionNoFiles) {
853*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
854*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
855*9190c2a8SAndroid Build Coastguard Worker return;
856*9190c2a8SAndroid Build Coastguard Worker }
857*9190c2a8SAndroid Build Coastguard Worker
858*9190c2a8SAndroid Build Coastguard Worker size_t count = 0;
859*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ListIncompleteFiles(control_, nullptr, &count));
860*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(0), count);
861*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_WaitForLoadingComplete(control_, 0));
862*9190c2a8SAndroid Build Coastguard Worker }
863*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,CompletionOneFile)864*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, CompletionOneFile) {
865*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
866*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
867*9190c2a8SAndroid Build Coastguard Worker return;
868*9190c2a8SAndroid Build Coastguard Worker }
869*9190c2a8SAndroid Build Coastguard Worker
870*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
871*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
872*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id, {.size = test_file_size_}));
873*9190c2a8SAndroid Build Coastguard Worker
874*9190c2a8SAndroid Build Coastguard Worker size_t count = 0;
875*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-E2BIG, IncFs_ListIncompleteFiles(control_, nullptr, &count));
876*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), count);
877*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ETIMEDOUT, IncFs_WaitForLoadingComplete(control_, 0));
878*9190c2a8SAndroid Build Coastguard Worker
879*9190c2a8SAndroid Build Coastguard Worker IncFsFileId ids[2];
880*9190c2a8SAndroid Build Coastguard Worker count = 2;
881*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ListIncompleteFiles(control_, ids, &count));
882*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), count);
883*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id, ids[0]);
884*9190c2a8SAndroid Build Coastguard Worker
885*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, id);
886*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
887*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
888*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
889*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
890*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
891*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
892*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
893*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
894*9190c2a8SAndroid Build Coastguard Worker };
895*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
896*9190c2a8SAndroid Build Coastguard Worker
897*9190c2a8SAndroid Build Coastguard Worker count = 2;
898*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ListIncompleteFiles(control_, ids, &count));
899*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(0), count);
900*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_WaitForLoadingComplete(control_, 0));
901*9190c2a8SAndroid Build Coastguard Worker }
902*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,CompletionMultiple)903*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, CompletionMultiple) {
904*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
905*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
906*9190c2a8SAndroid Build Coastguard Worker return;
907*9190c2a8SAndroid Build Coastguard Worker }
908*9190c2a8SAndroid Build Coastguard Worker
909*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
910*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
911*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id, {.size = test_file_size_}));
912*9190c2a8SAndroid Build Coastguard Worker
913*9190c2a8SAndroid Build Coastguard Worker size_t count = 0;
914*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-E2BIG, IncFs_ListIncompleteFiles(control_, nullptr, &count));
915*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), count);
916*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ETIMEDOUT, IncFs_WaitForLoadingComplete(control_, 0));
917*9190c2a8SAndroid Build Coastguard Worker
918*9190c2a8SAndroid Build Coastguard Worker // fill the existing file but add another one
919*9190c2a8SAndroid Build Coastguard Worker const auto id2 = fileId(2);
920*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeFile(control_, mountPath("test2"), 0555, id2, {.size = test_file_size_}));
921*9190c2a8SAndroid Build Coastguard Worker
922*9190c2a8SAndroid Build Coastguard Worker IncFsFileId ids[2];
923*9190c2a8SAndroid Build Coastguard Worker count = 2;
924*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ListIncompleteFiles(control_, ids, &count));
925*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(2), count);
926*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id, ids[0]);
927*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id2, ids[1]);
928*9190c2a8SAndroid Build Coastguard Worker
929*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, id);
930*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
931*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
932*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
933*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
934*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
935*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
936*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
937*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
938*9190c2a8SAndroid Build Coastguard Worker };
939*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
940*9190c2a8SAndroid Build Coastguard Worker
941*9190c2a8SAndroid Build Coastguard Worker count = 2;
942*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ListIncompleteFiles(control_, ids, &count));
943*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(size_t(1), count);
944*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id2, ids[0]);
945*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ETIMEDOUT, IncFs_WaitForLoadingComplete(control_, 0));
946*9190c2a8SAndroid Build Coastguard Worker }
947*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,CompletionWait)948*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, CompletionWait) {
949*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
950*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
951*9190c2a8SAndroid Build Coastguard Worker return;
952*9190c2a8SAndroid Build Coastguard Worker }
953*9190c2a8SAndroid Build Coastguard Worker
954*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
955*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath("test1"), 0555, fileId(1),
956*9190c2a8SAndroid Build Coastguard Worker {.size = INCFS_DATA_FILE_BLOCK_SIZE}));
957*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
958*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath("test2"), 0555, fileId(2),
959*9190c2a8SAndroid Build Coastguard Worker {.size = INCFS_DATA_FILE_BLOCK_SIZE}));
960*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
961*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath("test3"), 0555, fileId(3),
962*9190c2a8SAndroid Build Coastguard Worker {.size = INCFS_DATA_FILE_BLOCK_SIZE}));
963*9190c2a8SAndroid Build Coastguard Worker
964*9190c2a8SAndroid Build Coastguard Worker std::atomic<int> res = -1;
965*9190c2a8SAndroid Build Coastguard Worker auto waiter = std::thread([&] { res = IncFs_WaitForLoadingComplete(control_, 5 * 1000); });
966*9190c2a8SAndroid Build Coastguard Worker
967*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
968*9190c2a8SAndroid Build Coastguard Worker
969*9190c2a8SAndroid Build Coastguard Worker {
970*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
971*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
972*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
973*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
974*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
975*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
976*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
977*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
978*9190c2a8SAndroid Build Coastguard Worker };
979*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
980*9190c2a8SAndroid Build Coastguard Worker }
981*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(res == -1);
982*9190c2a8SAndroid Build Coastguard Worker
983*9190c2a8SAndroid Build Coastguard Worker {
984*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(3));
985*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
986*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
987*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
988*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
989*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
990*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
991*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
992*9190c2a8SAndroid Build Coastguard Worker };
993*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
994*9190c2a8SAndroid Build Coastguard Worker }
995*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(res == -1);
996*9190c2a8SAndroid Build Coastguard Worker
997*9190c2a8SAndroid Build Coastguard Worker {
998*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(2));
999*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1000*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
1001*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
1002*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
1003*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1004*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
1005*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
1006*9190c2a8SAndroid Build Coastguard Worker };
1007*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
1008*9190c2a8SAndroid Build Coastguard Worker }
1009*9190c2a8SAndroid Build Coastguard Worker
1010*9190c2a8SAndroid Build Coastguard Worker waiter.join();
1011*9190c2a8SAndroid Build Coastguard Worker
1012*9190c2a8SAndroid Build Coastguard Worker auto listIncomplete = [&] {
1013*9190c2a8SAndroid Build Coastguard Worker IncFsFileId ids[3];
1014*9190c2a8SAndroid Build Coastguard Worker size_t count = 3;
1015*9190c2a8SAndroid Build Coastguard Worker if (IncFs_ListIncompleteFiles(control_, ids, &count) != 0) {
1016*9190c2a8SAndroid Build Coastguard Worker return "error listing incomplete files"s;
1017*9190c2a8SAndroid Build Coastguard Worker }
1018*9190c2a8SAndroid Build Coastguard Worker auto res = ab::StringPrintf("[%d]", int(count));
1019*9190c2a8SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) {
1020*9190c2a8SAndroid Build Coastguard Worker ab::StringAppendF(&res, " %s", toString(ids[i]).c_str());
1021*9190c2a8SAndroid Build Coastguard Worker }
1022*9190c2a8SAndroid Build Coastguard Worker return res;
1023*9190c2a8SAndroid Build Coastguard Worker };
1024*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, res) << "Incomplete files: " << listIncomplete();
1025*9190c2a8SAndroid Build Coastguard Worker }
1026*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetBlockCounts)1027*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetBlockCounts) {
1028*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1029*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1030*9190c2a8SAndroid Build Coastguard Worker return;
1031*9190c2a8SAndroid Build Coastguard Worker }
1032*9190c2a8SAndroid Build Coastguard Worker
1033*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
1034*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
1035*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id,
1036*9190c2a8SAndroid Build Coastguard Worker {.size = 20 * INCFS_DATA_FILE_BLOCK_SIZE + 3}));
1037*9190c2a8SAndroid Build Coastguard Worker
1038*9190c2a8SAndroid Build Coastguard Worker IncFsBlockCounts counts = {};
1039*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1040*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFileBlockCountByPath(control_, mountPath(test_file_name_).c_str(), &counts));
1041*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(21, counts.totalDataBlocks);
1042*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledDataBlocks);
1043*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.totalHashBlocks);
1044*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledHashBlocks);
1045*9190c2a8SAndroid Build Coastguard Worker
1046*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFileBlockCountById(control_, id, &counts));
1047*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(21, counts.totalDataBlocks);
1048*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledDataBlocks);
1049*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.totalHashBlocks);
1050*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledHashBlocks);
1051*9190c2a8SAndroid Build Coastguard Worker
1052*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, id);
1053*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1054*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
1055*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
1056*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
1057*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 3,
1058*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1059*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
1060*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
1061*9190c2a8SAndroid Build Coastguard Worker };
1062*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
1063*9190c2a8SAndroid Build Coastguard Worker
1064*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1065*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFileBlockCountByPath(control_, mountPath(test_file_name_).c_str(), &counts));
1066*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(21, counts.totalDataBlocks);
1067*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, counts.filledDataBlocks);
1068*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.totalHashBlocks);
1069*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledHashBlocks);
1070*9190c2a8SAndroid Build Coastguard Worker
1071*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetFileBlockCountById(control_, id, &counts));
1072*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(21, counts.totalDataBlocks);
1073*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, counts.filledDataBlocks);
1074*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.totalHashBlocks);
1075*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledHashBlocks);
1076*9190c2a8SAndroid Build Coastguard Worker }
1077*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,GetBlockCountsHash)1078*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, GetBlockCountsHash) {
1079*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1080*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1081*9190c2a8SAndroid Build Coastguard Worker return;
1082*9190c2a8SAndroid Build Coastguard Worker }
1083*9190c2a8SAndroid Build Coastguard Worker
1084*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(1);
1085*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
1086*9190c2a8SAndroid Build Coastguard Worker
1087*9190c2a8SAndroid Build Coastguard Worker IncFsBlockCounts counts = {};
1088*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1089*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFileBlockCountByPath(control_, mountPath(test_file_name_).c_str(), &counts));
1090*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(sizeToPages(size), counts.totalDataBlocks);
1091*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledDataBlocks);
1092*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, counts.totalHashBlocks);
1093*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, counts.filledHashBlocks);
1094*9190c2a8SAndroid Build Coastguard Worker
1095*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(writeTestRanges(1, size));
1096*9190c2a8SAndroid Build Coastguard Worker
1097*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1098*9190c2a8SAndroid Build Coastguard Worker IncFs_GetFileBlockCountByPath(control_, mountPath(test_file_name_).c_str(), &counts));
1099*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(sizeToPages(size), counts.totalDataBlocks);
1100*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(4, counts.filledDataBlocks);
1101*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(3, counts.totalHashBlocks);
1102*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, counts.filledHashBlocks);
1103*9190c2a8SAndroid Build Coastguard Worker }
1104*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,ReserveSpace)1105*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, ReserveSpace) {
1106*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(1);
1107*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
1108*9190c2a8SAndroid Build Coastguard Worker
1109*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENOENT,
1110*9190c2a8SAndroid Build Coastguard Worker IncFs_ReserveSpaceByPath(control_, mountPath("1"s += test_file_name_).c_str(), size));
1111*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceByPath(control_, mountPath(test_file_name_).c_str(), size));
1112*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceByPath(control_, mountPath(test_file_name_).c_str(), 2 * size));
1113*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceByPath(control_, mountPath(test_file_name_).c_str(), 2 * size));
1114*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1115*9190c2a8SAndroid Build Coastguard Worker IncFs_ReserveSpaceByPath(control_, mountPath(test_file_name_).c_str(),
1116*9190c2a8SAndroid Build Coastguard Worker kTrimReservedSpace));
1117*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0,
1118*9190c2a8SAndroid Build Coastguard Worker IncFs_ReserveSpaceByPath(control_, mountPath(test_file_name_).c_str(),
1119*9190c2a8SAndroid Build Coastguard Worker kTrimReservedSpace));
1120*9190c2a8SAndroid Build Coastguard Worker
1121*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ENOENT, IncFs_ReserveSpaceById(control_, fileId(2), size));
1122*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceById(control_, fileId(1), size));
1123*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceById(control_, fileId(1), 2 * size));
1124*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceById(control_, fileId(1), 2 * size));
1125*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceById(control_, fileId(1), kTrimReservedSpace));
1126*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ReserveSpaceById(control_, fileId(1), kTrimReservedSpace));
1127*9190c2a8SAndroid Build Coastguard Worker }
1128*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,ForEachFile)1129*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, ForEachFile) {
1130*9190c2a8SAndroid Build Coastguard Worker const auto incompleteSupported = (features() & Features::v2) != 0;
1131*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ForEachFile(nullptr, nullptr, nullptr));
1132*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ForEachIncompleteFile(nullptr, nullptr, nullptr));
1133*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ForEachFile(control_, nullptr, nullptr));
1134*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EINVAL, IncFs_ForEachIncompleteFile(control_, nullptr, nullptr));
1135*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ForEachFile(control_, nullptr, [](auto, auto, auto) { return true; }));
1136*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(incompleteSupported ? 0 : -ENOTSUP,
1137*9190c2a8SAndroid Build Coastguard Worker IncFs_ForEachIncompleteFile(control_, nullptr,
1138*9190c2a8SAndroid Build Coastguard Worker [](auto, auto, auto) { return true; }));
1139*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_ForEachFile(control_, this, [](auto, auto, auto) { return true; }));
1140*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(incompleteSupported ? 0 : -ENOTSUP,
1141*9190c2a8SAndroid Build Coastguard Worker IncFs_ForEachIncompleteFile(control_, this, [](auto, auto, auto) { return true; }));
1142*9190c2a8SAndroid Build Coastguard Worker
1143*9190c2a8SAndroid Build Coastguard Worker int res = makeFile(control_, mountPath("incomplete.txt"), 0555, fileId(1),
1144*9190c2a8SAndroid Build Coastguard Worker {.metadata = metadata("md")});
1145*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(res, 0);
1146*9190c2a8SAndroid Build Coastguard Worker
1147*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, IncFs_ForEachFile(control_, this, [](auto, auto context, auto id) {
1148*9190c2a8SAndroid Build Coastguard Worker auto self = (IncFsTest*)context;
1149*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(self->fileId(1), id);
1150*9190c2a8SAndroid Build Coastguard Worker return true;
1151*9190c2a8SAndroid Build Coastguard Worker }));
1152*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(incompleteSupported ? 0 : -ENOTSUP,
1153*9190c2a8SAndroid Build Coastguard Worker IncFs_ForEachIncompleteFile(control_, this, [](auto, auto, auto) { return true; }));
1154*9190c2a8SAndroid Build Coastguard Worker
1155*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(2);
1156*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
1157*9190c2a8SAndroid Build Coastguard Worker
1158*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, IncFs_ForEachFile(control_, this, [](auto, auto context, auto id) {
1159*9190c2a8SAndroid Build Coastguard Worker auto self = (IncFsTest*)context;
1160*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE(id == self->fileId(1) || id == self->fileId(2));
1161*9190c2a8SAndroid Build Coastguard Worker return false;
1162*9190c2a8SAndroid Build Coastguard Worker }));
1163*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(2, IncFs_ForEachFile(control_, this, [](auto, auto context, auto id) {
1164*9190c2a8SAndroid Build Coastguard Worker auto self = (IncFsTest*)context;
1165*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE(id == self->fileId(1) || id == self->fileId(2));
1166*9190c2a8SAndroid Build Coastguard Worker return true;
1167*9190c2a8SAndroid Build Coastguard Worker }));
1168*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(incompleteSupported ? 1 : -ENOTSUP,
1169*9190c2a8SAndroid Build Coastguard Worker IncFs_ForEachIncompleteFile(control_, this, [](auto, auto context, auto id) {
1170*9190c2a8SAndroid Build Coastguard Worker auto self = (IncFsTest*)context;
1171*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(self->fileId(2), id);
1172*9190c2a8SAndroid Build Coastguard Worker return true;
1173*9190c2a8SAndroid Build Coastguard Worker }));
1174*9190c2a8SAndroid Build Coastguard Worker }
1175*9190c2a8SAndroid Build Coastguard Worker
TEST(CStrWrapperTest,EmptyStringView)1176*9190c2a8SAndroid Build Coastguard Worker TEST(CStrWrapperTest, EmptyStringView) {
1177*9190c2a8SAndroid Build Coastguard Worker ASSERT_STREQ("", details::c_str({}).get());
1178*9190c2a8SAndroid Build Coastguard Worker ASSERT_STREQ("", details::c_str({nullptr, 0}).get());
1179*9190c2a8SAndroid Build Coastguard Worker }
1180*9190c2a8SAndroid Build Coastguard Worker
1181*9190c2a8SAndroid Build Coastguard Worker class IncFsGetMetricsTest : public IncFsTestBase {
1182*9190c2a8SAndroid Build Coastguard Worker protected:
getReadTimeout()1183*9190c2a8SAndroid Build Coastguard Worker int32_t getReadTimeout() override { return 100 /* 0.1 second */; }
1184*9190c2a8SAndroid Build Coastguard Worker };
1185*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsGetMetricsTest,MetricsWithNoEvents)1186*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsGetMetricsTest, MetricsWithNoEvents) {
1187*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1188*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1189*9190c2a8SAndroid Build Coastguard Worker return;
1190*9190c2a8SAndroid Build Coastguard Worker }
1191*9190c2a8SAndroid Build Coastguard Worker IncFsLastReadError lastReadError = {.id = fileId(-1),
1192*9190c2a8SAndroid Build Coastguard Worker .timestampUs = static_cast<uint64_t>(-1),
1193*9190c2a8SAndroid Build Coastguard Worker .block = static_cast<IncFsBlockIndex>(-1),
1194*9190c2a8SAndroid Build Coastguard Worker .errorNo = static_cast<uint32_t>(-1),
1195*9190c2a8SAndroid Build Coastguard Worker .uid = static_cast<IncFsUid>(-1)};
1196*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetLastReadError(control_, &lastReadError));
1197*9190c2a8SAndroid Build Coastguard Worker // All fields should be zero
1198*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(FileId{}, lastReadError.id);
1199*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.timestampUs);
1200*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.block);
1201*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.errorNo);
1202*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.uid);
1203*9190c2a8SAndroid Build Coastguard Worker
1204*9190c2a8SAndroid Build Coastguard Worker IncFsMetrics incfsMetrics = {10, 10, 10, 10, 10, 10, 10, 10, 10};
1205*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetMetrics(metrics_key_.c_str(), &incfsMetrics));
1206*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMin);
1207*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMinUs);
1208*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPending);
1209*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPendingUs);
1210*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedHashVerification);
1211*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
1212*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedTimedOut);
1213*9190c2a8SAndroid Build Coastguard Worker }
1214*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsGetMetricsTest,MetricsWithReadsTimeOut)1215*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsGetMetricsTest, MetricsWithReadsTimeOut) {
1216*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1217*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1218*9190c2a8SAndroid Build Coastguard Worker return;
1219*9190c2a8SAndroid Build Coastguard Worker }
1220*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
1221*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
1222*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, mountPath(test_file_name_), 0555, id,
1223*9190c2a8SAndroid Build Coastguard Worker {.size = INCFS_DATA_FILE_BLOCK_SIZE}));
1224*9190c2a8SAndroid Build Coastguard Worker
1225*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
1226*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
1227*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1228*9190c2a8SAndroid Build Coastguard Worker // Read should timeout immediately
1229*9190c2a8SAndroid Build Coastguard Worker char buf[INCFS_DATA_FILE_BLOCK_SIZE];
1230*9190c2a8SAndroid Build Coastguard Worker EXPECT_FALSE(android::base::ReadFully(fd, buf, sizeof(buf)));
1231*9190c2a8SAndroid Build Coastguard Worker IncFsLastReadError lastReadError = {.id = fileId(-1),
1232*9190c2a8SAndroid Build Coastguard Worker .timestampUs = static_cast<uint64_t>(-1),
1233*9190c2a8SAndroid Build Coastguard Worker .block = static_cast<IncFsBlockIndex>(-1),
1234*9190c2a8SAndroid Build Coastguard Worker .errorNo = static_cast<uint32_t>(-1),
1235*9190c2a8SAndroid Build Coastguard Worker .uid = static_cast<IncFsUid>(-1)};
1236*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetLastReadError(control_, &lastReadError));
1237*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(id, lastReadError.id);
1238*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE(lastReadError.timestampUs > 0);
1239*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.block);
1240*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-ETIME, (int)lastReadError.errorNo);
1241*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ((int)getuid(), (int)lastReadError.uid);
1242*9190c2a8SAndroid Build Coastguard Worker
1243*9190c2a8SAndroid Build Coastguard Worker IncFsMetrics incfsMetrics = {10, 10, 10, 10, 10, 10, 10, 10, 10};
1244*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetMetrics(metrics_key_.c_str(), &incfsMetrics));
1245*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMin);
1246*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMinUs);
1247*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPending);
1248*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPendingUs);
1249*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedHashVerification);
1250*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
1251*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, (int)incfsMetrics.readsFailedTimedOut);
1252*9190c2a8SAndroid Build Coastguard Worker }
1253*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsGetMetricsTest,MetricsWithHashFailure)1254*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsGetMetricsTest, MetricsWithHashFailure) {
1255*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1256*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1257*9190c2a8SAndroid Build Coastguard Worker return;
1258*9190c2a8SAndroid Build Coastguard Worker }
1259*9190c2a8SAndroid Build Coastguard Worker auto size = makeFileWithHash(1);
1260*9190c2a8SAndroid Build Coastguard Worker ASSERT_GT(size, 0);
1261*9190c2a8SAndroid Build Coastguard Worker // Make data and hash mismatch
1262*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
1263*9190c2a8SAndroid Build Coastguard Worker char data[INCFS_DATA_FILE_BLOCK_SIZE]{static_cast<char>(-1)};
1264*9190c2a8SAndroid Build Coastguard Worker char hashData[INCFS_DATA_FILE_BLOCK_SIZE]{};
1265*9190c2a8SAndroid Build Coastguard Worker auto wfd = openForSpecialOps(control_, id);
1266*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(wfd.get(), 0);
1267*9190c2a8SAndroid Build Coastguard Worker DataBlock blocks[] = {{
1268*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
1269*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
1270*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1271*9190c2a8SAndroid Build Coastguard Worker .dataSize = INCFS_DATA_FILE_BLOCK_SIZE,
1272*9190c2a8SAndroid Build Coastguard Worker .data = data,
1273*9190c2a8SAndroid Build Coastguard Worker },
1274*9190c2a8SAndroid Build Coastguard Worker {
1275*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
1276*9190c2a8SAndroid Build Coastguard Worker // first hash page
1277*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
1278*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1279*9190c2a8SAndroid Build Coastguard Worker .dataSize = INCFS_DATA_FILE_BLOCK_SIZE,
1280*9190c2a8SAndroid Build Coastguard Worker .kind = INCFS_BLOCK_KIND_HASH,
1281*9190c2a8SAndroid Build Coastguard Worker .data = hashData,
1282*9190c2a8SAndroid Build Coastguard Worker },
1283*9190c2a8SAndroid Build Coastguard Worker {
1284*9190c2a8SAndroid Build Coastguard Worker .fileFd = wfd.get(),
1285*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 2,
1286*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1287*9190c2a8SAndroid Build Coastguard Worker .dataSize = INCFS_DATA_FILE_BLOCK_SIZE,
1288*9190c2a8SAndroid Build Coastguard Worker .kind = INCFS_BLOCK_KIND_HASH,
1289*9190c2a8SAndroid Build Coastguard Worker .data = hashData,
1290*9190c2a8SAndroid Build Coastguard Worker }};
1291*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ((int)std::size(blocks), writeBlocks({blocks, std::size(blocks)}));
1292*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
1293*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
1294*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1295*9190c2a8SAndroid Build Coastguard Worker // Read should fail at reading the first block due to hash failure
1296*9190c2a8SAndroid Build Coastguard Worker char buf[INCFS_DATA_FILE_BLOCK_SIZE];
1297*9190c2a8SAndroid Build Coastguard Worker EXPECT_FALSE(android::base::ReadFully(fd, buf, sizeof(buf)));
1298*9190c2a8SAndroid Build Coastguard Worker IncFsLastReadError lastReadError = {.id = fileId(-1),
1299*9190c2a8SAndroid Build Coastguard Worker .timestampUs = static_cast<uint64_t>(-1),
1300*9190c2a8SAndroid Build Coastguard Worker .block = static_cast<IncFsBlockIndex>(-1),
1301*9190c2a8SAndroid Build Coastguard Worker .errorNo = static_cast<uint32_t>(-1),
1302*9190c2a8SAndroid Build Coastguard Worker .uid = static_cast<IncFsUid>(-1)};
1303*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetLastReadError(control_, &lastReadError));
1304*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, std::strcmp(lastReadError.id.data, id.data));
1305*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE(lastReadError.timestampUs > 0);
1306*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.block);
1307*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(-EBADMSG, (int)lastReadError.errorNo);
1308*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ((int)getuid(), (int)lastReadError.uid);
1309*9190c2a8SAndroid Build Coastguard Worker
1310*9190c2a8SAndroid Build Coastguard Worker IncFsMetrics incfsMetrics = {10, 10, 10, 10, 10, 10, 10, 10, 10};
1311*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetMetrics(metrics_key_.c_str(), &incfsMetrics));
1312*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMin);
1313*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMinUs);
1314*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPending);
1315*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPendingUs);
1316*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, (int)incfsMetrics.readsFailedHashVerification);
1317*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
1318*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedTimedOut);
1319*9190c2a8SAndroid Build Coastguard Worker }
1320*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsGetMetricsTest,MetricsWithReadsDelayed)1321*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsGetMetricsTest, MetricsWithReadsDelayed) {
1322*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1323*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1324*9190c2a8SAndroid Build Coastguard Worker return;
1325*9190c2a8SAndroid Build Coastguard Worker }
1326*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
1327*9190c2a8SAndroid Build Coastguard Worker int testFileSize = INCFS_DATA_FILE_BLOCK_SIZE;
1328*9190c2a8SAndroid Build Coastguard Worker int waitBeforeWriteUs = 10000;
1329*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeFile(control_, mountPath(test_file_name_), 0555, id, {.size = testFileSize}));
1330*9190c2a8SAndroid Build Coastguard Worker std::thread wait_before_write_thread([&]() {
1331*9190c2a8SAndroid Build Coastguard Worker std::vector<ReadInfoWithUid> pending_reads;
1332*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(WaitResult::HaveData,
1333*9190c2a8SAndroid Build Coastguard Worker waitForPendingReads(control_, std::chrono::seconds(1), &pending_reads));
1334*9190c2a8SAndroid Build Coastguard Worker // Additional wait is needed for the kernel jiffies counter to increment
1335*9190c2a8SAndroid Build Coastguard Worker usleep(waitBeforeWriteUs);
1336*9190c2a8SAndroid Build Coastguard Worker auto fd = openForSpecialOps(control_, fileId(1));
1337*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1338*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
1339*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
1340*9190c2a8SAndroid Build Coastguard Worker .fileFd = fd.get(),
1341*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
1342*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1343*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
1344*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
1345*9190c2a8SAndroid Build Coastguard Worker };
1346*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
1347*9190c2a8SAndroid Build Coastguard Worker });
1348*9190c2a8SAndroid Build Coastguard Worker
1349*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
1350*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
1351*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1352*9190c2a8SAndroid Build Coastguard Worker char buf[testFileSize];
1353*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE(android::base::ReadFully(fd, buf, sizeof(buf)));
1354*9190c2a8SAndroid Build Coastguard Worker wait_before_write_thread.join();
1355*9190c2a8SAndroid Build Coastguard Worker
1356*9190c2a8SAndroid Build Coastguard Worker IncFsLastReadError lastReadError = {.id = fileId(-1), 1, 1, 1, 1};
1357*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetLastReadError(control_, &lastReadError));
1358*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(FileId{}, lastReadError.id);
1359*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.timestampUs);
1360*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.block);
1361*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.errorNo);
1362*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.uid);
1363*9190c2a8SAndroid Build Coastguard Worker
1364*9190c2a8SAndroid Build Coastguard Worker IncFsMetrics incfsMetrics = {10, 10, 10, 10, 10, 10, 10, 10, 10};
1365*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetMetrics(metrics_key_.c_str(), &incfsMetrics));
1366*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMin);
1367*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedMinUs);
1368*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, (int)incfsMetrics.readsDelayedPending);
1369*9190c2a8SAndroid Build Coastguard Worker EXPECT_TRUE((int)incfsMetrics.readsDelayedPendingUs > 0);
1370*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedHashVerification);
1371*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
1372*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedTimedOut);
1373*9190c2a8SAndroid Build Coastguard Worker }
1374*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsGetMetricsTest,MetricsWithReadsDelayedPerUidTimeout)1375*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsGetMetricsTest, MetricsWithReadsDelayedPerUidTimeout) {
1376*9190c2a8SAndroid Build Coastguard Worker if (!(features() & Features::v2)) {
1377*9190c2a8SAndroid Build Coastguard Worker GTEST_SKIP() << "test not supported: IncFS is too old";
1378*9190c2a8SAndroid Build Coastguard Worker return;
1379*9190c2a8SAndroid Build Coastguard Worker }
1380*9190c2a8SAndroid Build Coastguard Worker const auto id = fileId(1);
1381*9190c2a8SAndroid Build Coastguard Worker int testFileSize = INCFS_DATA_FILE_BLOCK_SIZE;
1382*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeFile(control_, mountPath(test_file_name_), 0555, id, {.size = testFileSize}));
1383*9190c2a8SAndroid Build Coastguard Worker
1384*9190c2a8SAndroid Build Coastguard Worker auto fdToFill = openForSpecialOps(control_, fileId(1));
1385*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fdToFill.get(), 0);
1386*9190c2a8SAndroid Build Coastguard Worker std::vector<char> data(INCFS_DATA_FILE_BLOCK_SIZE);
1387*9190c2a8SAndroid Build Coastguard Worker auto block = DataBlock{
1388*9190c2a8SAndroid Build Coastguard Worker .fileFd = fdToFill.get(),
1389*9190c2a8SAndroid Build Coastguard Worker .pageIndex = 0,
1390*9190c2a8SAndroid Build Coastguard Worker .compression = INCFS_COMPRESSION_KIND_NONE,
1391*9190c2a8SAndroid Build Coastguard Worker .dataSize = (uint32_t)data.size(),
1392*9190c2a8SAndroid Build Coastguard Worker .data = data.data(),
1393*9190c2a8SAndroid Build Coastguard Worker };
1394*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(1, writeBlocks({&block, 1}));
1395*9190c2a8SAndroid Build Coastguard Worker
1396*9190c2a8SAndroid Build Coastguard Worker // Set per-uid read timeout then read
1397*9190c2a8SAndroid Build Coastguard Worker uint32_t readTimeoutUs = 1000000;
1398*9190c2a8SAndroid Build Coastguard Worker IncFsUidReadTimeouts timeouts[1] = {
1399*9190c2a8SAndroid Build Coastguard Worker {static_cast<IncFsUid>(getuid()), readTimeoutUs, readTimeoutUs, readTimeoutUs}};
1400*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, IncFs_SetUidReadTimeouts(control_, timeouts, std::size(timeouts)));
1401*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_file_name_);
1402*9190c2a8SAndroid Build Coastguard Worker const android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
1403*9190c2a8SAndroid Build Coastguard Worker char buf[testFileSize];
1404*9190c2a8SAndroid Build Coastguard Worker ASSERT_GE(fd.get(), 0);
1405*9190c2a8SAndroid Build Coastguard Worker ASSERT_TRUE(android::base::ReadFully(fd, buf, sizeof(buf)));
1406*9190c2a8SAndroid Build Coastguard Worker
1407*9190c2a8SAndroid Build Coastguard Worker IncFsLastReadError lastReadError = {.id = fileId(-1), 1, 1, 1, 1};
1408*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetLastReadError(control_, &lastReadError));
1409*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(FileId{}, lastReadError.id);
1410*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.timestampUs);
1411*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.block);
1412*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.errorNo);
1413*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)lastReadError.uid);
1414*9190c2a8SAndroid Build Coastguard Worker
1415*9190c2a8SAndroid Build Coastguard Worker IncFsMetrics incfsMetrics = {10, 10, 10, 10, 10, 10, 10, 10, 10};
1416*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, IncFs_GetMetrics(metrics_key_.c_str(), &incfsMetrics));
1417*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(1, (int)incfsMetrics.readsDelayedMin);
1418*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(readTimeoutUs, (uint32_t)incfsMetrics.readsDelayedMinUs);
1419*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPending);
1420*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsDelayedPendingUs);
1421*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedHashVerification);
1422*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedOther);
1423*9190c2a8SAndroid Build Coastguard Worker EXPECT_EQ(0, (int)incfsMetrics.readsFailedTimedOut);
1424*9190c2a8SAndroid Build Coastguard Worker }
1425*9190c2a8SAndroid Build Coastguard Worker
operator ==(const BlockCounts & lhs,const BlockCounts & rhs)1426*9190c2a8SAndroid Build Coastguard Worker inline bool operator==(const BlockCounts& lhs, const BlockCounts& rhs) {
1427*9190c2a8SAndroid Build Coastguard Worker return lhs.totalDataBlocks == rhs.totalDataBlocks &&
1428*9190c2a8SAndroid Build Coastguard Worker lhs.filledDataBlocks == rhs.filledDataBlocks &&
1429*9190c2a8SAndroid Build Coastguard Worker lhs.totalHashBlocks == rhs.totalHashBlocks &&
1430*9190c2a8SAndroid Build Coastguard Worker lhs.filledHashBlocks == rhs.filledHashBlocks;
1431*9190c2a8SAndroid Build Coastguard Worker }
1432*9190c2a8SAndroid Build Coastguard Worker
TEST_F(IncFsTest,LoadingProgress)1433*9190c2a8SAndroid Build Coastguard Worker TEST_F(IncFsTest, LoadingProgress) {
1434*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, makeDir(control_, mountPath(test_dir_name_)));
1435*9190c2a8SAndroid Build Coastguard Worker
1436*9190c2a8SAndroid Build Coastguard Worker constexpr auto file_size = INCFS_DATA_FILE_BLOCK_SIZE * 2;
1437*9190c2a8SAndroid Build Coastguard Worker constexpr auto mapped_file_offset = file_size / 2;
1438*9190c2a8SAndroid Build Coastguard Worker constexpr auto mapped_file_size = file_size / 3;
1439*9190c2a8SAndroid Build Coastguard Worker
1440*9190c2a8SAndroid Build Coastguard Worker const auto file_id = fileId(1);
1441*9190c2a8SAndroid Build Coastguard Worker
1442*9190c2a8SAndroid Build Coastguard Worker const auto file_path = mountPath(test_dir_name_, test_file_name_);
1443*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(file_path));
1444*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
1445*9190c2a8SAndroid Build Coastguard Worker makeFile(control_, file_path, 0111, file_id,
1446*9190c2a8SAndroid Build Coastguard Worker {.size = file_size, .metadata = metadata("md")}));
1447*9190c2a8SAndroid Build Coastguard Worker struct stat s = {};
1448*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(file_path.c_str(), &s));
1449*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(file_size, (int)s.st_size);
1450*9190c2a8SAndroid Build Coastguard Worker
1451*9190c2a8SAndroid Build Coastguard Worker const auto mapped_file_path = mountPath(test_dir_name_, test_mapped_file_name_);
1452*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(exists(mapped_file_path));
1453*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0,
1454*9190c2a8SAndroid Build Coastguard Worker makeMappedFile(control_, mapped_file_path, 0111,
1455*9190c2a8SAndroid Build Coastguard Worker {.sourceId = file_id,
1456*9190c2a8SAndroid Build Coastguard Worker .sourceOffset = mapped_file_offset,
1457*9190c2a8SAndroid Build Coastguard Worker .size = mapped_file_size}));
1458*9190c2a8SAndroid Build Coastguard Worker s = {};
1459*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(0, stat(mapped_file_path.c_str(), &s));
1460*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(mapped_file_size, (int)s.st_size);
1461*9190c2a8SAndroid Build Coastguard Worker
1462*9190c2a8SAndroid Build Coastguard Worker // Check fully loaded first.
1463*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_path));
1464*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_id));
1465*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
1466*9190c2a8SAndroid Build Coastguard Worker
1467*9190c2a8SAndroid Build Coastguard Worker // Next is loading progress.
1468*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(BlockCounts{.totalDataBlocks = 2}, *getBlockCount(control_, file_path));
1469*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(BlockCounts{.totalDataBlocks = 2}, *getBlockCount(control_, file_id));
1470*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
1471*9190c2a8SAndroid Build Coastguard Worker
1472*9190c2a8SAndroid Build Coastguard Worker // Now write a page #0.
1473*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(writeBlock(0));
1474*9190c2a8SAndroid Build Coastguard Worker
1475*9190c2a8SAndroid Build Coastguard Worker // Recheck everything.
1476*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_path));
1477*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::MissingBlocks, isFullyLoaded(control_, file_id));
1478*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
1479*9190c2a8SAndroid Build Coastguard Worker
1480*9190c2a8SAndroid Build Coastguard Worker BlockCounts onePage{.totalDataBlocks = 2, .filledDataBlocks = 1};
1481*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(onePage, *getBlockCount(control_, file_path));
1482*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(onePage, *getBlockCount(control_, file_id));
1483*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
1484*9190c2a8SAndroid Build Coastguard Worker
1485*9190c2a8SAndroid Build Coastguard Worker // Now write a page #1.
1486*9190c2a8SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(writeBlock(1));
1487*9190c2a8SAndroid Build Coastguard Worker
1488*9190c2a8SAndroid Build Coastguard Worker // Check for fully loaded.
1489*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::Full, isFullyLoaded(control_, file_path));
1490*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(LoadingState::Full, isFullyLoaded(control_, file_id));
1491*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ((LoadingState)-ENOTSUP, isFullyLoaded(control_, mapped_file_path));
1492*9190c2a8SAndroid Build Coastguard Worker
1493*9190c2a8SAndroid Build Coastguard Worker BlockCounts twoPages{.totalDataBlocks = 2, .filledDataBlocks = 2};
1494*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(twoPages, *getBlockCount(control_, file_path));
1495*9190c2a8SAndroid Build Coastguard Worker ASSERT_EQ(twoPages, *getBlockCount(control_, file_id));
1496*9190c2a8SAndroid Build Coastguard Worker ASSERT_FALSE(getBlockCount(control_, mapped_file_path));
1497*9190c2a8SAndroid Build Coastguard Worker }
1498