1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <liblp/builder.h>
20 #include <storage_literals/storage_literals.h>
21
22 #include "liblp_test.h"
23 #include "utility.h"
24
25 using namespace std;
26 using namespace android::storage_literals;
27 using namespace android::fs_mgr;
28 using namespace android::fs_mgr::testing;
29 using ::testing::_;
30 using ::testing::AnyNumber;
31 using ::testing::ElementsAre;
32 using ::testing::NiceMock;
33 using ::testing::Return;
34
35 class Environment : public ::testing::Environment {
36 public:
SetUp()37 void SetUp() override { ResetMockPropertyFetcher(); }
38 };
39
main(int argc,char ** argv)40 int main(int argc, char** argv) {
41 ::testing::InitGoogleTest(&argc, argv);
42 return RUN_ALL_TESTS();
43 }
44
45 class BuilderTest : public LiblpTest {};
46
TEST_F(BuilderTest,BuildBasic)47 TEST_F(BuilderTest, BuildBasic) {
48 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
49 ASSERT_NE(builder, nullptr);
50
51 Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
52 ASSERT_NE(partition, nullptr);
53 EXPECT_EQ(partition->name(), "system");
54 EXPECT_EQ(partition->attributes(), LP_PARTITION_ATTR_READONLY);
55 EXPECT_EQ(partition->size(), 0);
56 EXPECT_EQ(builder->FindPartition("system"), partition);
57
58 builder->RemovePartition("system");
59 EXPECT_EQ(builder->FindPartition("system"), nullptr);
60 }
61
TEST_F(BuilderTest,ResizePartition)62 TEST_F(BuilderTest, ResizePartition) {
63 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
64 ASSERT_NE(builder, nullptr);
65
66 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
67 ASSERT_NE(system, nullptr);
68 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
69 EXPECT_EQ(system->size(), 65536);
70 ASSERT_EQ(system->extents().size(), 1);
71
72 LinearExtent* extent = system->extents()[0]->AsLinearExtent();
73 ASSERT_NE(extent, nullptr);
74 EXPECT_EQ(extent->num_sectors(), 65536 / LP_SECTOR_SIZE);
75 // The first logical sector will be:
76 // (LP_PARTITION_RESERVED_BYTES + 4096*2 + 1024*4) / 512
77 // Or, in terms of sectors (reserved + geometry + metadata):
78 // (8 + 16 + 8) = 32
79 EXPECT_EQ(extent->physical_sector(), 32);
80
81 // Test resizing to the same size.
82 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
83 EXPECT_EQ(system->size(), 65536);
84 EXPECT_EQ(system->extents().size(), 1);
85 EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE);
86 // Test resizing to a smaller size.
87 EXPECT_EQ(builder->ResizePartition(system, 0), true);
88 EXPECT_EQ(system->size(), 0);
89 EXPECT_EQ(system->extents().size(), 0);
90 // Test resizing to a greater size.
91 builder->ResizePartition(system, 131072);
92 EXPECT_EQ(system->size(), 131072);
93 EXPECT_EQ(system->extents().size(), 1);
94 EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE);
95 // Test resizing again, that the extents are merged together.
96 builder->ResizePartition(system, 1024 * 256);
97 EXPECT_EQ(system->size(), 1024 * 256);
98 EXPECT_EQ(system->extents().size(), 1);
99 EXPECT_EQ(system->extents()[0]->num_sectors(), (1024 * 256) / LP_SECTOR_SIZE);
100
101 // Test shrinking within the same extent.
102 builder->ResizePartition(system, 32768);
103 EXPECT_EQ(system->size(), 32768);
104 EXPECT_EQ(system->extents().size(), 1);
105 extent = system->extents()[0]->AsLinearExtent();
106 ASSERT_NE(extent, nullptr);
107 EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
108 EXPECT_EQ(extent->physical_sector(), 32);
109
110 auto exported = builder->Export();
111 ASSERT_NE(exported, nullptr);
112 ASSERT_EQ(FindPartition(*exported.get(), "not found"), nullptr);
113 auto entry = FindPartition(*exported.get(), "system");
114 ASSERT_NE(entry, nullptr);
115 ASSERT_EQ(GetPartitionSize(*exported.get(), *entry), 32768);
116
117 // Test shrinking to 0.
118 builder->ResizePartition(system, 0);
119 EXPECT_EQ(system->size(), 0);
120 EXPECT_EQ(system->extents().size(), 0);
121 }
122
TEST_F(BuilderTest,PartitionAlignment)123 TEST_F(BuilderTest, PartitionAlignment) {
124 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
125 ASSERT_NE(builder, nullptr);
126
127 // Test that we align up to one sector.
128 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
129 ASSERT_NE(system, nullptr);
130 EXPECT_EQ(builder->ResizePartition(system, 10000), true);
131 EXPECT_EQ(system->size(), 12288);
132 EXPECT_EQ(system->extents().size(), 1);
133
134 builder->ResizePartition(system, 7000);
135 EXPECT_EQ(system->size(), 8192);
136 EXPECT_EQ(system->extents().size(), 1);
137 }
138
TEST_F(BuilderTest,DiskAlignment)139 TEST_F(BuilderTest, DiskAlignment) {
140 static const uint64_t kDiskSize = 1000000;
141 static const uint32_t kMetadataSize = 1024;
142 static const uint32_t kMetadataSlots = 2;
143
144 unique_ptr<MetadataBuilder> builder =
145 MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
146 ASSERT_EQ(builder, nullptr);
147 }
148
TEST_F(BuilderTest,MetadataAlignment)149 TEST_F(BuilderTest, MetadataAlignment) {
150 // Make sure metadata sizes get aligned up.
151 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1000, 2);
152 ASSERT_NE(builder, nullptr);
153 unique_ptr<LpMetadata> exported = builder->Export();
154 ASSERT_NE(exported, nullptr);
155 EXPECT_EQ(exported->geometry.metadata_max_size, 1024);
156 }
157
TEST_F(BuilderTest,InternalAlignment)158 TEST_F(BuilderTest, InternalAlignment) {
159 // Test the metadata fitting within alignment.
160 BlockDeviceInfo device_info("super", 1024 * 1024, 768 * 1024, 0, 4096);
161 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
162 ASSERT_NE(builder, nullptr);
163 unique_ptr<LpMetadata> exported = builder->Export();
164 ASSERT_NE(exported, nullptr);
165 auto super_device = GetMetadataSuperBlockDevice(*exported.get());
166 ASSERT_NE(super_device, nullptr);
167 EXPECT_EQ(super_device->first_logical_sector, 1536);
168
169 // Test a large alignment offset thrown in.
170 device_info.alignment_offset = 753664;
171 builder = MetadataBuilder::New(device_info, 1024, 2);
172 ASSERT_NE(builder, nullptr);
173 exported = builder->Export();
174 ASSERT_NE(exported, nullptr);
175 super_device = GetMetadataSuperBlockDevice(*exported.get());
176 ASSERT_NE(super_device, nullptr);
177 EXPECT_EQ(super_device->first_logical_sector, 1536);
178
179 // Alignment offset without alignment is ignored.
180 device_info.alignment = 0;
181 builder = MetadataBuilder::New(device_info, 1024, 2);
182 ASSERT_NE(builder, nullptr);
183
184 // Test a small alignment with an alignment offset.
185 device_info.alignment = 12 * 1024;
186 device_info.alignment_offset = 3 * 1024;
187 builder = MetadataBuilder::New(device_info, 16 * 1024, 2);
188 ASSERT_NE(builder, nullptr);
189 exported = builder->Export();
190 ASSERT_NE(exported, nullptr);
191 super_device = GetMetadataSuperBlockDevice(*exported.get());
192 ASSERT_NE(super_device, nullptr);
193 EXPECT_EQ(super_device->first_logical_sector, 168);
194
195 // Test a small alignment with no alignment offset.
196 device_info.alignment = 11 * 1024;
197 builder = MetadataBuilder::New(device_info, 16 * 1024, 2);
198 ASSERT_NE(builder, nullptr);
199 exported = builder->Export();
200 ASSERT_NE(exported, nullptr);
201 super_device = GetMetadataSuperBlockDevice(*exported.get());
202 ASSERT_NE(super_device, nullptr);
203 EXPECT_EQ(super_device->first_logical_sector, 154);
204 }
205
TEST_F(BuilderTest,InternalPartitionAlignment)206 TEST_F(BuilderTest, InternalPartitionAlignment) {
207 BlockDeviceInfo device_info("super", 512 * 1024 * 1024, 768 * 1024, 753664, 4096);
208 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
209
210 Partition* a = builder->AddPartition("a", 0);
211 ASSERT_NE(a, nullptr);
212 Partition* b = builder->AddPartition("b", 0);
213 ASSERT_NE(b, nullptr);
214
215 // Add a bunch of small extents to each, interleaving.
216 for (size_t i = 0; i < 10; i++) {
217 ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096));
218 ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096));
219 }
220 EXPECT_EQ(a->size(), 40960);
221 EXPECT_EQ(b->size(), 40960);
222
223 unique_ptr<LpMetadata> exported = builder->Export();
224 ASSERT_NE(exported, nullptr);
225
226 // Check that each starting sector is aligned.
227 for (const auto& extent : exported->extents) {
228 ASSERT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
229 EXPECT_EQ(extent.num_sectors, 80);
230
231 uint64_t aligned_lba;
232 uint64_t lba = extent.target_data * LP_SECTOR_SIZE;
233 ASSERT_TRUE(AlignTo(lba, device_info.alignment, &aligned_lba));
234 EXPECT_EQ(lba, aligned_lba);
235 }
236
237 // Check one extent.
238 EXPECT_EQ(exported->extents.back().target_data, 3072);
239 }
240
TEST_F(BuilderTest,UseAllDiskSpace)241 TEST_F(BuilderTest, UseAllDiskSpace) {
242 static constexpr uint64_t total = 1024 * 1024;
243 static constexpr uint64_t metadata = 1024;
244 static constexpr uint64_t slots = 2;
245 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(total, metadata, slots);
246 // We reserve a geometry block (4KB) plus space for each copy of the
247 // maximum size of a metadata blob. Then, we double that space since
248 // we store a backup copy of everything.
249 static constexpr uint64_t geometry = 4 * 1024;
250 static constexpr uint64_t allocatable =
251 total - (metadata * slots + geometry) * 2 - LP_PARTITION_RESERVED_BYTES;
252 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
253 EXPECT_EQ(builder->UsedSpace(), 0);
254
255 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
256 ASSERT_NE(system, nullptr);
257 EXPECT_EQ(builder->ResizePartition(system, allocatable), true);
258 EXPECT_EQ(system->size(), allocatable);
259 EXPECT_EQ(builder->UsedSpace(), allocatable);
260 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
261 EXPECT_EQ(builder->ResizePartition(system, allocatable + 1), false);
262 EXPECT_EQ(system->size(), allocatable);
263 EXPECT_EQ(builder->UsedSpace(), allocatable);
264 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
265 }
266
TEST_F(BuilderTest,BuildComplex)267 TEST_F(BuilderTest, BuildComplex) {
268 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
269
270 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
271 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
272 ASSERT_NE(system, nullptr);
273 ASSERT_NE(vendor, nullptr);
274 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
275 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
276 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
277 EXPECT_EQ(system->size(), 98304);
278 EXPECT_EQ(vendor->size(), 32768);
279
280 // We now expect to have 3 extents total: 2 for system, 1 for vendor, since
281 // our allocation strategy is greedy/first-fit.
282 ASSERT_EQ(system->extents().size(), 2);
283 ASSERT_EQ(vendor->extents().size(), 1);
284
285 LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
286 LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
287 LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
288 ASSERT_NE(system1, nullptr);
289 ASSERT_NE(system2, nullptr);
290 ASSERT_NE(vendor1, nullptr);
291 EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
292 EXPECT_EQ(system1->physical_sector(), 32);
293 EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
294 EXPECT_EQ(system2->physical_sector(), 224);
295 EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
296 EXPECT_EQ(vendor1->physical_sector(), 160);
297 EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector());
298 EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector());
299 }
300
TEST_F(BuilderTest,AddInvalidPartition)301 TEST_F(BuilderTest, AddInvalidPartition) {
302 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
303
304 Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
305 ASSERT_NE(partition, nullptr);
306
307 // Duplicate name.
308 partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
309 EXPECT_EQ(partition, nullptr);
310
311 // Empty name.
312 partition = builder->AddPartition("", LP_PARTITION_ATTR_READONLY);
313 EXPECT_EQ(partition, nullptr);
314 }
315
TEST_F(BuilderTest,BuilderExport)316 TEST_F(BuilderTest, BuilderExport) {
317 static const uint64_t kDiskSize = 1024 * 1024;
318 static const uint32_t kMetadataSize = 1024;
319 static const uint32_t kMetadataSlots = 2;
320 unique_ptr<MetadataBuilder> builder =
321 MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
322
323 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
324 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
325 ASSERT_NE(system, nullptr);
326 ASSERT_NE(vendor, nullptr);
327 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
328 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
329 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
330
331 unique_ptr<LpMetadata> exported = builder->Export();
332 EXPECT_NE(exported, nullptr);
333
334 auto super_device = GetMetadataSuperBlockDevice(*exported.get());
335 ASSERT_NE(super_device, nullptr);
336
337 // Verify geometry. Some details of this may change if we change the
338 // metadata structures. So in addition to checking the exact values, we
339 // also check that they are internally consistent after.
340 const LpMetadataGeometry& geometry = exported->geometry;
341 EXPECT_EQ(geometry.magic, LP_METADATA_GEOMETRY_MAGIC);
342 EXPECT_EQ(geometry.struct_size, sizeof(geometry));
343 EXPECT_EQ(geometry.metadata_max_size, 1024);
344 EXPECT_EQ(geometry.metadata_slot_count, 2);
345 EXPECT_EQ(super_device->first_logical_sector, 32);
346
347 static const size_t kMetadataSpace =
348 ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
349 EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
350
351 // Verify header.
352 const LpMetadataHeader& header = exported->header;
353 EXPECT_EQ(header.magic, LP_METADATA_HEADER_MAGIC);
354 EXPECT_EQ(header.major_version, LP_METADATA_MAJOR_VERSION);
355 EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION_MIN);
356 EXPECT_EQ(header.header_size, sizeof(LpMetadataHeaderV1_0));
357
358 ASSERT_EQ(exported->partitions.size(), 2);
359 ASSERT_EQ(exported->extents.size(), 3);
360
361 for (const auto& partition : exported->partitions) {
362 Partition* original = builder->FindPartition(GetPartitionName(partition));
363 ASSERT_NE(original, nullptr);
364 for (size_t i = 0; i < partition.num_extents; i++) {
365 const auto& extent = exported->extents[partition.first_extent_index + i];
366 LinearExtent* original_extent = original->extents()[i]->AsLinearExtent();
367 EXPECT_EQ(extent.num_sectors, original_extent->num_sectors());
368 EXPECT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
369 EXPECT_EQ(extent.target_data, original_extent->physical_sector());
370 }
371 EXPECT_EQ(partition.attributes, original->attributes());
372 }
373 }
374
TEST_F(BuilderTest,BuilderImport)375 TEST_F(BuilderTest, BuilderImport) {
376 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
377
378 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
379 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
380 ASSERT_NE(system, nullptr);
381 ASSERT_NE(vendor, nullptr);
382 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
383 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
384 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
385
386 unique_ptr<LpMetadata> exported = builder->Export();
387 ASSERT_NE(exported, nullptr);
388
389 builder = MetadataBuilder::New(*exported.get());
390 ASSERT_NE(builder, nullptr);
391 system = builder->FindPartition("system");
392 ASSERT_NE(system, nullptr);
393 vendor = builder->FindPartition("vendor");
394 ASSERT_NE(vendor, nullptr);
395
396 EXPECT_EQ(system->size(), 98304);
397 ASSERT_EQ(system->extents().size(), 2);
398 EXPECT_EQ(system->attributes(), LP_PARTITION_ATTR_READONLY);
399 EXPECT_EQ(vendor->size(), 32768);
400 ASSERT_EQ(vendor->extents().size(), 1);
401 EXPECT_EQ(vendor->attributes(), LP_PARTITION_ATTR_READONLY);
402
403 LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
404 LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
405 LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
406 EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
407 EXPECT_EQ(system1->physical_sector(), 32);
408 EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
409 EXPECT_EQ(system2->physical_sector(), 224);
410 EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
411 }
412
TEST_F(BuilderTest,ExportNameTooLong)413 TEST_F(BuilderTest, ExportNameTooLong) {
414 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
415
416 std::string name = "abcdefghijklmnopqrstuvwxyz0123456789";
417 Partition* system = builder->AddPartition(name + name, LP_PARTITION_ATTR_READONLY);
418 EXPECT_NE(system, nullptr);
419
420 unique_ptr<LpMetadata> exported = builder->Export();
421 EXPECT_EQ(exported, nullptr);
422 }
423
TEST_F(BuilderTest,MetadataTooLarge)424 TEST_F(BuilderTest, MetadataTooLarge) {
425 static const size_t kDiskSize = 128 * 1024;
426 static const size_t kMetadataSize = 64 * 1024;
427
428 // No space to store metadata + geometry.
429 BlockDeviceInfo device_info("super", kDiskSize, 0, 0, 4096);
430 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
431 EXPECT_EQ(builder, nullptr);
432
433 // No space to store metadata + geometry + one free sector.
434 device_info.size += LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2);
435 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
436 EXPECT_EQ(builder, nullptr);
437
438 // Space for metadata + geometry + one free block.
439 device_info.size += device_info.logical_block_size;
440 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
441 EXPECT_NE(builder, nullptr);
442
443 // Test with alignment.
444 device_info.alignment = 131072;
445 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
446 EXPECT_EQ(builder, nullptr);
447 }
448
TEST_F(BuilderTest,UpdateBlockDeviceInfo)449 TEST_F(BuilderTest, UpdateBlockDeviceInfo) {
450 BlockDeviceInfo device_info("super", 1024 * 1024, 4096, 1024, 4096);
451 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
452 ASSERT_NE(builder, nullptr);
453
454 BlockDeviceInfo new_info;
455 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
456
457 EXPECT_EQ(new_info.size, device_info.size);
458 EXPECT_EQ(new_info.alignment, device_info.alignment);
459 EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
460 EXPECT_EQ(new_info.logical_block_size, device_info.logical_block_size);
461
462 device_info.alignment = 0;
463 device_info.alignment_offset = 2048;
464 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
465 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
466 EXPECT_EQ(new_info.alignment, 4096);
467 EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
468
469 device_info.alignment = 8192;
470 device_info.alignment_offset = 0;
471 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
472 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
473 EXPECT_EQ(new_info.alignment, 8192);
474 EXPECT_EQ(new_info.alignment_offset, 2048);
475
476 new_info.size += 4096;
477 ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
478 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
479 EXPECT_EQ(new_info.size, 1024 * 1024);
480
481 new_info.logical_block_size = 512;
482 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", new_info));
483 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
484 EXPECT_EQ(new_info.logical_block_size, 4096);
485
486 new_info.logical_block_size = 7;
487 ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
488 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
489 EXPECT_EQ(new_info.logical_block_size, 4096);
490 }
491
TEST_F(BuilderTest,InvalidBlockSize)492 TEST_F(BuilderTest, InvalidBlockSize) {
493 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 513);
494 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
495 EXPECT_EQ(builder, nullptr);
496 }
497
TEST_F(BuilderTest,AlignedExtentSize)498 TEST_F(BuilderTest, AlignedExtentSize) {
499 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
500 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
501 ASSERT_NE(builder, nullptr);
502
503 Partition* partition = builder->AddPartition("system", 0);
504 ASSERT_NE(partition, nullptr);
505 ASSERT_TRUE(builder->ResizePartition(partition, 512));
506 EXPECT_EQ(partition->size(), 4096);
507 }
508
TEST_F(BuilderTest,AlignedFreeSpace)509 TEST_F(BuilderTest, AlignedFreeSpace) {
510 // Only one sector free - at least one block is required.
511 BlockDeviceInfo device_info("super", 10240, 0, 0, 4096);
512 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
513 ASSERT_EQ(builder, nullptr);
514 }
515
TEST_F(BuilderTest,HasDefaultGroup)516 TEST_F(BuilderTest, HasDefaultGroup) {
517 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
518 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
519 ASSERT_NE(builder, nullptr);
520
521 EXPECT_FALSE(builder->AddGroup("default", 0));
522 }
523
TEST_F(BuilderTest,GroupSizeLimits)524 TEST_F(BuilderTest, GroupSizeLimits) {
525 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
526 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
527 ASSERT_NE(builder, nullptr);
528
529 ASSERT_TRUE(builder->AddGroup("google", 16384));
530
531 Partition* partition = builder->AddPartition("system", "google", 0);
532 ASSERT_NE(partition, nullptr);
533 EXPECT_TRUE(builder->ResizePartition(partition, 8192));
534 EXPECT_EQ(partition->size(), 8192);
535 EXPECT_TRUE(builder->ResizePartition(partition, 16384));
536 EXPECT_EQ(partition->size(), 16384);
537 EXPECT_FALSE(builder->ResizePartition(partition, 32768));
538 EXPECT_EQ(partition->size(), 16384);
539 }
540
TEST_F(BuilderTest,ListPartitionsInGroup)541 TEST_F(BuilderTest, ListPartitionsInGroup) {
542 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
543 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
544 ASSERT_NE(builder, nullptr);
545
546 ASSERT_TRUE(builder->AddGroup("groupA", 16384));
547 ASSERT_TRUE(builder->AddGroup("groupB", 16384));
548
549 Partition* system = builder->AddPartition("system", "groupA", 0);
550 Partition* vendor = builder->AddPartition("vendor", "groupA", 0);
551 Partition* product = builder->AddPartition("product", "groupB", 0);
552 ASSERT_NE(system, nullptr);
553 ASSERT_NE(vendor, nullptr);
554 ASSERT_NE(product, nullptr);
555
556 auto groupA = builder->ListPartitionsInGroup("groupA");
557 auto groupB = builder->ListPartitionsInGroup("groupB");
558 auto groupC = builder->ListPartitionsInGroup("groupC");
559 ASSERT_THAT(groupA, ElementsAre(system, vendor));
560 ASSERT_THAT(groupB, ElementsAre(product));
561 ASSERT_TRUE(groupC.empty());
562 }
563
TEST_F(BuilderTest,ChangeGroups)564 TEST_F(BuilderTest, ChangeGroups) {
565 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
566 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
567 ASSERT_NE(builder, nullptr);
568
569 ASSERT_TRUE(builder->AddGroup("groupA", 16384));
570 ASSERT_TRUE(builder->AddGroup("groupB", 32768));
571
572 Partition* system = builder->AddPartition("system", "groupA", 0);
573 Partition* vendor = builder->AddPartition("vendor", "groupB", 0);
574 ASSERT_NE(system, nullptr);
575 ASSERT_NE(vendor, nullptr);
576 ASSERT_NE(builder->Export(), nullptr);
577
578 ASSERT_FALSE(builder->ChangePartitionGroup(system, "groupXYZ"));
579 ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupB"));
580 ASSERT_NE(builder->Export(), nullptr);
581
582 // Violate group constraint by reassigning groups.
583 ASSERT_TRUE(builder->ResizePartition(system, 16384 + 4096));
584 ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupA"));
585 ASSERT_EQ(builder->Export(), nullptr);
586
587 ASSERT_FALSE(builder->ChangeGroupSize("default", 2));
588 ASSERT_FALSE(builder->ChangeGroupSize("unknown", 2));
589 ASSERT_TRUE(builder->ChangeGroupSize("groupA", 32768));
590 ASSERT_NE(builder->Export(), nullptr);
591 }
592
TEST_F(BuilderTest,RemoveAndAddFirstPartition)593 TEST_F(BuilderTest, RemoveAndAddFirstPartition) {
594 auto builder = MetadataBuilder::New(10_GiB, 65536, 2);
595 ASSERT_NE(nullptr, builder);
596 ASSERT_TRUE(builder->AddGroup("foo_a", 5_GiB));
597 ASSERT_TRUE(builder->AddGroup("foo_b", 5_GiB));
598 android::fs_mgr::Partition* p;
599 p = builder->AddPartition("system_a", "foo_a", 0);
600 ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
601 p = builder->AddPartition("vendor_a", "foo_a", 0);
602 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
603 p = builder->AddPartition("system_b", "foo_b", 0);
604 ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
605 p = builder->AddPartition("vendor_b", "foo_b", 0);
606 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
607
608 builder->RemovePartition("system_a");
609 builder->RemovePartition("vendor_a");
610 p = builder->AddPartition("system_a", "foo_a", 0);
611 ASSERT_TRUE(p && builder->ResizePartition(p, 3_GiB));
612 p = builder->AddPartition("vendor_a", "foo_a", 0);
613 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
614 }
615
TEST_F(BuilderTest,ListGroups)616 TEST_F(BuilderTest, ListGroups) {
617 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
618 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
619 ASSERT_NE(builder, nullptr);
620 ASSERT_TRUE(builder->AddGroup("example", 0));
621
622 std::vector<std::string> groups = builder->ListGroups();
623 ASSERT_THAT(groups, ElementsAre("default", "example"));
624 }
625
TEST_F(BuilderTest,RemoveGroupAndPartitions)626 TEST_F(BuilderTest, RemoveGroupAndPartitions) {
627 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
628 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
629 ASSERT_NE(builder, nullptr);
630 ASSERT_TRUE(builder->AddGroup("example", 0));
631 ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
632 ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
633
634 builder->RemoveGroupAndPartitions("example");
635 ASSERT_NE(builder->FindPartition("system"), nullptr);
636 ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
637 ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
638
639 builder->RemoveGroupAndPartitions("default");
640 ASSERT_NE(builder->FindPartition("system"), nullptr);
641 }
642
TEST_F(BuilderTest,MultipleBlockDevices)643 TEST_F(BuilderTest, MultipleBlockDevices) {
644 std::vector<BlockDeviceInfo> partitions = {
645 BlockDeviceInfo("system_a", 256_MiB, 786432, 229376, 4096),
646 BlockDeviceInfo("vendor_a", 128_MiB, 786432, 753664, 4096),
647 BlockDeviceInfo("product_a", 64_MiB, 786432, 753664, 4096),
648 };
649 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(partitions, "system_a", 65536, 2);
650 ASSERT_NE(builder, nullptr);
651 EXPECT_EQ(builder->AllocatableSpace(), 467402752);
652
653 // Create a partition that spans 3 devices.
654 Partition* p = builder->AddPartition("system_a", 0);
655 ASSERT_NE(p, nullptr);
656 ASSERT_TRUE(builder->ResizePartition(p, 466976768));
657
658 unique_ptr<LpMetadata> metadata = builder->Export();
659 ASSERT_NE(metadata, nullptr);
660 ASSERT_EQ(metadata->block_devices.size(), 3);
661 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "system_a");
662 EXPECT_EQ(metadata->block_devices[0].size, 256_MiB);
663 EXPECT_EQ(metadata->block_devices[0].alignment, 786432);
664 EXPECT_EQ(metadata->block_devices[0].alignment_offset, 229376);
665 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[1]), "vendor_a");
666 EXPECT_EQ(metadata->block_devices[1].size, 128_MiB);
667 EXPECT_EQ(metadata->block_devices[1].alignment, 786432);
668 EXPECT_EQ(metadata->block_devices[1].alignment_offset, 753664);
669 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[2]), "product_a");
670 EXPECT_EQ(metadata->block_devices[2].size, 64_MiB);
671 EXPECT_EQ(metadata->block_devices[2].alignment, 786432);
672 EXPECT_EQ(metadata->block_devices[2].alignment_offset, 753664);
673 ASSERT_EQ(metadata->extents.size(), 3);
674 EXPECT_EQ(metadata->extents[0].num_sectors, 522752);
675 EXPECT_EQ(metadata->extents[0].target_type, LP_TARGET_TYPE_LINEAR);
676 EXPECT_EQ(metadata->extents[0].target_data, 1536);
677 EXPECT_EQ(metadata->extents[0].target_source, 0);
678 EXPECT_EQ(metadata->extents[1].num_sectors, 260608);
679 EXPECT_EQ(metadata->extents[1].target_type, LP_TARGET_TYPE_LINEAR);
680 EXPECT_EQ(metadata->extents[1].target_data, 1536);
681 EXPECT_EQ(metadata->extents[1].target_source, 1);
682 EXPECT_EQ(metadata->extents[2].num_sectors, 128704);
683 EXPECT_EQ(metadata->extents[2].target_type, LP_TARGET_TYPE_LINEAR);
684 EXPECT_EQ(metadata->extents[2].target_data, 1536);
685 EXPECT_EQ(metadata->extents[2].target_source, 2);
686 }
687
TEST_F(BuilderTest,ImportPartitionsOk)688 TEST_F(BuilderTest, ImportPartitionsOk) {
689 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
690 ASSERT_NE(builder, nullptr);
691
692 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
693 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
694 ASSERT_NE(system, nullptr);
695 ASSERT_NE(vendor, nullptr);
696 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
697 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
698 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
699
700 unique_ptr<LpMetadata> exported = builder->Export();
701 ASSERT_NE(exported, nullptr);
702
703 builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
704 ASSERT_NE(builder, nullptr);
705
706 ASSERT_TRUE(builder->ImportPartitions(*exported.get(), {"vendor"}));
707 EXPECT_NE(builder->FindPartition("vendor"), nullptr);
708 EXPECT_EQ(builder->FindPartition("system"), nullptr);
709
710 unique_ptr<LpMetadata> new_metadata = builder->Export();
711 ASSERT_NE(new_metadata, nullptr);
712
713 ASSERT_EQ(exported->partitions.size(), static_cast<size_t>(2));
714 ASSERT_EQ(GetPartitionName(exported->partitions[1]), "vendor");
715 ASSERT_EQ(new_metadata->partitions.size(), static_cast<size_t>(1));
716 ASSERT_EQ(GetPartitionName(new_metadata->partitions[0]), "vendor");
717
718 const LpMetadataExtent& extent_a =
719 exported->extents[exported->partitions[1].first_extent_index];
720 const LpMetadataExtent& extent_b =
721 new_metadata->extents[new_metadata->partitions[0].first_extent_index];
722 EXPECT_EQ(extent_a.num_sectors, extent_b.num_sectors);
723 EXPECT_EQ(extent_a.target_type, extent_b.target_type);
724 EXPECT_EQ(extent_a.target_data, extent_b.target_data);
725 EXPECT_EQ(extent_a.target_source, extent_b.target_source);
726 }
727
TEST_F(BuilderTest,ImportPartitionsFail)728 TEST_F(BuilderTest, ImportPartitionsFail) {
729 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
730 ASSERT_NE(builder, nullptr);
731
732 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
733 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
734 ASSERT_NE(system, nullptr);
735 ASSERT_NE(vendor, nullptr);
736 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
737 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
738 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
739
740 unique_ptr<LpMetadata> exported = builder->Export();
741 ASSERT_NE(exported, nullptr);
742
743 // Different device size.
744 builder = MetadataBuilder::New(1024 * 2048, 1024, 2);
745 ASSERT_NE(builder, nullptr);
746 EXPECT_FALSE(builder->ImportPartitions(*exported.get(), {"system"}));
747 }
748
TEST_F(BuilderTest,ABExtents)749 TEST_F(BuilderTest, ABExtents) {
750 BlockDeviceInfo device_info("super", 10_GiB, 768 * 1024, 0, 4096);
751
752 // A and B slots should be allocated from separate halves of the partition,
753 // to mitigate allocating too many extents. (b/120433288)
754 ON_CALL(*GetMockedPropertyFetcher(), GetProperty("ro.boot.slot_suffix", _))
755 .WillByDefault(Return("_a"));
756
757 auto builder = MetadataBuilder::New(device_info, 65536, 2);
758 ASSERT_NE(builder, nullptr);
759 Partition* system_a = builder->AddPartition("system_a", 0);
760 ASSERT_NE(system_a, nullptr);
761 Partition* system_b = builder->AddPartition("system_b", 0);
762 ASSERT_NE(system_b, nullptr);
763 ASSERT_TRUE(builder->ResizePartition(system_a, 2_GiB));
764 ASSERT_TRUE(builder->ResizePartition(system_b, 2_GiB));
765
766 builder->RemovePartition("system_a");
767 system_a = builder->AddPartition("system_a", 0);
768 ASSERT_NE(system_a, nullptr);
769 ASSERT_TRUE(builder->ResizePartition(system_a, 3_GiB));
770
771 EXPECT_EQ(system_a->extents().size(), static_cast<size_t>(1));
772 EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(1));
773 ASSERT_TRUE(builder->ResizePartition(system_b, 6_GiB));
774 EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(2));
775
776 unique_ptr<LpMetadata> exported = builder->Export();
777 ASSERT_NE(exported, nullptr);
778 ASSERT_EQ(exported->extents.size(), static_cast<size_t>(3));
779 EXPECT_EQ(exported->extents[0].target_data, 10487808);
780 EXPECT_EQ(exported->extents[0].num_sectors, 10483712);
781 EXPECT_EQ(exported->extents[1].target_data, 6292992);
782 EXPECT_EQ(exported->extents[1].num_sectors, 2099200);
783 EXPECT_EQ(exported->extents[2].target_data, 1536);
784 EXPECT_EQ(exported->extents[2].num_sectors, 6291456);
785 }
786
TEST_F(BuilderTest,PartialExtents)787 TEST_F(BuilderTest, PartialExtents) {
788 // super has a minimum extent size of 768KiB.
789 BlockDeviceInfo device_info("super", 1_GiB, 768 * 1024, 0, 4096);
790 auto builder = MetadataBuilder::New(device_info, 65536, 1);
791 ASSERT_NE(builder, nullptr);
792 Partition* system = builder->AddPartition("system", 0);
793 ASSERT_NE(system, nullptr);
794 Partition* vendor = builder->AddPartition("vendor", 0);
795 ASSERT_NE(vendor, nullptr);
796 ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment + 4096));
797 ASSERT_TRUE(builder->ResizePartition(vendor, device_info.alignment));
798 ASSERT_EQ(system->size(), device_info.alignment + 4096);
799 ASSERT_EQ(vendor->size(), device_info.alignment);
800
801 ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment * 2));
802 ASSERT_EQ(system->extents().size(), static_cast<size_t>(1));
803
804 unique_ptr<LpMetadata> exported = builder->Export();
805 ASSERT_NE(exported, nullptr);
806 ASSERT_EQ(exported->extents.size(), static_cast<size_t>(2));
807 EXPECT_EQ(exported->extents[0].target_data, 1536);
808 EXPECT_EQ(exported->extents[0].num_sectors, 3072);
809 EXPECT_EQ(exported->extents[1].target_data, 4608);
810 EXPECT_EQ(exported->extents[1].num_sectors, 1536);
811 }
812
TEST_F(BuilderTest,UpdateSuper)813 TEST_F(BuilderTest, UpdateSuper) {
814 // Build the on-disk metadata that we saw before flashing.
815 auto builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
816 ASSERT_NE(builder, nullptr);
817
818 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
819 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
820
821 Partition* partition = builder->AddPartition("system_a", "google_dynamic_partitions_a",
822 LP_PARTITION_ATTR_READONLY);
823 ASSERT_NE(partition, nullptr);
824 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 3608576));
825
826 partition = builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
827 LP_PARTITION_ATTR_READONLY);
828 ASSERT_NE(partition, nullptr);
829 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 5510144));
830
831 partition = builder->AddPartition("product_a", "google_dynamic_partitions_a",
832 LP_PARTITION_ATTR_READONLY);
833 ASSERT_NE(partition, nullptr);
834 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 2048));
835
836 partition = builder->AddPartition("system_b", "google_dynamic_partitions_b",
837 LP_PARTITION_ATTR_READONLY);
838 ASSERT_NE(partition, nullptr);
839 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 7955456));
840
841 partition = builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
842 LP_PARTITION_ATTR_READONLY);
843 ASSERT_NE(partition, nullptr);
844 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 9857024));
845
846 partition = builder->AddPartition("product_b", "google_dynamic_partitions_b",
847 LP_PARTITION_ATTR_READONLY);
848 ASSERT_NE(partition, nullptr);
849 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 11378688));
850
851 auto on_disk = builder->Export();
852 ASSERT_NE(on_disk, nullptr);
853
854 // Build the super_empty from the new build.
855 builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
856 ASSERT_NE(builder, nullptr);
857
858 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
859 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
860 ASSERT_NE(builder->AddPartition("system_a", "google_dynamic_partitions_a",
861 LP_PARTITION_ATTR_READONLY),
862 nullptr);
863 ASSERT_NE(builder->AddPartition("system_b", "google_dynamic_partitions_b",
864 LP_PARTITION_ATTR_READONLY),
865 nullptr);
866 ASSERT_NE(builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
867 LP_PARTITION_ATTR_READONLY),
868 nullptr);
869 ASSERT_NE(builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
870 LP_PARTITION_ATTR_READONLY),
871 nullptr);
872 ASSERT_NE(builder->AddPartition("product_a", "google_dynamic_partitions_a",
873 LP_PARTITION_ATTR_READONLY),
874 nullptr);
875 ASSERT_NE(builder->AddPartition("product_b", "google_dynamic_partitions_b",
876 LP_PARTITION_ATTR_READONLY),
877 nullptr);
878
879 std::set<std::string> partitions_to_keep{"system_a", "vendor_a", "product_a"};
880 ASSERT_TRUE(builder->ImportPartitions(*on_disk.get(), partitions_to_keep));
881 }
882
883 // Interval has operator< defined; it is not appropriate to re-define Interval::operator== that
884 // compares device index.
885 namespace android {
886 namespace fs_mgr {
operator ==(const Interval & a,const Interval & b)887 bool operator==(const Interval& a, const Interval& b) {
888 return a.device_index == b.device_index && a.start == b.start && a.end == b.end;
889 }
890 } // namespace fs_mgr
891 } // namespace android
892
TEST_F(BuilderTest,Interval)893 TEST_F(BuilderTest, Interval) {
894 EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 100)).length());
895 EXPECT_EQ(Interval(0, 100, 150),
896 Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 150)));
897 EXPECT_EQ(Interval(0, 100, 200),
898 Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 200)));
899 EXPECT_EQ(Interval(0, 100, 200),
900 Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 250)));
901 EXPECT_EQ(Interval(0, 100, 200),
902 Interval::Intersect(Interval(0, 100, 200), Interval(0, 100, 200)));
903 EXPECT_EQ(Interval(0, 150, 200),
904 Interval::Intersect(Interval(0, 100, 200), Interval(0, 150, 250)));
905 EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 200, 250)).length());
906
907 auto v = Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50), Interval(0, 100, 150)},
908 std::vector<Interval>{Interval(0, 25, 125)});
909 ASSERT_EQ(2, v.size());
910 EXPECT_EQ(Interval(0, 25, 50), v[0]);
911 EXPECT_EQ(Interval(0, 100, 125), v[1]);
912
913 EXPECT_EQ(0u, Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50)},
914 std::vector<Interval>{Interval(0, 100, 150)})
915 .size());
916 }
917
TEST_F(BuilderTest,ExpandedHeader)918 TEST_F(BuilderTest, ExpandedHeader) {
919 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
920 ASSERT_NE(builder, nullptr);
921
922 builder->RequireExpandedMetadataHeader();
923
924 unique_ptr<LpMetadata> exported = builder->Export();
925 ASSERT_NE(exported, nullptr);
926 EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2));
927
928 exported->header.flags = 0x5e5e5e5e;
929
930 builder = MetadataBuilder::New(*exported.get());
931 exported = builder->Export();
932 ASSERT_NE(exported, nullptr);
933 EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2));
934 EXPECT_EQ(exported->header.flags, 0x5e5e5e5e);
935 }
936
ToInterval(const std::unique_ptr<Extent> & extent)937 static Interval ToInterval(const std::unique_ptr<Extent>& extent) {
938 if (LinearExtent* le = extent->AsLinearExtent()) {
939 return le->AsInterval();
940 }
941 return {0, 0, 0};
942 }
943
AddPartition(const std::unique_ptr<MetadataBuilder> & builder,const std::string & partition_name,const std::string & group_name,uint64_t num_sectors,uint64_t start_sector,std::vector<Interval> * intervals=nullptr)944 static void AddPartition(const std::unique_ptr<MetadataBuilder>& builder,
945 const std::string& partition_name, const std::string& group_name,
946 uint64_t num_sectors, uint64_t start_sector,
947 std::vector<Interval>* intervals = nullptr) {
948 Partition* p = builder->AddPartition(partition_name, group_name, 0);
949 ASSERT_NE(p, nullptr);
950 ASSERT_TRUE(builder->AddLinearExtent(p, "super", num_sectors, start_sector));
951 ASSERT_EQ(p->extents().size(), 1);
952
953 if (!intervals) {
954 return;
955 }
956
957 auto new_interval = ToInterval(p->extents().back());
958 std::vector<Interval> new_intervals = {new_interval};
959
960 auto overlap = Interval::Intersect(*intervals, new_intervals);
961 ASSERT_TRUE(overlap.empty());
962
963 intervals->push_back(new_interval);
964 }
965
TEST_F(BuilderTest,CollidedExtents)966 TEST_F(BuilderTest, CollidedExtents) {
967 BlockDeviceInfo super("super", 8_GiB, 786432, 229376, 4096);
968 std::vector<BlockDeviceInfo> block_devices = {super};
969
970 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(block_devices, "super", 65536, 2);
971 ASSERT_NE(builder, nullptr);
972
973 ASSERT_TRUE(builder->AddGroup("group", 0));
974
975 std::vector<Interval> old_intervals;
976 AddPartition(builder, "system", "group", 10229008, 2048, &old_intervals);
977 AddPartition(builder, "test_a", "group", 648, 12709888, &old_intervals);
978 AddPartition(builder, "test_b", "group", 625184, 12711936, &old_intervals);
979 AddPartition(builder, "test_c", "group", 130912, 13338624, &old_intervals);
980 AddPartition(builder, "test_d", "group", 888, 13469696, &old_intervals);
981 AddPartition(builder, "test_e", "group", 888, 13471744, &old_intervals);
982 AddPartition(builder, "test_f", "group", 888, 13475840, &old_intervals);
983 AddPartition(builder, "test_g", "group", 888, 13477888, &old_intervals);
984
985 // Don't track the first vendor interval, since it will get extended.
986 AddPartition(builder, "vendor", "group", 2477920, 10231808, nullptr);
987
988 std::vector<Interval> new_intervals;
989
990 Partition* p = builder->FindPartition("vendor");
991 ASSERT_NE(p, nullptr);
992 ASSERT_TRUE(builder->ResizePartition(p, 1282031616));
993 ASSERT_GE(p->extents().size(), 1);
994 for (const auto& extent : p->extents()) {
995 new_intervals.push_back(ToInterval(extent));
996 }
997
998 std::vector<Interval> overlap = Interval::Intersect(old_intervals, new_intervals);
999 ASSERT_TRUE(overlap.empty());
1000 }
1001
TEST_F(BuilderTest,LinearExtentOverlap)1002 TEST_F(BuilderTest, LinearExtentOverlap) {
1003 LinearExtent extent(20, 0, 10);
1004
1005 EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 10}));
1006 EXPECT_TRUE(extent.OverlapsWith(LinearExtent{50, 0, 10}));
1007 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 0, 30}));
1008 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{10, 0, 0}));
1009 EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 0}));
1010 EXPECT_TRUE(extent.OverlapsWith(LinearExtent{40, 0, 0}));
1011 EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 15}));
1012
1013 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 0}));
1014 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{50, 1, 10}));
1015 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{40, 1, 0}));
1016 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 15}));
1017 EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 10}));
1018 }
1019
TEST_F(BuilderTest,AlignFreeRegion)1020 TEST_F(BuilderTest, AlignFreeRegion) {
1021 BlockDeviceInfo super("super", 8_GiB, 786432, 0, 4096);
1022 std::vector<BlockDeviceInfo> block_devices = {super};
1023
1024 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(block_devices, "super", 65536, 2);
1025 ASSERT_NE(builder, nullptr);
1026
1027 Partition* p = builder->AddPartition("system", "default", 0);
1028 ASSERT_NE(p, nullptr);
1029 ASSERT_TRUE(builder->AddLinearExtent(p, "super", 64, (super.alignment + 4096) / 512));
1030
1031 p = builder->AddPartition("vendor", "default", 0);
1032 ASSERT_NE(p, nullptr);
1033 ASSERT_TRUE(builder->ResizePartition(p, 2_GiB));
1034
1035 const auto& extents = p->extents();
1036 ASSERT_EQ(extents.size(), 2);
1037
1038 LinearExtent* e1 = extents[0]->AsLinearExtent();
1039 ASSERT_NE(e1, nullptr);
1040 LinearExtent* e2 = extents[1]->AsLinearExtent();
1041 ASSERT_NE(e2, nullptr);
1042
1043 // The misaligned partition starting at sector 1544 should not cause any
1044 // overlap with previous extents. We should see vendor punch a hole where
1045 // "system" is, extending the hole up to the next aligned block.
1046 EXPECT_EQ(e1->physical_sector(), 1536);
1047 EXPECT_EQ(e1->end_sector(), 1544);
1048 EXPECT_EQ(e2->physical_sector(), 3072);
1049 EXPECT_EQ(e2->end_sector(), 4197368);
1050 }
1051
TEST_F(BuilderTest,ResizeOverflow)1052 TEST_F(BuilderTest, ResizeOverflow) {
1053 BlockDeviceInfo super("super", 8_GiB, 786432, 229376, 4096);
1054 std::vector<BlockDeviceInfo> block_devices = {super};
1055
1056 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(block_devices, "super", 65536, 2);
1057 ASSERT_NE(builder, nullptr);
1058
1059 ASSERT_TRUE(builder->AddGroup("group", 0));
1060
1061 Partition* p = builder->AddPartition("system", "default", 0);
1062 ASSERT_NE(p, nullptr);
1063 ASSERT_FALSE(builder->ResizePartition(p, 18446744073709551615ULL));
1064 }
1065
TEST_F(BuilderTest,VerifyExtent)1066 TEST_F(BuilderTest, VerifyExtent) {
1067 auto source_builder = MetadataBuilder::New(4096 * 50, 40960, 2);
1068 ASSERT_NE(source_builder, nullptr);
1069 ASSERT_TRUE(source_builder->AddGroup("test_group_a", 40960));
1070 ASSERT_TRUE(source_builder->AddGroup("test_group_b", 40960));
1071 AddPartition(source_builder, "system_a", "test_group_a", 8192, 2048);
1072 AddPartition(source_builder, "vendor_a", "test_group_a", 10240, 10240);
1073 AddPartition(source_builder, "system_b", "test_group_b", 8192, 20480);
1074
1075 auto target_builder = MetadataBuilder::New(4096 * 50, 40960, 2);
1076 ASSERT_NE(target_builder, nullptr);
1077 ASSERT_TRUE(target_builder->AddGroup("test_group_b", 40960));
1078 AddPartition(target_builder, "system_b", "test_group_b", 8192, 2048);
1079 AddPartition(target_builder, "vendor_b", "test_group_b", 10240, 10240);
1080
1081 ASSERT_TRUE(MetadataBuilder::VerifyExtentsAgainstSourceMetadata(
1082 *source_builder, 0, *target_builder, 1, std::vector<std::string>{"system", "vendor"}));
1083
1084 target_builder->RemovePartition("vendor_b");
1085 ASSERT_FALSE(target_builder->VerifyExtentsAgainstSourceMetadata(
1086 *source_builder, 0, *target_builder, 1, std::vector<std::string>{"vendor"}));
1087
1088 AddPartition(target_builder, "vendor_b", "test_group_b", 1000, 10240);
1089 ASSERT_FALSE(target_builder->VerifyExtentsAgainstSourceMetadata(
1090 *source_builder, 0, *target_builder, 1, std::vector<std::string>{"vendor"}));
1091 }
1092