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