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 <fs_mgr.h>
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 #include <liblp/builder.h>
21
22 #include "utility.h"
23
24 using namespace std;
25 using namespace android::fs_mgr;
26 using ::testing::ElementsAre;
27
28 class Environment : public ::testing::Environment {
29 public:
SetUp()30 void SetUp() override { MetadataBuilder::OverrideABForTesting(false); }
31 };
32
main(int argc,char ** argv)33 int main(int argc, char** argv) {
34 std::unique_ptr<Environment> env(new Environment);
35 ::testing::AddGlobalTestEnvironment(env.get());
36 ::testing::InitGoogleTest(&argc, argv);
37 return RUN_ALL_TESTS();
38 }
39
40 class BuilderTest : public ::testing::Test {
41 public:
SetUp()42 void SetUp() override { MetadataBuilder::OverrideABForTesting(false); }
TearDown()43 void TearDown() override { MetadataBuilder::OverrideABForTesting(false); }
44 };
45
TEST_F(BuilderTest,BuildBasic)46 TEST_F(BuilderTest, BuildBasic) {
47 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
48 ASSERT_NE(builder, nullptr);
49
50 Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
51 ASSERT_NE(partition, nullptr);
52 EXPECT_EQ(partition->name(), "system");
53 EXPECT_EQ(partition->attributes(), LP_PARTITION_ATTR_READONLY);
54 EXPECT_EQ(partition->size(), 0);
55 EXPECT_EQ(builder->FindPartition("system"), partition);
56
57 builder->RemovePartition("system");
58 EXPECT_EQ(builder->FindPartition("system"), nullptr);
59 }
60
TEST_F(BuilderTest,ResizePartition)61 TEST_F(BuilderTest, ResizePartition) {
62 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
63 ASSERT_NE(builder, nullptr);
64
65 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
66 ASSERT_NE(system, nullptr);
67 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
68 EXPECT_EQ(system->size(), 65536);
69 ASSERT_EQ(system->extents().size(), 1);
70
71 LinearExtent* extent = system->extents()[0]->AsLinearExtent();
72 ASSERT_NE(extent, nullptr);
73 EXPECT_EQ(extent->num_sectors(), 65536 / LP_SECTOR_SIZE);
74 // The first logical sector will be:
75 // (LP_PARTITION_RESERVED_BYTES + 4096*2 + 1024*4) / 512
76 // Or, in terms of sectors (reserved + geometry + metadata):
77 // (8 + 16 + 8) = 32
78 EXPECT_EQ(extent->physical_sector(), 32);
79
80 // Test resizing to the same size.
81 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
82 EXPECT_EQ(system->size(), 65536);
83 EXPECT_EQ(system->extents().size(), 1);
84 EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE);
85 // Test resizing to a smaller size.
86 EXPECT_EQ(builder->ResizePartition(system, 0), true);
87 EXPECT_EQ(system->size(), 0);
88 EXPECT_EQ(system->extents().size(), 0);
89 // Test resizing to a greater size.
90 builder->ResizePartition(system, 131072);
91 EXPECT_EQ(system->size(), 131072);
92 EXPECT_EQ(system->extents().size(), 1);
93 EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE);
94 // Test resizing again, that the extents are merged together.
95 builder->ResizePartition(system, 1024 * 256);
96 EXPECT_EQ(system->size(), 1024 * 256);
97 EXPECT_EQ(system->extents().size(), 1);
98 EXPECT_EQ(system->extents()[0]->num_sectors(), (1024 * 256) / LP_SECTOR_SIZE);
99
100 // Test shrinking within the same extent.
101 builder->ResizePartition(system, 32768);
102 EXPECT_EQ(system->size(), 32768);
103 EXPECT_EQ(system->extents().size(), 1);
104 extent = system->extents()[0]->AsLinearExtent();
105 ASSERT_NE(extent, nullptr);
106 EXPECT_EQ(extent->num_sectors(), 32768 / LP_SECTOR_SIZE);
107 EXPECT_EQ(extent->physical_sector(), 32);
108
109 // Test shrinking to 0.
110 builder->ResizePartition(system, 0);
111 EXPECT_EQ(system->size(), 0);
112 EXPECT_EQ(system->extents().size(), 0);
113 }
114
TEST_F(BuilderTest,PartitionAlignment)115 TEST_F(BuilderTest, PartitionAlignment) {
116 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
117 ASSERT_NE(builder, nullptr);
118
119 // Test that we align up to one sector.
120 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
121 ASSERT_NE(system, nullptr);
122 EXPECT_EQ(builder->ResizePartition(system, 10000), true);
123 EXPECT_EQ(system->size(), 12288);
124 EXPECT_EQ(system->extents().size(), 1);
125
126 builder->ResizePartition(system, 7000);
127 EXPECT_EQ(system->size(), 8192);
128 EXPECT_EQ(system->extents().size(), 1);
129 }
130
TEST_F(BuilderTest,DiskAlignment)131 TEST_F(BuilderTest, DiskAlignment) {
132 static const uint64_t kDiskSize = 1000000;
133 static const uint32_t kMetadataSize = 1024;
134 static const uint32_t kMetadataSlots = 2;
135
136 unique_ptr<MetadataBuilder> builder =
137 MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
138 ASSERT_EQ(builder, nullptr);
139 }
140
TEST_F(BuilderTest,MetadataAlignment)141 TEST_F(BuilderTest, MetadataAlignment) {
142 // Make sure metadata sizes get aligned up.
143 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1000, 2);
144 ASSERT_NE(builder, nullptr);
145 unique_ptr<LpMetadata> exported = builder->Export();
146 ASSERT_NE(exported, nullptr);
147 EXPECT_EQ(exported->geometry.metadata_max_size, 1024);
148 }
149
TEST_F(BuilderTest,InternalAlignment)150 TEST_F(BuilderTest, InternalAlignment) {
151 // Test the metadata fitting within alignment.
152 BlockDeviceInfo device_info("super", 1024 * 1024, 768 * 1024, 0, 4096);
153 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
154 ASSERT_NE(builder, nullptr);
155 unique_ptr<LpMetadata> exported = builder->Export();
156 ASSERT_NE(exported, nullptr);
157 auto super_device = GetMetadataSuperBlockDevice(*exported.get());
158 ASSERT_NE(super_device, nullptr);
159 EXPECT_EQ(super_device->first_logical_sector, 1536);
160
161 // Test a large alignment offset thrown in.
162 device_info.alignment_offset = 753664;
163 builder = MetadataBuilder::New(device_info, 1024, 2);
164 ASSERT_NE(builder, nullptr);
165 exported = builder->Export();
166 ASSERT_NE(exported, nullptr);
167 super_device = GetMetadataSuperBlockDevice(*exported.get());
168 ASSERT_NE(super_device, nullptr);
169 EXPECT_EQ(super_device->first_logical_sector, 1472);
170
171 // Alignment offset without alignment doesn't mean anything.
172 device_info.alignment = 0;
173 builder = MetadataBuilder::New(device_info, 1024, 2);
174 ASSERT_EQ(builder, nullptr);
175
176 // Test a small alignment with an alignment offset.
177 device_info.alignment = 12 * 1024;
178 device_info.alignment_offset = 3 * 1024;
179 builder = MetadataBuilder::New(device_info, 16 * 1024, 2);
180 ASSERT_NE(builder, nullptr);
181 exported = builder->Export();
182 ASSERT_NE(exported, nullptr);
183 super_device = GetMetadataSuperBlockDevice(*exported.get());
184 ASSERT_NE(super_device, nullptr);
185 EXPECT_EQ(super_device->first_logical_sector, 174);
186
187 // Test a small alignment with no alignment offset.
188 device_info.alignment = 11 * 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, 160);
196 }
197
TEST_F(BuilderTest,InternalPartitionAlignment)198 TEST_F(BuilderTest, InternalPartitionAlignment) {
199 BlockDeviceInfo device_info("super", 512 * 1024 * 1024, 768 * 1024, 753664, 4096);
200 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
201
202 Partition* a = builder->AddPartition("a", 0);
203 ASSERT_NE(a, nullptr);
204 Partition* b = builder->AddPartition("b", 0);
205 ASSERT_NE(b, nullptr);
206
207 // Add a bunch of small extents to each, interleaving.
208 for (size_t i = 0; i < 10; i++) {
209 ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096));
210 ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096));
211 }
212 EXPECT_EQ(a->size(), 40960);
213 EXPECT_EQ(b->size(), 40960);
214
215 unique_ptr<LpMetadata> exported = builder->Export();
216 ASSERT_NE(exported, nullptr);
217
218 // Check that each starting sector is aligned.
219 for (const auto& extent : exported->extents) {
220 ASSERT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
221 EXPECT_EQ(extent.num_sectors, 80);
222
223 uint64_t lba = extent.target_data * LP_SECTOR_SIZE;
224 uint64_t aligned_lba = AlignTo(lba, device_info.alignment, device_info.alignment_offset);
225 EXPECT_EQ(lba, aligned_lba);
226 }
227
228 // Sanity check one extent.
229 EXPECT_EQ(exported->extents.back().target_data, 3008);
230 }
231
TEST_F(BuilderTest,UseAllDiskSpace)232 TEST_F(BuilderTest, UseAllDiskSpace) {
233 static constexpr uint64_t total = 1024 * 1024;
234 static constexpr uint64_t metadata = 1024;
235 static constexpr uint64_t slots = 2;
236 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(total, metadata, slots);
237 // We reserve a geometry block (4KB) plus space for each copy of the
238 // maximum size of a metadata blob. Then, we double that space since
239 // we store a backup copy of everything.
240 static constexpr uint64_t geometry = 4 * 1024;
241 static constexpr uint64_t allocatable =
242 total - (metadata * slots + geometry) * 2 - LP_PARTITION_RESERVED_BYTES;
243 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
244 EXPECT_EQ(builder->UsedSpace(), 0);
245
246 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
247 ASSERT_NE(system, nullptr);
248 EXPECT_EQ(builder->ResizePartition(system, allocatable), true);
249 EXPECT_EQ(system->size(), allocatable);
250 EXPECT_EQ(builder->UsedSpace(), allocatable);
251 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
252 EXPECT_EQ(builder->ResizePartition(system, allocatable + 1), false);
253 EXPECT_EQ(system->size(), allocatable);
254 EXPECT_EQ(builder->UsedSpace(), allocatable);
255 EXPECT_EQ(builder->AllocatableSpace(), allocatable);
256 }
257
TEST_F(BuilderTest,BuildComplex)258 TEST_F(BuilderTest, BuildComplex) {
259 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
260
261 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
262 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
263 ASSERT_NE(system, nullptr);
264 ASSERT_NE(vendor, nullptr);
265 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
266 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
267 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
268 EXPECT_EQ(system->size(), 98304);
269 EXPECT_EQ(vendor->size(), 32768);
270
271 // We now expect to have 3 extents total: 2 for system, 1 for vendor, since
272 // our allocation strategy is greedy/first-fit.
273 ASSERT_EQ(system->extents().size(), 2);
274 ASSERT_EQ(vendor->extents().size(), 1);
275
276 LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
277 LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
278 LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
279 ASSERT_NE(system1, nullptr);
280 ASSERT_NE(system2, nullptr);
281 ASSERT_NE(vendor1, nullptr);
282 EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
283 EXPECT_EQ(system1->physical_sector(), 32);
284 EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
285 EXPECT_EQ(system2->physical_sector(), 224);
286 EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
287 EXPECT_EQ(vendor1->physical_sector(), 160);
288 EXPECT_EQ(system1->physical_sector() + system1->num_sectors(), vendor1->physical_sector());
289 EXPECT_EQ(vendor1->physical_sector() + vendor1->num_sectors(), system2->physical_sector());
290 }
291
TEST_F(BuilderTest,AddInvalidPartition)292 TEST_F(BuilderTest, AddInvalidPartition) {
293 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
294
295 Partition* partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
296 ASSERT_NE(partition, nullptr);
297
298 // Duplicate name.
299 partition = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
300 EXPECT_EQ(partition, nullptr);
301
302 // Empty name.
303 partition = builder->AddPartition("", LP_PARTITION_ATTR_READONLY);
304 EXPECT_EQ(partition, nullptr);
305 }
306
TEST_F(BuilderTest,BuilderExport)307 TEST_F(BuilderTest, BuilderExport) {
308 static const uint64_t kDiskSize = 1024 * 1024;
309 static const uint32_t kMetadataSize = 1024;
310 static const uint32_t kMetadataSlots = 2;
311 unique_ptr<MetadataBuilder> builder =
312 MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
313
314 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
315 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
316 ASSERT_NE(system, nullptr);
317 ASSERT_NE(vendor, nullptr);
318 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
319 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
320 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
321
322 unique_ptr<LpMetadata> exported = builder->Export();
323 EXPECT_NE(exported, nullptr);
324
325 auto super_device = GetMetadataSuperBlockDevice(*exported.get());
326 ASSERT_NE(super_device, nullptr);
327
328 // Verify geometry. Some details of this may change if we change the
329 // metadata structures. So in addition to checking the exact values, we
330 // also check that they are internally consistent after.
331 const LpMetadataGeometry& geometry = exported->geometry;
332 EXPECT_EQ(geometry.magic, LP_METADATA_GEOMETRY_MAGIC);
333 EXPECT_EQ(geometry.struct_size, sizeof(geometry));
334 EXPECT_EQ(geometry.metadata_max_size, 1024);
335 EXPECT_EQ(geometry.metadata_slot_count, 2);
336 EXPECT_EQ(super_device->first_logical_sector, 32);
337
338 static const size_t kMetadataSpace =
339 ((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
340 EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
341
342 // Verify header.
343 const LpMetadataHeader& header = exported->header;
344 EXPECT_EQ(header.magic, LP_METADATA_HEADER_MAGIC);
345 EXPECT_EQ(header.major_version, LP_METADATA_MAJOR_VERSION);
346 EXPECT_EQ(header.minor_version, LP_METADATA_MINOR_VERSION);
347
348 ASSERT_EQ(exported->partitions.size(), 2);
349 ASSERT_EQ(exported->extents.size(), 3);
350
351 for (const auto& partition : exported->partitions) {
352 Partition* original = builder->FindPartition(GetPartitionName(partition));
353 ASSERT_NE(original, nullptr);
354 for (size_t i = 0; i < partition.num_extents; i++) {
355 const auto& extent = exported->extents[partition.first_extent_index + i];
356 LinearExtent* original_extent = original->extents()[i]->AsLinearExtent();
357 EXPECT_EQ(extent.num_sectors, original_extent->num_sectors());
358 EXPECT_EQ(extent.target_type, LP_TARGET_TYPE_LINEAR);
359 EXPECT_EQ(extent.target_data, original_extent->physical_sector());
360 }
361 EXPECT_EQ(partition.attributes, original->attributes());
362 }
363 }
364
TEST_F(BuilderTest,BuilderImport)365 TEST_F(BuilderTest, BuilderImport) {
366 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
367
368 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
369 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
370 ASSERT_NE(system, nullptr);
371 ASSERT_NE(vendor, nullptr);
372 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
373 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
374 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
375
376 unique_ptr<LpMetadata> exported = builder->Export();
377 ASSERT_NE(exported, nullptr);
378
379 builder = MetadataBuilder::New(*exported.get());
380 ASSERT_NE(builder, nullptr);
381 system = builder->FindPartition("system");
382 ASSERT_NE(system, nullptr);
383 vendor = builder->FindPartition("vendor");
384 ASSERT_NE(vendor, nullptr);
385
386 EXPECT_EQ(system->size(), 98304);
387 ASSERT_EQ(system->extents().size(), 2);
388 EXPECT_EQ(system->attributes(), LP_PARTITION_ATTR_READONLY);
389 EXPECT_EQ(vendor->size(), 32768);
390 ASSERT_EQ(vendor->extents().size(), 1);
391 EXPECT_EQ(vendor->attributes(), LP_PARTITION_ATTR_READONLY);
392
393 LinearExtent* system1 = system->extents()[0]->AsLinearExtent();
394 LinearExtent* system2 = system->extents()[1]->AsLinearExtent();
395 LinearExtent* vendor1 = vendor->extents()[0]->AsLinearExtent();
396 EXPECT_EQ(system1->num_sectors(), 65536 / LP_SECTOR_SIZE);
397 EXPECT_EQ(system1->physical_sector(), 32);
398 EXPECT_EQ(system2->num_sectors(), 32768 / LP_SECTOR_SIZE);
399 EXPECT_EQ(system2->physical_sector(), 224);
400 EXPECT_EQ(vendor1->num_sectors(), 32768 / LP_SECTOR_SIZE);
401 }
402
TEST_F(BuilderTest,ExportNameTooLong)403 TEST_F(BuilderTest, ExportNameTooLong) {
404 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
405
406 std::string name = "abcdefghijklmnopqrstuvwxyz0123456789";
407 Partition* system = builder->AddPartition(name + name, LP_PARTITION_ATTR_READONLY);
408 EXPECT_NE(system, nullptr);
409
410 unique_ptr<LpMetadata> exported = builder->Export();
411 EXPECT_EQ(exported, nullptr);
412 }
413
TEST_F(BuilderTest,MetadataTooLarge)414 TEST_F(BuilderTest, MetadataTooLarge) {
415 static const size_t kDiskSize = 128 * 1024;
416 static const size_t kMetadataSize = 64 * 1024;
417
418 // No space to store metadata + geometry.
419 BlockDeviceInfo device_info("super", kDiskSize, 0, 0, 4096);
420 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
421 EXPECT_EQ(builder, nullptr);
422
423 // No space to store metadata + geometry + one free sector.
424 device_info.size += LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2);
425 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
426 EXPECT_EQ(builder, nullptr);
427
428 // Space for metadata + geometry + one free block.
429 device_info.size += device_info.logical_block_size;
430 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
431 EXPECT_NE(builder, nullptr);
432
433 // Test with alignment.
434 device_info.alignment = 131072;
435 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
436 EXPECT_EQ(builder, nullptr);
437
438 device_info.alignment = 0;
439 device_info.alignment_offset = 32768 - LP_SECTOR_SIZE;
440 builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
441 EXPECT_EQ(builder, nullptr);
442 }
443
TEST_F(BuilderTest,block_device_info)444 TEST_F(BuilderTest, block_device_info) {
445 PartitionOpener opener;
446
447 BlockDeviceInfo device_info;
448 ASSERT_TRUE(opener.GetInfo(fs_mgr_get_super_partition_name(), &device_info));
449
450 // Sanity check that the device doesn't give us some weird inefficient
451 // alignment.
452 ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
453 ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
454 ASSERT_LE(device_info.alignment_offset, INT_MAX);
455 ASSERT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
456
457 // Having an alignment offset > alignment doesn't really make sense.
458 ASSERT_LT(device_info.alignment_offset, device_info.alignment);
459 }
460
TEST_F(BuilderTest,UpdateBlockDeviceInfo)461 TEST_F(BuilderTest, UpdateBlockDeviceInfo) {
462 BlockDeviceInfo device_info("super", 1024 * 1024, 4096, 1024, 4096);
463 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
464 ASSERT_NE(builder, nullptr);
465
466 BlockDeviceInfo new_info;
467 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
468
469 EXPECT_EQ(new_info.size, device_info.size);
470 EXPECT_EQ(new_info.alignment, device_info.alignment);
471 EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
472 EXPECT_EQ(new_info.logical_block_size, device_info.logical_block_size);
473
474 device_info.alignment = 0;
475 device_info.alignment_offset = 2048;
476 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
477 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
478 EXPECT_EQ(new_info.alignment, 4096);
479 EXPECT_EQ(new_info.alignment_offset, device_info.alignment_offset);
480
481 device_info.alignment = 8192;
482 device_info.alignment_offset = 0;
483 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", device_info));
484 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
485 EXPECT_EQ(new_info.alignment, 8192);
486 EXPECT_EQ(new_info.alignment_offset, 2048);
487
488 new_info.size += 4096;
489 ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
490 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
491 EXPECT_EQ(new_info.size, 1024 * 1024);
492
493 new_info.logical_block_size = 512;
494 ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", new_info));
495 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
496 EXPECT_EQ(new_info.logical_block_size, 4096);
497
498 new_info.logical_block_size = 7;
499 ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
500 ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
501 EXPECT_EQ(new_info.logical_block_size, 4096);
502 }
503
TEST_F(BuilderTest,InvalidBlockSize)504 TEST_F(BuilderTest, InvalidBlockSize) {
505 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 513);
506 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
507 EXPECT_EQ(builder, nullptr);
508 }
509
TEST_F(BuilderTest,AlignedExtentSize)510 TEST_F(BuilderTest, AlignedExtentSize) {
511 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
512 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
513 ASSERT_NE(builder, nullptr);
514
515 Partition* partition = builder->AddPartition("system", 0);
516 ASSERT_NE(partition, nullptr);
517 ASSERT_TRUE(builder->ResizePartition(partition, 512));
518 EXPECT_EQ(partition->size(), 4096);
519 }
520
TEST_F(BuilderTest,AlignedFreeSpace)521 TEST_F(BuilderTest, AlignedFreeSpace) {
522 // Only one sector free - at least one block is required.
523 BlockDeviceInfo device_info("super", 10240, 0, 0, 4096);
524 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
525 ASSERT_EQ(builder, nullptr);
526 }
527
TEST_F(BuilderTest,HasDefaultGroup)528 TEST_F(BuilderTest, HasDefaultGroup) {
529 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
530 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
531 ASSERT_NE(builder, nullptr);
532
533 EXPECT_FALSE(builder->AddGroup("default", 0));
534 }
535
TEST_F(BuilderTest,GroupSizeLimits)536 TEST_F(BuilderTest, GroupSizeLimits) {
537 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
538 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
539 ASSERT_NE(builder, nullptr);
540
541 ASSERT_TRUE(builder->AddGroup("google", 16384));
542
543 Partition* partition = builder->AddPartition("system", "google", 0);
544 ASSERT_NE(partition, nullptr);
545 EXPECT_TRUE(builder->ResizePartition(partition, 8192));
546 EXPECT_EQ(partition->size(), 8192);
547 EXPECT_TRUE(builder->ResizePartition(partition, 16384));
548 EXPECT_EQ(partition->size(), 16384);
549 EXPECT_FALSE(builder->ResizePartition(partition, 32768));
550 EXPECT_EQ(partition->size(), 16384);
551 }
552
TEST_F(BuilderTest,ListPartitionsInGroup)553 TEST_F(BuilderTest, ListPartitionsInGroup) {
554 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
555 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
556 ASSERT_NE(builder, nullptr);
557
558 ASSERT_TRUE(builder->AddGroup("groupA", 16384));
559 ASSERT_TRUE(builder->AddGroup("groupB", 16384));
560
561 Partition* system = builder->AddPartition("system", "groupA", 0);
562 Partition* vendor = builder->AddPartition("vendor", "groupA", 0);
563 Partition* product = builder->AddPartition("product", "groupB", 0);
564 ASSERT_NE(system, nullptr);
565 ASSERT_NE(vendor, nullptr);
566 ASSERT_NE(product, nullptr);
567
568 auto groupA = builder->ListPartitionsInGroup("groupA");
569 auto groupB = builder->ListPartitionsInGroup("groupB");
570 auto groupC = builder->ListPartitionsInGroup("groupC");
571 ASSERT_THAT(groupA, ElementsAre(system, vendor));
572 ASSERT_THAT(groupB, ElementsAre(product));
573 ASSERT_TRUE(groupC.empty());
574 }
575
TEST_F(BuilderTest,ChangeGroups)576 TEST_F(BuilderTest, ChangeGroups) {
577 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
578 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
579 ASSERT_NE(builder, nullptr);
580
581 ASSERT_TRUE(builder->AddGroup("groupA", 16384));
582 ASSERT_TRUE(builder->AddGroup("groupB", 32768));
583
584 Partition* system = builder->AddPartition("system", "groupA", 0);
585 Partition* vendor = builder->AddPartition("vendor", "groupB", 0);
586 ASSERT_NE(system, nullptr);
587 ASSERT_NE(vendor, nullptr);
588 ASSERT_NE(builder->Export(), nullptr);
589
590 ASSERT_FALSE(builder->ChangePartitionGroup(system, "groupXYZ"));
591 ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupB"));
592 ASSERT_NE(builder->Export(), nullptr);
593
594 // Violate group constraint by reassigning groups.
595 ASSERT_TRUE(builder->ResizePartition(system, 16384 + 4096));
596 ASSERT_TRUE(builder->ChangePartitionGroup(system, "groupA"));
597 ASSERT_EQ(builder->Export(), nullptr);
598
599 ASSERT_FALSE(builder->ChangeGroupSize("default", 2));
600 ASSERT_FALSE(builder->ChangeGroupSize("unknown", 2));
601 ASSERT_TRUE(builder->ChangeGroupSize("groupA", 32768));
602 ASSERT_NE(builder->Export(), nullptr);
603 }
604
operator ""_GiB(unsigned long long x)605 constexpr unsigned long long operator"" _GiB(unsigned long long x) { // NOLINT
606 return x << 30;
607 }
operator ""_MiB(unsigned long long x)608 constexpr unsigned long long operator"" _MiB(unsigned long long x) { // NOLINT
609 return x << 20;
610 }
611
TEST_F(BuilderTest,RemoveAndAddFirstPartition)612 TEST_F(BuilderTest, RemoveAndAddFirstPartition) {
613 auto builder = MetadataBuilder::New(10_GiB, 65536, 2);
614 ASSERT_NE(nullptr, builder);
615 ASSERT_TRUE(builder->AddGroup("foo_a", 5_GiB));
616 ASSERT_TRUE(builder->AddGroup("foo_b", 5_GiB));
617 android::fs_mgr::Partition* p;
618 p = builder->AddPartition("system_a", "foo_a", 0);
619 ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
620 p = builder->AddPartition("vendor_a", "foo_a", 0);
621 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
622 p = builder->AddPartition("system_b", "foo_b", 0);
623 ASSERT_TRUE(p && builder->ResizePartition(p, 2_GiB));
624 p = builder->AddPartition("vendor_b", "foo_b", 0);
625 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
626
627 builder->RemovePartition("system_a");
628 builder->RemovePartition("vendor_a");
629 p = builder->AddPartition("system_a", "foo_a", 0);
630 ASSERT_TRUE(p && builder->ResizePartition(p, 3_GiB));
631 p = builder->AddPartition("vendor_a", "foo_a", 0);
632 ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
633 }
634
TEST_F(BuilderTest,ListGroups)635 TEST_F(BuilderTest, ListGroups) {
636 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
637 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
638 ASSERT_NE(builder, nullptr);
639 ASSERT_TRUE(builder->AddGroup("example", 0));
640
641 std::vector<std::string> groups = builder->ListGroups();
642 ASSERT_THAT(groups, ElementsAre("default", "example"));
643 }
644
TEST_F(BuilderTest,RemoveGroupAndPartitions)645 TEST_F(BuilderTest, RemoveGroupAndPartitions) {
646 BlockDeviceInfo device_info("super", 1024 * 1024, 0, 0, 4096);
647 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
648 ASSERT_NE(builder, nullptr);
649 ASSERT_TRUE(builder->AddGroup("example", 0));
650 ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
651 ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
652
653 builder->RemoveGroupAndPartitions("example");
654 ASSERT_NE(builder->FindPartition("system"), nullptr);
655 ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
656 ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
657
658 builder->RemoveGroupAndPartitions("default");
659 ASSERT_NE(builder->FindPartition("system"), nullptr);
660 }
661
TEST_F(BuilderTest,MultipleBlockDevices)662 TEST_F(BuilderTest, MultipleBlockDevices) {
663 std::vector<BlockDeviceInfo> partitions = {
664 BlockDeviceInfo("system_a", 256_MiB, 786432, 229376, 4096),
665 BlockDeviceInfo("vendor_a", 128_MiB, 786432, 753664, 4096),
666 BlockDeviceInfo("product_a", 64_MiB, 786432, 753664, 4096),
667 };
668 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(partitions, "system_a", 65536, 2);
669 ASSERT_NE(builder, nullptr);
670 EXPECT_EQ(builder->AllocatableSpace(), 467238912);
671
672 // Create a partition that spans 3 devices.
673 Partition* p = builder->AddPartition("system_a", 0);
674 ASSERT_NE(p, nullptr);
675 ASSERT_TRUE(builder->ResizePartition(p, 466976768));
676
677 unique_ptr<LpMetadata> metadata = builder->Export();
678 ASSERT_NE(metadata, nullptr);
679 ASSERT_EQ(metadata->block_devices.size(), 3);
680 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "system_a");
681 EXPECT_EQ(metadata->block_devices[0].size, 256_MiB);
682 EXPECT_EQ(metadata->block_devices[0].alignment, 786432);
683 EXPECT_EQ(metadata->block_devices[0].alignment_offset, 229376);
684 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[1]), "vendor_a");
685 EXPECT_EQ(metadata->block_devices[1].size, 128_MiB);
686 EXPECT_EQ(metadata->block_devices[1].alignment, 786432);
687 EXPECT_EQ(metadata->block_devices[1].alignment_offset, 753664);
688 EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[2]), "product_a");
689 EXPECT_EQ(metadata->block_devices[2].size, 64_MiB);
690 EXPECT_EQ(metadata->block_devices[2].alignment, 786432);
691 EXPECT_EQ(metadata->block_devices[2].alignment_offset, 753664);
692 ASSERT_EQ(metadata->extents.size(), 3);
693 EXPECT_EQ(metadata->extents[0].num_sectors, 522304);
694 EXPECT_EQ(metadata->extents[0].target_type, LP_TARGET_TYPE_LINEAR);
695 EXPECT_EQ(metadata->extents[0].target_data, 1984);
696 EXPECT_EQ(metadata->extents[0].target_source, 0);
697 EXPECT_EQ(metadata->extents[1].num_sectors, 260672);
698 EXPECT_EQ(metadata->extents[1].target_type, LP_TARGET_TYPE_LINEAR);
699 EXPECT_EQ(metadata->extents[1].target_data, 1472);
700 EXPECT_EQ(metadata->extents[1].target_source, 1);
701 EXPECT_EQ(metadata->extents[2].num_sectors, 129088);
702 EXPECT_EQ(metadata->extents[2].target_type, LP_TARGET_TYPE_LINEAR);
703 EXPECT_EQ(metadata->extents[2].target_data, 1472);
704 EXPECT_EQ(metadata->extents[2].target_source, 2);
705 }
706
TEST_F(BuilderTest,ImportPartitionsOk)707 TEST_F(BuilderTest, ImportPartitionsOk) {
708 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
709 ASSERT_NE(builder, nullptr);
710
711 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
712 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
713 ASSERT_NE(system, nullptr);
714 ASSERT_NE(vendor, nullptr);
715 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
716 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
717 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
718
719 unique_ptr<LpMetadata> exported = builder->Export();
720 ASSERT_NE(exported, nullptr);
721
722 builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
723 ASSERT_NE(builder, nullptr);
724
725 ASSERT_TRUE(builder->ImportPartitions(*exported.get(), {"vendor"}));
726 EXPECT_NE(builder->FindPartition("vendor"), nullptr);
727 EXPECT_EQ(builder->FindPartition("system"), nullptr);
728
729 unique_ptr<LpMetadata> new_metadata = builder->Export();
730 ASSERT_NE(new_metadata, nullptr);
731
732 ASSERT_EQ(exported->partitions.size(), static_cast<size_t>(2));
733 ASSERT_EQ(GetPartitionName(exported->partitions[1]), "vendor");
734 ASSERT_EQ(new_metadata->partitions.size(), static_cast<size_t>(1));
735 ASSERT_EQ(GetPartitionName(new_metadata->partitions[0]), "vendor");
736
737 const LpMetadataExtent& extent_a =
738 exported->extents[exported->partitions[1].first_extent_index];
739 const LpMetadataExtent& extent_b =
740 new_metadata->extents[new_metadata->partitions[0].first_extent_index];
741 EXPECT_EQ(extent_a.num_sectors, extent_b.num_sectors);
742 EXPECT_EQ(extent_a.target_type, extent_b.target_type);
743 EXPECT_EQ(extent_a.target_data, extent_b.target_data);
744 EXPECT_EQ(extent_a.target_source, extent_b.target_source);
745 }
746
TEST_F(BuilderTest,ImportPartitionsFail)747 TEST_F(BuilderTest, ImportPartitionsFail) {
748 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
749 ASSERT_NE(builder, nullptr);
750
751 Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_READONLY);
752 Partition* vendor = builder->AddPartition("vendor", LP_PARTITION_ATTR_READONLY);
753 ASSERT_NE(system, nullptr);
754 ASSERT_NE(vendor, nullptr);
755 EXPECT_EQ(builder->ResizePartition(system, 65536), true);
756 EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
757 EXPECT_EQ(builder->ResizePartition(system, 98304), true);
758
759 unique_ptr<LpMetadata> exported = builder->Export();
760 ASSERT_NE(exported, nullptr);
761
762 // Different device size.
763 builder = MetadataBuilder::New(1024 * 2048, 1024, 2);
764 ASSERT_NE(builder, nullptr);
765 EXPECT_FALSE(builder->ImportPartitions(*exported.get(), {"system"}));
766 }
767
TEST_F(BuilderTest,UnsuffixedPartitions)768 TEST_F(BuilderTest, UnsuffixedPartitions) {
769 MetadataBuilder::OverrideABForTesting(true);
770 unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
771 ASSERT_NE(builder, nullptr);
772
773 ASSERT_EQ(builder->AddPartition("system", 0), nullptr);
774 ASSERT_NE(builder->AddPartition("system_a", 0), nullptr);
775 }
776
TEST_F(BuilderTest,ABExtents)777 TEST_F(BuilderTest, ABExtents) {
778 BlockDeviceInfo device_info("super", 10_GiB, 768 * 1024, 0, 4096);
779
780 // A and B slots should be allocated from separate halves of the partition,
781 // to mitigate allocating too many extents. (b/120433288)
782 MetadataBuilder::OverrideABForTesting(true);
783 auto builder = MetadataBuilder::New(device_info, 65536, 2);
784 ASSERT_NE(builder, nullptr);
785 Partition* system_a = builder->AddPartition("system_a", 0);
786 ASSERT_NE(system_a, nullptr);
787 Partition* system_b = builder->AddPartition("system_b", 0);
788 ASSERT_NE(system_b, nullptr);
789 ASSERT_TRUE(builder->ResizePartition(system_a, 2_GiB));
790 ASSERT_TRUE(builder->ResizePartition(system_b, 2_GiB));
791
792 builder->RemovePartition("system_a");
793 system_a = builder->AddPartition("system_a", 0);
794 ASSERT_NE(system_a, nullptr);
795 ASSERT_TRUE(builder->ResizePartition(system_a, 3_GiB));
796
797 EXPECT_EQ(system_a->extents().size(), static_cast<size_t>(1));
798 EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(1));
799 ASSERT_TRUE(builder->ResizePartition(system_b, 6_GiB));
800 EXPECT_EQ(system_b->extents().size(), static_cast<size_t>(2));
801
802 unique_ptr<LpMetadata> exported = builder->Export();
803 ASSERT_NE(exported, nullptr);
804 ASSERT_EQ(exported->extents.size(), static_cast<size_t>(3));
805 EXPECT_EQ(exported->extents[0].target_data, 10487808);
806 EXPECT_EQ(exported->extents[0].num_sectors, 10483712);
807 EXPECT_EQ(exported->extents[1].target_data, 6292992);
808 EXPECT_EQ(exported->extents[1].num_sectors, 2099200);
809 EXPECT_EQ(exported->extents[2].target_data, 1536);
810 EXPECT_EQ(exported->extents[2].num_sectors, 6291456);
811 }
812
TEST_F(BuilderTest,PartialExtents)813 TEST_F(BuilderTest, PartialExtents) {
814 // super has a minimum extent size of 768KiB.
815 BlockDeviceInfo device_info("super", 1_GiB, 768 * 1024, 0, 4096);
816 auto builder = MetadataBuilder::New(device_info, 65536, 1);
817 ASSERT_NE(builder, nullptr);
818 Partition* system = builder->AddPartition("system", 0);
819 ASSERT_NE(system, nullptr);
820 Partition* vendor = builder->AddPartition("vendor", 0);
821 ASSERT_NE(vendor, nullptr);
822 ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment + 4096));
823 ASSERT_TRUE(builder->ResizePartition(vendor, device_info.alignment));
824 ASSERT_EQ(system->size(), device_info.alignment + 4096);
825 ASSERT_EQ(vendor->size(), device_info.alignment);
826
827 ASSERT_TRUE(builder->ResizePartition(system, device_info.alignment * 2));
828 ASSERT_EQ(system->extents().size(), static_cast<size_t>(1));
829
830 unique_ptr<LpMetadata> exported = builder->Export();
831 ASSERT_NE(exported, nullptr);
832 ASSERT_EQ(exported->extents.size(), static_cast<size_t>(2));
833 EXPECT_EQ(exported->extents[0].target_data, 1536);
834 EXPECT_EQ(exported->extents[0].num_sectors, 3072);
835 EXPECT_EQ(exported->extents[1].target_data, 4608);
836 EXPECT_EQ(exported->extents[1].num_sectors, 1536);
837 }
838
TEST_F(BuilderTest,UpdateSuper)839 TEST_F(BuilderTest, UpdateSuper) {
840 // Build the on-disk metadata that we saw before flashing.
841 auto builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
842 ASSERT_NE(builder, nullptr);
843
844 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
845 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
846
847 Partition* partition = builder->AddPartition("system_a", "google_dynamic_partitions_a",
848 LP_PARTITION_ATTR_READONLY);
849 ASSERT_NE(partition, nullptr);
850 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 3608576));
851
852 partition = builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
853 LP_PARTITION_ATTR_READONLY);
854 ASSERT_NE(partition, nullptr);
855 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 5510144));
856
857 partition = builder->AddPartition("product_a", "google_dynamic_partitions_a",
858 LP_PARTITION_ATTR_READONLY);
859 ASSERT_NE(partition, nullptr);
860 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 2048));
861
862 partition = builder->AddPartition("system_b", "google_dynamic_partitions_b",
863 LP_PARTITION_ATTR_READONLY);
864 ASSERT_NE(partition, nullptr);
865 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1901568, 7955456));
866
867 partition = builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
868 LP_PARTITION_ATTR_READONLY);
869 ASSERT_NE(partition, nullptr);
870 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 1521664, 9857024));
871
872 partition = builder->AddPartition("product_b", "google_dynamic_partitions_b",
873 LP_PARTITION_ATTR_READONLY);
874 ASSERT_NE(partition, nullptr);
875 ASSERT_TRUE(builder->AddLinearExtent(partition, "super", 3606528, 11378688));
876
877 auto on_disk = builder->Export();
878 ASSERT_NE(on_disk, nullptr);
879
880 // Build the super_empty from the new build.
881 builder = MetadataBuilder::New(8145338368ULL, 65536, 3);
882 ASSERT_NE(builder, nullptr);
883
884 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_a", 4068474880ULL));
885 ASSERT_TRUE(builder->AddGroup("google_dynamic_partitions_b", 4068474880ULL));
886 ASSERT_NE(builder->AddPartition("system_a", "google_dynamic_partitions_a",
887 LP_PARTITION_ATTR_READONLY),
888 nullptr);
889 ASSERT_NE(builder->AddPartition("system_b", "google_dynamic_partitions_b",
890 LP_PARTITION_ATTR_READONLY),
891 nullptr);
892 ASSERT_NE(builder->AddPartition("vendor_a", "google_dynamic_partitions_a",
893 LP_PARTITION_ATTR_READONLY),
894 nullptr);
895 ASSERT_NE(builder->AddPartition("vendor_b", "google_dynamic_partitions_b",
896 LP_PARTITION_ATTR_READONLY),
897 nullptr);
898 ASSERT_NE(builder->AddPartition("product_a", "google_dynamic_partitions_a",
899 LP_PARTITION_ATTR_READONLY),
900 nullptr);
901 ASSERT_NE(builder->AddPartition("product_b", "google_dynamic_partitions_b",
902 LP_PARTITION_ATTR_READONLY),
903 nullptr);
904
905 std::set<std::string> partitions_to_keep{"system_a", "vendor_a", "product_a"};
906 ASSERT_TRUE(builder->ImportPartitions(*on_disk.get(), partitions_to_keep));
907 }
908