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