1 //
2 // Copyright (C) 2023 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 <liblp/super_layout_builder.h>
21 #include <storage_literals/storage_literals.h>
22
23 #include "images.h"
24 #include "writer.h"
25
26 using namespace android::fs_mgr;
27 using namespace android::storage_literals;
28
TEST(SuperImageTool,Layout)29 TEST(SuperImageTool, Layout) {
30 auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
31 ASSERT_NE(builder, nullptr);
32
33 Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
34 ASSERT_NE(p, nullptr);
35
36 auto metadata = builder->Export();
37 ASSERT_NE(metadata, nullptr);
38
39 SuperLayoutBuilder tool;
40 ASSERT_TRUE(tool.Open(*metadata.get()));
41 ASSERT_TRUE(tool.AddPartition("system_a", "system.img", 16_KiB));
42
43 // Get a copy of the metadata we'd expect if flashing.
44 ASSERT_TRUE(builder->ResizePartition(p, 16_KiB));
45 metadata = builder->Export();
46 ASSERT_NE(metadata, nullptr);
47
48 auto geometry_blob = std::make_shared<std::string>(SerializeGeometry(metadata->geometry));
49 auto metadata_blob = std::make_shared<std::string>(SerializeMetadata(*metadata.get()));
50 metadata_blob->resize(4_KiB, '\0');
51
52 auto extents = tool.GetImageLayout();
53 ASSERT_EQ(extents.size(), 12);
54 EXPECT_EQ(extents[0], SuperImageExtent(0, 4096, SuperImageExtent::Type::ZERO));
55 EXPECT_EQ(extents[1], SuperImageExtent(4096, geometry_blob));
56 EXPECT_EQ(extents[2], SuperImageExtent(8192, geometry_blob));
57 EXPECT_EQ(extents[3], SuperImageExtent(12288, metadata_blob));
58 EXPECT_EQ(extents[4], SuperImageExtent(16384, 4096, SuperImageExtent::Type::DONTCARE));
59 EXPECT_EQ(extents[5], SuperImageExtent(20480, metadata_blob));
60 EXPECT_EQ(extents[6], SuperImageExtent(24576, 4096, SuperImageExtent::Type::DONTCARE));
61 EXPECT_EQ(extents[7], SuperImageExtent(28672, metadata_blob));
62 EXPECT_EQ(extents[8], SuperImageExtent(32768, 4096, SuperImageExtent::Type::DONTCARE));
63 EXPECT_EQ(extents[9], SuperImageExtent(36864, metadata_blob));
64 EXPECT_EQ(extents[10], SuperImageExtent(40960, 4096, SuperImageExtent::Type::DONTCARE));
65 EXPECT_EQ(extents[11], SuperImageExtent(45056, 16384, "system.img", 0));
66 }
67
TEST(SuperImageTool,NoWritablePartitions)68 TEST(SuperImageTool, NoWritablePartitions) {
69 auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
70 ASSERT_NE(builder, nullptr);
71
72 Partition* p = builder->AddPartition("system_a", 0);
73 ASSERT_NE(p, nullptr);
74
75 auto metadata = builder->Export();
76 ASSERT_NE(metadata, nullptr);
77
78 SuperLayoutBuilder tool;
79 ASSERT_FALSE(tool.Open(*metadata.get()));
80 }
81
TEST(SuperImageTool,NoRetrofit)82 TEST(SuperImageTool, NoRetrofit) {
83 auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
84 ASSERT_NE(builder, nullptr);
85
86 Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
87 ASSERT_NE(p, nullptr);
88
89 auto metadata = builder->Export();
90 ASSERT_NE(metadata, nullptr);
91
92 // Add an extra block device.
93 metadata->block_devices.emplace_back(metadata->block_devices[0]);
94
95 SuperLayoutBuilder tool;
96 ASSERT_FALSE(tool.Open(*metadata.get()));
97 }
98
TEST(SuperImageTool,NoRetrofit2)99 TEST(SuperImageTool, NoRetrofit2) {
100 auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
101 ASSERT_NE(builder, nullptr);
102
103 Partition* p = builder->AddPartition(
104 "system_a", LP_PARTITION_ATTR_READONLY | LP_PARTITION_ATTR_SLOT_SUFFIXED);
105 ASSERT_NE(p, nullptr);
106
107 auto metadata = builder->Export();
108 ASSERT_NE(metadata, nullptr);
109
110 SuperLayoutBuilder tool;
111 ASSERT_FALSE(tool.Open(*metadata.get()));
112 }
113
TEST(SuperImageTool,NoFixedPartitions)114 TEST(SuperImageTool, NoFixedPartitions) {
115 auto builder = MetadataBuilder::New(4_MiB, 8_KiB, 2);
116 ASSERT_NE(builder, nullptr);
117
118 Partition* p = builder->AddPartition("system_a", LP_PARTITION_ATTR_READONLY);
119 ASSERT_NE(p, nullptr);
120 ASSERT_TRUE(builder->ResizePartition(p, 4_KiB));
121
122 auto metadata = builder->Export();
123 ASSERT_NE(metadata, nullptr);
124
125 SuperLayoutBuilder tool;
126 ASSERT_FALSE(tool.Open(*metadata.get()));
127 }
128
TEST(SuperImageTool,LargeAlignedMetadata)129 TEST(SuperImageTool, LargeAlignedMetadata) {
130 auto builder = MetadataBuilder::New(4_MiB, 512, 2);
131 ASSERT_NE(builder, nullptr);
132
133 auto metadata = builder->Export();
134 ASSERT_NE(metadata, nullptr);
135
136 SuperLayoutBuilder tool;
137 ASSERT_TRUE(tool.Open(*metadata.get()));
138
139 auto extents = tool.GetImageLayout();
140 ASSERT_TRUE(extents.empty());
141 }
142