blob: 3e0320d2201ea276305477a008a482311131255e [file] [log] [blame]
Yifan Hong537802d2018-08-15 13:15:42 -07001//
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 "update_engine/boot_control_android.h"
18
19#include <set>
Yifan Hongd4db07e2018-10-18 17:46:27 -070020#include <vector>
Yifan Hong537802d2018-08-15 13:15:42 -070021
Yifan Hongd4db07e2018-10-18 17:46:27 -070022#include <base/logging.h>
23#include <base/strings/string_util.h>
David Andersond63cb3c2018-10-01 14:15:00 -070024#include <fs_mgr.h>
Yifan Hong537802d2018-08-15 13:15:42 -070025#include <gmock/gmock.h>
26#include <gtest/gtest.h>
Yifan Hong1d9077f2018-12-07 12:09:37 -080027#include <libdm/dm.h>
Yifan Hong537802d2018-08-15 13:15:42 -070028
29#include "update_engine/mock_boot_control_hal.h"
30#include "update_engine/mock_dynamic_partition_control.h"
31
Yifan Hong1d9077f2018-12-07 12:09:37 -080032using android::dm::DmDeviceState;
Yifan Hong537802d2018-08-15 13:15:42 -070033using android::fs_mgr::MetadataBuilder;
34using android::hardware::Void;
Dan Albertfcfbda22018-12-14 12:57:55 -080035using std::string;
Yifan Hong537802d2018-08-15 13:15:42 -070036using testing::_;
37using testing::AnyNumber;
38using testing::Contains;
39using testing::Eq;
40using testing::Invoke;
41using testing::Key;
42using testing::MakeMatcher;
43using testing::Matcher;
44using testing::MatcherInterface;
45using testing::MatchResultListener;
46using testing::NiceMock;
Yifan Hongd4db07e2018-10-18 17:46:27 -070047using testing::Not;
Yifan Hong537802d2018-08-15 13:15:42 -070048using testing::Return;
49
50namespace chromeos_update_engine {
51
52constexpr const uint32_t kMaxNumSlots = 2;
53constexpr const char* kSlotSuffixes[kMaxNumSlots] = {"_a", "_b"};
54constexpr const char* kFakeDevicePath = "/fake/dev/path/";
Yifan Hong1d9077f2018-12-07 12:09:37 -080055constexpr const char* kFakeDmDevicePath = "/fake/dm/dev/path/";
Yifan Hong537802d2018-08-15 13:15:42 -070056constexpr const uint32_t kFakeMetadataSize = 65536;
Yifan Hongd4db07e2018-10-18 17:46:27 -070057constexpr const char* kDefaultGroup = "foo";
58
Yifan Hong537802d2018-08-15 13:15:42 -070059// A map describing the size of each partition.
Dan Albertfcfbda22018-12-14 12:57:55 -080060// "{name, size}"
61using PartitionSizes = std::map<string, uint64_t>;
62
63// "{name_a, size}"
64using PartitionSuffixSizes = std::map<string, uint64_t>;
Yifan Hongd4db07e2018-10-18 17:46:27 -070065
66using PartitionMetadata = BootControlInterface::PartitionMetadata;
Yifan Hong537802d2018-08-15 13:15:42 -070067
68// C++ standards do not allow uint64_t (aka unsigned long) to be the parameter
69// of user-defined literal operators.
Yifan Hongd4db07e2018-10-18 17:46:27 -070070constexpr unsigned long long operator"" _MiB(unsigned long long x) { // NOLINT
Yifan Hong537802d2018-08-15 13:15:42 -070071 return x << 20;
72}
Yifan Hongd4db07e2018-10-18 17:46:27 -070073constexpr unsigned long long operator"" _GiB(unsigned long long x) { // NOLINT
Yifan Hong537802d2018-08-15 13:15:42 -070074 return x << 30;
75}
76
Yifan Hongd4db07e2018-10-18 17:46:27 -070077constexpr uint64_t kDefaultGroupSize = 5_GiB;
78// Super device size. 1 MiB for metadata.
79constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
80
Yifan Hong537802d2018-08-15 13:15:42 -070081template <typename U, typename V>
82std::ostream& operator<<(std::ostream& os, const std::map<U, V>& param) {
83 os << "{";
84 bool first = true;
85 for (const auto& pair : param) {
86 if (!first)
87 os << ", ";
88 os << pair.first << ":" << pair.second;
89 first = false;
90 }
91 return os << "}";
92}
93
Yifan Hongd4db07e2018-10-18 17:46:27 -070094template <typename T>
95std::ostream& operator<<(std::ostream& os, const std::vector<T>& param) {
96 os << "[";
97 bool first = true;
98 for (const auto& e : param) {
99 if (!first)
100 os << ", ";
101 os << e;
102 first = false;
103 }
104 return os << "]";
105}
106
107std::ostream& operator<<(std::ostream& os,
108 const PartitionMetadata::Partition& p) {
109 return os << "{" << p.name << ", " << p.size << "}";
110}
111
112std::ostream& operator<<(std::ostream& os, const PartitionMetadata::Group& g) {
113 return os << "{" << g.name << ", " << g.size << ", " << g.partitions << "}";
114}
115
116std::ostream& operator<<(std::ostream& os, const PartitionMetadata& m) {
117 return os << m.groups;
118}
119
Dan Albertfcfbda22018-12-14 12:57:55 -0800120inline string GetDevice(const string& name) {
Yifan Hong537802d2018-08-15 13:15:42 -0700121 return kFakeDevicePath + name;
122}
Yifan Hong30eb7b52018-11-20 11:05:46 -0800123
Dan Albertfcfbda22018-12-14 12:57:55 -0800124inline string GetDmDevice(const string& name) {
Yifan Hong1d9077f2018-12-07 12:09:37 -0800125 return kFakeDmDevicePath + name;
126}
127
Yifan Hong30eb7b52018-11-20 11:05:46 -0800128// TODO(elsk): fs_mgr_get_super_partition_name should be mocked.
Dan Albertfcfbda22018-12-14 12:57:55 -0800129inline string GetSuperDevice(uint32_t slot) {
Yifan Hong30eb7b52018-11-20 11:05:46 -0800130 return GetDevice(fs_mgr_get_super_partition_name(slot));
Yifan Hong537802d2018-08-15 13:15:42 -0700131}
132
133struct TestParam {
134 uint32_t source;
135 uint32_t target;
136};
137std::ostream& operator<<(std::ostream& os, const TestParam& param) {
138 return os << "{source: " << param.source << ", target:" << param.target
139 << "}";
140}
141
Yifan Hongd4db07e2018-10-18 17:46:27 -0700142// To support legacy tests, auto-convert {name_a: size} map to
143// PartitionMetadata.
Dan Albertfcfbda22018-12-14 12:57:55 -0800144PartitionMetadata partitionSuffixSizesToMetadata(
145 const PartitionSuffixSizes& partition_sizes) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700146 PartitionMetadata metadata;
147 for (const char* suffix : kSlotSuffixes) {
148 metadata.groups.push_back(
Dan Albertfcfbda22018-12-14 12:57:55 -0800149 {string(kDefaultGroup) + suffix, kDefaultGroupSize, {}});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700150 }
151 for (const auto& pair : partition_sizes) {
152 for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
153 if (base::EndsWith(pair.first,
154 kSlotSuffixes[suffix_idx],
155 base::CompareCase::SENSITIVE)) {
156 metadata.groups[suffix_idx].partitions.push_back(
157 {pair.first, pair.second});
158 }
159 }
160 }
161 return metadata;
162}
163
164// To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
Dan Albertfcfbda22018-12-14 12:57:55 -0800165PartitionMetadata partitionSizesToMetadata(
166 const PartitionSizes& partition_sizes) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700167 PartitionMetadata metadata;
Dan Albertfcfbda22018-12-14 12:57:55 -0800168 metadata.groups.push_back({string{kDefaultGroup}, kDefaultGroupSize, {}});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700169 for (const auto& pair : partition_sizes) {
170 metadata.groups[0].partitions.push_back({pair.first, pair.second});
171 }
172 return metadata;
173}
174
175std::unique_ptr<MetadataBuilder> NewFakeMetadata(
176 const PartitionMetadata& metadata) {
177 auto builder =
178 MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
179 EXPECT_GE(builder->AllocatableSpace(), kDefaultGroupSize * 2);
Yifan Hong537802d2018-08-15 13:15:42 -0700180 EXPECT_NE(nullptr, builder);
181 if (builder == nullptr)
182 return nullptr;
Yifan Hongd4db07e2018-10-18 17:46:27 -0700183 for (const auto& group : metadata.groups) {
184 EXPECT_TRUE(builder->AddGroup(group.name, group.size));
185 for (const auto& partition : group.partitions) {
186 auto p = builder->AddPartition(partition.name, group.name, 0 /* attr */);
187 EXPECT_TRUE(p && builder->ResizePartition(p, partition.size));
188 }
Yifan Hong537802d2018-08-15 13:15:42 -0700189 }
190 return builder;
191}
192
193class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
194 public:
Yifan Hongd4db07e2018-10-18 17:46:27 -0700195 explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
Dan Albertfcfbda22018-12-14 12:57:55 -0800196 : partition_metadata_(partitionSuffixSizesToMetadata(partition_sizes)) {}
Yifan Hongd4db07e2018-10-18 17:46:27 -0700197 explicit MetadataMatcher(const PartitionMetadata& partition_metadata)
198 : partition_metadata_(partition_metadata) {}
199
Yifan Hong537802d2018-08-15 13:15:42 -0700200 bool MatchAndExplain(MetadataBuilder* metadata,
201 MatchResultListener* listener) const override {
202 bool success = true;
Yifan Hongd4db07e2018-10-18 17:46:27 -0700203 for (const auto& group : partition_metadata_.groups) {
204 for (const auto& partition : group.partitions) {
205 auto p = metadata->FindPartition(partition.name);
206 if (p == nullptr) {
207 if (!success)
208 *listener << "; ";
209 *listener << "No partition " << partition.name;
210 success = false;
211 continue;
212 }
213 if (p->size() != partition.size) {
214 if (!success)
215 *listener << "; ";
216 *listener << "Partition " << partition.name << " has size "
217 << p->size() << ", expected " << partition.size;
218 success = false;
219 }
220 if (p->group_name() != group.name) {
221 if (!success)
222 *listener << "; ";
223 *listener << "Partition " << partition.name << " has group "
224 << p->group_name() << ", expected " << group.name;
225 success = false;
226 }
Yifan Hong537802d2018-08-15 13:15:42 -0700227 }
228 }
229 return success;
230 }
231
232 void DescribeTo(std::ostream* os) const override {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700233 *os << "expect: " << partition_metadata_;
Yifan Hong537802d2018-08-15 13:15:42 -0700234 }
235
236 void DescribeNegationTo(std::ostream* os) const override {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700237 *os << "expect not: " << partition_metadata_;
Yifan Hong537802d2018-08-15 13:15:42 -0700238 }
239
240 private:
Yifan Hongd4db07e2018-10-18 17:46:27 -0700241 PartitionMetadata partition_metadata_;
Yifan Hong537802d2018-08-15 13:15:42 -0700242};
243
244inline Matcher<MetadataBuilder*> MetadataMatches(
Yifan Hongd4db07e2018-10-18 17:46:27 -0700245 const PartitionSuffixSizes& partition_sizes) {
Yifan Hong537802d2018-08-15 13:15:42 -0700246 return MakeMatcher(new MetadataMatcher(partition_sizes));
247}
248
Yifan Hongd4db07e2018-10-18 17:46:27 -0700249inline Matcher<MetadataBuilder*> MetadataMatches(
250 const PartitionMetadata& partition_metadata) {
251 return MakeMatcher(new MetadataMatcher(partition_metadata));
252}
253
254MATCHER_P(HasGroup, group, " has group " + group) {
255 auto groups = arg->ListGroups();
256 return std::find(groups.begin(), groups.end(), group) != groups.end();
257}
258
Yifan Hong537802d2018-08-15 13:15:42 -0700259class BootControlAndroidTest : public ::testing::Test {
260 protected:
261 void SetUp() override {
262 // Fake init bootctl_
263 bootctl_.module_ = new NiceMock<MockBootControlHal>();
264 bootctl_.dynamic_control_ =
Yifan Hong012508e2019-07-22 18:30:40 -0700265 std::make_unique<NiceMock<MockDynamicPartitionControlAndroid>>();
Yifan Hong537802d2018-08-15 13:15:42 -0700266
267 ON_CALL(module(), getNumberSlots()).WillByDefault(Invoke([] {
268 return kMaxNumSlots;
269 }));
270 ON_CALL(module(), getSuffix(_, _))
271 .WillByDefault(Invoke([](auto slot, auto cb) {
272 EXPECT_LE(slot, kMaxNumSlots);
273 cb(slot < kMaxNumSlots ? kSlotSuffixes[slot] : "");
274 return Void();
275 }));
276
Yifan Hong186bb682019-07-23 14:04:39 -0700277 ON_CALL(dynamicControl(), GetDynamicPartitionsFeatureFlag())
278 .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::LAUNCH)));
Yifan Hong1d9077f2018-12-07 12:09:37 -0800279 ON_CALL(dynamicControl(), DeviceExists(_)).WillByDefault(Return(true));
Yifan Hong537802d2018-08-15 13:15:42 -0700280 ON_CALL(dynamicControl(), GetDeviceDir(_))
281 .WillByDefault(Invoke([](auto path) {
282 *path = kFakeDevicePath;
283 return true;
284 }));
Yifan Hong1d9077f2018-12-07 12:09:37 -0800285 ON_CALL(dynamicControl(), GetDmDevicePathByName(_, _))
286 .WillByDefault(Invoke([](auto partition_name_suffix, auto device) {
287 *device = GetDmDevice(partition_name_suffix);
288 return true;
289 }));
Yifan Hong537802d2018-08-15 13:15:42 -0700290 }
291
292 // Return the mocked HAL module.
293 NiceMock<MockBootControlHal>& module() {
294 return static_cast<NiceMock<MockBootControlHal>&>(*bootctl_.module_);
295 }
296
297 // Return the mocked DynamicPartitionControlInterface.
Yifan Hong012508e2019-07-22 18:30:40 -0700298 NiceMock<MockDynamicPartitionControlAndroid>& dynamicControl() {
299 return static_cast<NiceMock<MockDynamicPartitionControlAndroid>&>(
Yifan Hong537802d2018-08-15 13:15:42 -0700300 *bootctl_.dynamic_control_);
301 }
302
303 // Set the fake metadata to return when LoadMetadataBuilder is called on
304 // |slot|.
Yifan Hongd4db07e2018-10-18 17:46:27 -0700305 void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
Dan Albertfcfbda22018-12-14 12:57:55 -0800306 SetMetadata(slot, partitionSuffixSizesToMetadata(sizes));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700307 }
308
309 void SetMetadata(uint32_t slot, const PartitionMetadata& metadata) {
Yifan Hong6e706b12018-11-09 16:50:51 -0800310 EXPECT_CALL(dynamicControl(),
Yifan Hong30eb7b52018-11-20 11:05:46 -0800311 LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
Yifan Hongd4db07e2018-10-18 17:46:27 -0700312 .Times(AnyNumber())
Yifan Hong6e706b12018-11-09 16:50:51 -0800313 .WillRepeatedly(Invoke([metadata](auto, auto, auto) {
314 return NewFakeMetadata(metadata);
315 }));
Yifan Hong537802d2018-08-15 13:15:42 -0700316 }
317
Yifan Hong537802d2018-08-15 13:15:42 -0700318 // Expect that UnmapPartitionOnDeviceMapper is called on target() metadata
319 // slot with each partition in |partitions|.
Dan Albertfcfbda22018-12-14 12:57:55 -0800320 void ExpectUnmap(const std::set<string>& partitions) {
Yifan Hong537802d2018-08-15 13:15:42 -0700321 // Error when UnmapPartitionOnDeviceMapper is called on unknown arguments.
David Anderson4c891c92019-06-21 17:45:23 -0700322 ON_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_))
Yifan Hong537802d2018-08-15 13:15:42 -0700323 .WillByDefault(Return(false));
324
325 for (const auto& partition : partitions) {
David Anderson4c891c92019-06-21 17:45:23 -0700326 EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(partition))
327 .WillOnce(Invoke([this](auto partition) {
Yifan Hong537802d2018-08-15 13:15:42 -0700328 mapped_devices_.erase(partition);
329 return true;
330 }));
331 }
332 }
333
Dan Albertfcfbda22018-12-14 12:57:55 -0800334 void ExpectDevicesAreMapped(const std::set<string>& partitions) {
Yifan Hong537802d2018-08-15 13:15:42 -0700335 ASSERT_EQ(partitions.size(), mapped_devices_.size());
336 for (const auto& partition : partitions) {
337 EXPECT_THAT(mapped_devices_, Contains(Key(Eq(partition))))
338 << "Expect that " << partition << " is mapped, but it is not.";
339 }
340 }
341
Yifan Hongd4db07e2018-10-18 17:46:27 -0700342 void ExpectStoreMetadata(const PartitionSuffixSizes& partition_sizes) {
Yifan Hong549eb362018-10-19 15:11:12 -0700343 ExpectStoreMetadataMatch(MetadataMatches(partition_sizes));
344 }
345
346 virtual void ExpectStoreMetadataMatch(
347 const Matcher<MetadataBuilder*>& matcher) {
348 EXPECT_CALL(dynamicControl(),
Yifan Hong30eb7b52018-11-20 11:05:46 -0800349 StoreMetadata(GetSuperDevice(target()), matcher, target()))
Yifan Hong549eb362018-10-19 15:11:12 -0700350 .WillOnce(Return(true));
351 }
352
Yifan Hong537802d2018-08-15 13:15:42 -0700353 uint32_t source() { return slots_.source; }
354
355 uint32_t target() { return slots_.target; }
356
357 // Return partition names with suffix of source().
Dan Albertfcfbda22018-12-14 12:57:55 -0800358 string S(const string& name) { return name + kSlotSuffixes[source()]; }
Yifan Hong537802d2018-08-15 13:15:42 -0700359
360 // Return partition names with suffix of target().
Dan Albertfcfbda22018-12-14 12:57:55 -0800361 string T(const string& name) { return name + kSlotSuffixes[target()]; }
Yifan Hong537802d2018-08-15 13:15:42 -0700362
363 // Set source and target slots to use before testing.
364 void SetSlots(const TestParam& slots) {
365 slots_ = slots;
366
367 ON_CALL(module(), getCurrentSlot()).WillByDefault(Invoke([this] {
368 return source();
369 }));
370 // Should not store metadata to source slot.
Yifan Hong30eb7b52018-11-20 11:05:46 -0800371 EXPECT_CALL(dynamicControl(),
372 StoreMetadata(GetSuperDevice(source()), _, source()))
Yifan Hong537802d2018-08-15 13:15:42 -0700373 .Times(0);
Yifan Hongd4db07e2018-10-18 17:46:27 -0700374 // Should not load metadata from target slot.
375 EXPECT_CALL(dynamicControl(),
Yifan Hong30eb7b52018-11-20 11:05:46 -0800376 LoadMetadataBuilder(GetSuperDevice(target()), target(), _))
Yifan Hongd4db07e2018-10-18 17:46:27 -0700377 .Times(0);
378 }
379
Tao Bao3406c772019-01-02 15:34:35 -0800380 bool InitPartitionMetadata(uint32_t slot,
381 PartitionSizes partition_sizes,
382 bool update_metadata = true) {
Dan Albertfcfbda22018-12-14 12:57:55 -0800383 auto m = partitionSizesToMetadata(partition_sizes);
Yifan Hongd4db07e2018-10-18 17:46:27 -0700384 LOG(INFO) << m;
Tao Bao3406c772019-01-02 15:34:35 -0800385 return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
Yifan Hong537802d2018-08-15 13:15:42 -0700386 }
387
388 BootControlAndroid bootctl_; // BootControlAndroid under test.
389 TestParam slots_;
390 // mapped devices through MapPartitionOnDeviceMapper.
Dan Albertfcfbda22018-12-14 12:57:55 -0800391 std::map<string, string> mapped_devices_;
Yifan Hong537802d2018-08-15 13:15:42 -0700392};
393
394class BootControlAndroidTestP
395 : public BootControlAndroidTest,
396 public ::testing::WithParamInterface<TestParam> {
397 public:
398 void SetUp() override {
399 BootControlAndroidTest::SetUp();
400 SetSlots(GetParam());
401 }
402};
403
Yifan Hong537802d2018-08-15 13:15:42 -0700404// Test resize case. Grow if target metadata contains a partition with a size
405// less than expected.
406TEST_P(BootControlAndroidTestP, NeedGrowIfSizeNotMatchWhenResizing) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700407 SetMetadata(source(),
408 {{S("system"), 2_GiB},
409 {S("vendor"), 1_GiB},
410 {T("system"), 2_GiB},
411 {T("vendor"), 1_GiB}});
Yifan Hong549eb362018-10-19 15:11:12 -0700412 ExpectStoreMetadata({{S("system"), 2_GiB},
413 {S("vendor"), 1_GiB},
414 {T("system"), 3_GiB},
415 {T("vendor"), 1_GiB}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800416 ExpectUnmap({T("system"), T("vendor")});
Yifan Hong537802d2018-08-15 13:15:42 -0700417
Yifan Hongd4db07e2018-10-18 17:46:27 -0700418 EXPECT_TRUE(
419 InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 1_GiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700420}
421
422// Test resize case. Shrink if target metadata contains a partition with a size
423// greater than expected.
424TEST_P(BootControlAndroidTestP, NeedShrinkIfSizeNotMatchWhenResizing) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700425 SetMetadata(source(),
426 {{S("system"), 2_GiB},
427 {S("vendor"), 1_GiB},
428 {T("system"), 2_GiB},
429 {T("vendor"), 1_GiB}});
Yifan Hong549eb362018-10-19 15:11:12 -0700430 ExpectStoreMetadata({{S("system"), 2_GiB},
431 {S("vendor"), 1_GiB},
432 {T("system"), 2_GiB},
433 {T("vendor"), 150_MiB}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800434 ExpectUnmap({T("system"), T("vendor")});
Yifan Hong537802d2018-08-15 13:15:42 -0700435
Yifan Hongd4db07e2018-10-18 17:46:27 -0700436 EXPECT_TRUE(InitPartitionMetadata(target(),
437 {{"system", 2_GiB}, {"vendor", 150_MiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700438}
439
440// Test adding partitions on the first run.
441TEST_P(BootControlAndroidTestP, AddPartitionToEmptyMetadata) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700442 SetMetadata(source(), PartitionSuffixSizes{});
Yifan Hong549eb362018-10-19 15:11:12 -0700443 ExpectStoreMetadata({{T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800444 ExpectUnmap({T("system"), T("vendor")});
Yifan Hong537802d2018-08-15 13:15:42 -0700445
Yifan Hongd4db07e2018-10-18 17:46:27 -0700446 EXPECT_TRUE(
447 InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700448}
449
450// Test subsequent add case.
451TEST_P(BootControlAndroidTestP, AddAdditionalPartition) {
452 SetMetadata(source(), {{S("system"), 2_GiB}, {T("system"), 2_GiB}});
Yifan Hong549eb362018-10-19 15:11:12 -0700453 ExpectStoreMetadata(
454 {{S("system"), 2_GiB}, {T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800455 ExpectUnmap({T("system"), T("vendor")});
Yifan Hong537802d2018-08-15 13:15:42 -0700456
Yifan Hongd4db07e2018-10-18 17:46:27 -0700457 EXPECT_TRUE(
458 InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700459}
460
461// Test delete one partition.
462TEST_P(BootControlAndroidTestP, DeletePartition) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700463 SetMetadata(source(),
464 {{S("system"), 2_GiB},
465 {S("vendor"), 1_GiB},
466 {T("system"), 2_GiB},
467 {T("vendor"), 1_GiB}});
468 // No T("vendor")
469 ExpectStoreMetadata(
470 {{S("system"), 2_GiB}, {S("vendor"), 1_GiB}, {T("system"), 2_GiB}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800471 ExpectUnmap({T("system")});
Yifan Hong537802d2018-08-15 13:15:42 -0700472
Yifan Hongd4db07e2018-10-18 17:46:27 -0700473 EXPECT_TRUE(InitPartitionMetadata(target(), {{"system", 2_GiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700474}
475
476// Test delete all partitions.
477TEST_P(BootControlAndroidTestP, DeleteAll) {
Yifan Hong537802d2018-08-15 13:15:42 -0700478 SetMetadata(source(),
479 {{S("system"), 2_GiB},
480 {S("vendor"), 1_GiB},
Yifan Hongd4db07e2018-10-18 17:46:27 -0700481 {T("system"), 2_GiB},
482 {T("vendor"), 1_GiB}});
483 ExpectStoreMetadata({{S("system"), 2_GiB}, {S("vendor"), 1_GiB}});
484
485 EXPECT_TRUE(InitPartitionMetadata(target(), {}));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700486}
487
488// Test corrupt source metadata case.
489TEST_P(BootControlAndroidTestP, CorruptedSourceMetadata) {
Yifan Hong6e706b12018-11-09 16:50:51 -0800490 EXPECT_CALL(dynamicControl(),
Yifan Hong30eb7b52018-11-20 11:05:46 -0800491 LoadMetadataBuilder(GetSuperDevice(source()), source(), _))
Yifan Hong6e706b12018-11-09 16:50:51 -0800492 .WillOnce(Invoke([](auto, auto, auto) { return nullptr; }));
Yifan Hong1d9077f2018-12-07 12:09:37 -0800493 ExpectUnmap({T("system")});
494
Yifan Hongd4db07e2018-10-18 17:46:27 -0700495 EXPECT_FALSE(InitPartitionMetadata(target(), {{"system", 1_GiB}}))
496 << "Should not be able to continue with corrupt source metadata";
Yifan Hong537802d2018-08-15 13:15:42 -0700497}
498
499// Test that InitPartitionMetadata fail if there is not enough space on the
500// device.
501TEST_P(BootControlAndroidTestP, NotEnoughSpace) {
Yifan Hongd4db07e2018-10-18 17:46:27 -0700502 SetMetadata(source(),
503 {{S("system"), 3_GiB},
504 {S("vendor"), 2_GiB},
505 {T("system"), 0},
506 {T("vendor"), 0}});
507 EXPECT_FALSE(
508 InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
Yifan Hong537802d2018-08-15 13:15:42 -0700509 << "Should not be able to fit 11GiB data into 10GiB space";
510}
511
Yifan Hongd4db07e2018-10-18 17:46:27 -0700512TEST_P(BootControlAndroidTestP, NotEnoughSpaceForSlot) {
513 SetMetadata(source(),
514 {{S("system"), 1_GiB},
515 {S("vendor"), 1_GiB},
516 {T("system"), 0},
517 {T("vendor"), 0}});
518 EXPECT_FALSE(
519 InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
520 << "Should not be able to grow over size of super / 2";
521}
522
Yifan Hong1d9077f2018-12-07 12:09:37 -0800523// Test applying retrofit update on a build with dynamic partitions enabled.
524TEST_P(BootControlAndroidTestP,
525 ApplyRetrofitUpdateOnDynamicPartitionsEnabledBuild) {
526 SetMetadata(source(),
527 {{S("system"), 2_GiB},
528 {S("vendor"), 1_GiB},
529 {T("system"), 2_GiB},
530 {T("vendor"), 1_GiB}});
531 // Should not try to unmap any target partition.
David Anderson4c891c92019-06-21 17:45:23 -0700532 EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_)).Times(0);
Yifan Hong1d9077f2018-12-07 12:09:37 -0800533 // Should not store metadata to target slot.
534 EXPECT_CALL(dynamicControl(),
535 StoreMetadata(GetSuperDevice(target()), _, target()))
536 .Times(0);
537
538 // Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
539 // we don't want any default group in the PartitionMetadata.
Tao Bao3406c772019-01-02 15:34:35 -0800540 EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
Yifan Hong1d9077f2018-12-07 12:09:37 -0800541
542 // Should use dynamic source partitions.
543 EXPECT_CALL(dynamicControl(), GetState(S("system")))
544 .Times(1)
545 .WillOnce(Return(DmDeviceState::ACTIVE));
Tao Bao3406c772019-01-02 15:34:35 -0800546 string system_device;
547 EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
548 EXPECT_EQ(GetDmDevice(S("system")), system_device);
Yifan Hong1d9077f2018-12-07 12:09:37 -0800549
550 // Should use static target partitions without querying dynamic control.
551 EXPECT_CALL(dynamicControl(), GetState(T("system"))).Times(0);
Tao Bao3406c772019-01-02 15:34:35 -0800552 EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
553 EXPECT_EQ(GetDevice(T("system")), system_device);
554
555 // Static partition "bar".
556 EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
557 std::string bar_device;
558 EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
559 EXPECT_EQ(GetDevice(S("bar")), bar_device);
560
561 EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
562 EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
563 EXPECT_EQ(GetDevice(T("bar")), bar_device);
564}
565
566TEST_P(BootControlAndroidTestP, GetPartitionDeviceWhenResumingUpdate) {
567 // Both of the two slots contain valid partition metadata, since this is
568 // resuming an update.
569 SetMetadata(source(),
570 {{S("system"), 2_GiB},
571 {S("vendor"), 1_GiB},
572 {T("system"), 2_GiB},
573 {T("vendor"), 1_GiB}});
574 SetMetadata(target(),
575 {{S("system"), 2_GiB},
576 {S("vendor"), 1_GiB},
577 {T("system"), 2_GiB},
578 {T("vendor"), 1_GiB}});
579 EXPECT_CALL(dynamicControl(),
580 StoreMetadata(GetSuperDevice(target()), _, target()))
581 .Times(0);
582 EXPECT_TRUE(InitPartitionMetadata(
583 target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
584
585 // Dynamic partition "system".
586 EXPECT_CALL(dynamicControl(), GetState(S("system")))
587 .Times(1)
588 .WillOnce(Return(DmDeviceState::ACTIVE));
589 string system_device;
590 EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
591 EXPECT_EQ(GetDmDevice(S("system")), system_device);
592
593 EXPECT_CALL(dynamicControl(), GetState(T("system")))
Yifan Hong8546a712019-03-28 14:42:53 -0700594 .Times(AnyNumber())
Tao Bao3406c772019-01-02 15:34:35 -0800595 .WillOnce(Return(DmDeviceState::ACTIVE));
Yifan Hong8546a712019-03-28 14:42:53 -0700596 EXPECT_CALL(dynamicControl(),
597 MapPartitionOnDeviceMapper(
598 GetSuperDevice(target()), T("system"), target(), _, _))
599 .Times(AnyNumber())
600 .WillRepeatedly(
601 Invoke([](const auto&, const auto& name, auto, auto, auto* device) {
602 *device = "/fake/remapped/" + name;
603 return true;
604 }));
Tao Bao3406c772019-01-02 15:34:35 -0800605 EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
Yifan Hong8546a712019-03-28 14:42:53 -0700606 EXPECT_EQ("/fake/remapped/" + T("system"), system_device);
Tao Bao3406c772019-01-02 15:34:35 -0800607
608 // Static partition "bar".
609 EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
610 std::string bar_device;
611 EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
612 EXPECT_EQ(GetDevice(S("bar")), bar_device);
613
614 EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
615 EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
616 EXPECT_EQ(GetDevice(T("bar")), bar_device);
Yifan Hong1d9077f2018-12-07 12:09:37 -0800617}
618
Yifan Hongd4db07e2018-10-18 17:46:27 -0700619INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
Yifan Hong537802d2018-08-15 13:15:42 -0700620 BootControlAndroidTestP,
621 testing::Values(TestParam{0, 1}, TestParam{1, 0}));
622
Yifan Hongd4db07e2018-10-18 17:46:27 -0700623const PartitionSuffixSizes update_sizes_0() {
624 // Initial state is 0 for "other" slot.
Yifan Hong537802d2018-08-15 13:15:42 -0700625 return {
626 {"grown_a", 2_GiB},
627 {"shrunk_a", 1_GiB},
628 {"same_a", 100_MiB},
629 {"deleted_a", 150_MiB},
Yifan Hongd4db07e2018-10-18 17:46:27 -0700630 // no added_a
631 {"grown_b", 200_MiB},
632 // simulate system_other
633 {"shrunk_b", 0},
634 {"same_b", 0},
635 {"deleted_b", 0},
636 // no added_b
637 };
638}
639
640const PartitionSuffixSizes update_sizes_1() {
641 return {
642 {"grown_a", 2_GiB},
643 {"shrunk_a", 1_GiB},
644 {"same_a", 100_MiB},
645 {"deleted_a", 150_MiB},
646 // no added_a
Yifan Hong537802d2018-08-15 13:15:42 -0700647 {"grown_b", 3_GiB},
648 {"shrunk_b", 150_MiB},
649 {"same_b", 100_MiB},
650 {"added_b", 150_MiB},
Yifan Hongd4db07e2018-10-18 17:46:27 -0700651 // no deleted_b
Yifan Hong537802d2018-08-15 13:15:42 -0700652 };
653}
654
Yifan Hongd4db07e2018-10-18 17:46:27 -0700655const PartitionSuffixSizes update_sizes_2() {
656 return {
657 {"grown_a", 4_GiB},
658 {"shrunk_a", 100_MiB},
659 {"same_a", 100_MiB},
660 {"deleted_a", 64_MiB},
661 // no added_a
662 {"grown_b", 3_GiB},
663 {"shrunk_b", 150_MiB},
664 {"same_b", 100_MiB},
665 {"added_b", 150_MiB},
666 // no deleted_b
667 };
Yifan Hong537802d2018-08-15 13:15:42 -0700668}
669
670// Test case for first update after the device is manufactured, in which
671// case the "other" slot is likely of size "0" (except system, which is
672// non-zero because of system_other partition)
673TEST_F(BootControlAndroidTest, SimulatedFirstUpdate) {
674 SetSlots({0, 1});
675
676 SetMetadata(source(), update_sizes_0());
677 SetMetadata(target(), update_sizes_0());
Yifan Hong549eb362018-10-19 15:11:12 -0700678 ExpectStoreMetadata(update_sizes_1());
Yifan Hong1d9077f2018-12-07 12:09:37 -0800679 ExpectUnmap({"grown_b", "shrunk_b", "same_b", "added_b"});
Yifan Hong537802d2018-08-15 13:15:42 -0700680
Yifan Hongd4db07e2018-10-18 17:46:27 -0700681 EXPECT_TRUE(InitPartitionMetadata(target(),
682 {{"grown", 3_GiB},
683 {"shrunk", 150_MiB},
684 {"same", 100_MiB},
685 {"added", 150_MiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700686}
687
688// After first update, test for the second update. In the second update, the
689// "added" partition is deleted and "deleted" partition is re-added.
690TEST_F(BootControlAndroidTest, SimulatedSecondUpdate) {
691 SetSlots({1, 0});
692
693 SetMetadata(source(), update_sizes_1());
694 SetMetadata(target(), update_sizes_0());
695
Yifan Hong549eb362018-10-19 15:11:12 -0700696 ExpectStoreMetadata(update_sizes_2());
Yifan Hong1d9077f2018-12-07 12:09:37 -0800697 ExpectUnmap({"grown_a", "shrunk_a", "same_a", "deleted_a"});
Yifan Hong537802d2018-08-15 13:15:42 -0700698
Yifan Hongd4db07e2018-10-18 17:46:27 -0700699 EXPECT_TRUE(InitPartitionMetadata(target(),
700 {{"grown", 4_GiB},
701 {"shrunk", 100_MiB},
702 {"same", 100_MiB},
703 {"deleted", 64_MiB}}));
Yifan Hong537802d2018-08-15 13:15:42 -0700704}
705
706TEST_F(BootControlAndroidTest, ApplyingToCurrentSlot) {
707 SetSlots({1, 1});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700708 EXPECT_FALSE(InitPartitionMetadata(target(), {}))
Yifan Hong537802d2018-08-15 13:15:42 -0700709 << "Should not be able to apply to current slot.";
710}
711
Yifan Hongd4db07e2018-10-18 17:46:27 -0700712class BootControlAndroidGroupTestP : public BootControlAndroidTestP {
713 public:
714 void SetUp() override {
715 BootControlAndroidTestP::SetUp();
716 SetMetadata(
717 source(),
718 {.groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
719 SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB),
720 SimpleGroup(T("android"), 3_GiB, T("system"), 0),
721 SimpleGroup(T("oem"), 2_GiB, T("vendor"), 0)}});
722 }
723
724 // Return a simple group with only one partition.
Dan Albertfcfbda22018-12-14 12:57:55 -0800725 PartitionMetadata::Group SimpleGroup(const string& group,
Yifan Hongd4db07e2018-10-18 17:46:27 -0700726 uint64_t group_size,
Dan Albertfcfbda22018-12-14 12:57:55 -0800727 const string& partition,
Yifan Hongd4db07e2018-10-18 17:46:27 -0700728 uint64_t partition_size) {
729 return {.name = group,
730 .size = group_size,
731 .partitions = {{.name = partition, .size = partition_size}}};
732 }
733
734 void ExpectStoreMetadata(const PartitionMetadata& partition_metadata) {
735 ExpectStoreMetadataMatch(MetadataMatches(partition_metadata));
736 }
737
738 // Expect that target slot is stored with target groups.
739 void ExpectStoreMetadataMatch(
740 const Matcher<MetadataBuilder*>& matcher) override {
741 BootControlAndroidTestP::ExpectStoreMetadataMatch(AllOf(
742 MetadataMatches(PartitionMetadata{
743 .groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
744 SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB)}}),
745 matcher));
746 }
747};
748
749// Allow to resize within group.
750TEST_P(BootControlAndroidGroupTestP, ResizeWithinGroup) {
751 ExpectStoreMetadata(PartitionMetadata{
752 .groups = {SimpleGroup(T("android"), 3_GiB, T("system"), 3_GiB),
753 SimpleGroup(T("oem"), 2_GiB, T("vendor"), 2_GiB)}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800754 ExpectUnmap({T("system"), T("vendor")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700755
756 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
757 target(),
758 PartitionMetadata{
759 .groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
Tao Bao3406c772019-01-02 15:34:35 -0800760 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
761 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700762}
763
764TEST_P(BootControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
765 EXPECT_FALSE(bootctl_.InitPartitionMetadata(
766 target(),
767 PartitionMetadata{
768 .groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
Tao Bao3406c772019-01-02 15:34:35 -0800769 SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}},
770 true))
Yifan Hongd4db07e2018-10-18 17:46:27 -0700771 << "Should not be able to grow over maximum size of group";
772}
773
774TEST_P(BootControlAndroidGroupTestP, GroupTooBig) {
775 EXPECT_FALSE(bootctl_.InitPartitionMetadata(
776 target(),
777 PartitionMetadata{.groups = {{.name = "android", .size = 3_GiB},
Tao Bao3406c772019-01-02 15:34:35 -0800778 {.name = "oem", .size = 3_GiB}}},
779 true))
Yifan Hongd4db07e2018-10-18 17:46:27 -0700780 << "Should not be able to grow over size of super / 2";
781}
782
783TEST_P(BootControlAndroidGroupTestP, AddPartitionToGroup) {
784 ExpectStoreMetadata(PartitionMetadata{
Justin Yun8ecb65f2019-07-01 11:04:13 +0900785 .groups = {{.name = T("android"),
786 .size = 3_GiB,
787 .partitions = {{.name = T("system"), .size = 2_GiB},
788 {.name = T("system_ext"), .size = 1_GiB}}}}});
789 ExpectUnmap({T("system"), T("vendor"), T("system_ext")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700790
791 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
792 target(),
793 PartitionMetadata{
Tao Bao3406c772019-01-02 15:34:35 -0800794 .groups = {{.name = "android",
795 .size = 3_GiB,
796 .partitions = {{.name = "system", .size = 2_GiB},
Justin Yun8ecb65f2019-07-01 11:04:13 +0900797 {.name = "system_ext", .size = 1_GiB}}},
Tao Bao3406c772019-01-02 15:34:35 -0800798 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
799 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700800}
801
802TEST_P(BootControlAndroidGroupTestP, RemovePartitionFromGroup) {
803 ExpectStoreMetadata(PartitionMetadata{
804 .groups = {{.name = T("android"), .size = 3_GiB, .partitions = {}}}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800805 ExpectUnmap({T("vendor")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700806
807 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
808 target(),
809 PartitionMetadata{
810 .groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
Tao Bao3406c772019-01-02 15:34:35 -0800811 SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
812 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700813}
814
815TEST_P(BootControlAndroidGroupTestP, AddGroup) {
816 ExpectStoreMetadata(PartitionMetadata{
817 .groups = {
818 SimpleGroup(T("new_group"), 2_GiB, T("new_partition"), 2_GiB)}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800819 ExpectUnmap({T("system"), T("vendor"), T("new_partition")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700820
821 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
822 target(),
823 PartitionMetadata{
Tao Bao3406c772019-01-02 15:34:35 -0800824 .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
825 SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
826 SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}},
827 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700828}
829
830TEST_P(BootControlAndroidGroupTestP, RemoveGroup) {
831 ExpectStoreMetadataMatch(Not(HasGroup(T("oem"))));
Yifan Hong1d9077f2018-12-07 12:09:37 -0800832 ExpectUnmap({T("system")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700833 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
834 target(),
835 PartitionMetadata{
Tao Bao3406c772019-01-02 15:34:35 -0800836 .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}},
837 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700838}
839
840TEST_P(BootControlAndroidGroupTestP, ResizeGroup) {
841 ExpectStoreMetadata(PartitionMetadata{
842 .groups = {SimpleGroup(T("android"), 2_GiB, T("system"), 2_GiB),
843 SimpleGroup(T("oem"), 3_GiB, T("vendor"), 3_GiB)}});
Yifan Hong1d9077f2018-12-07 12:09:37 -0800844 ExpectUnmap({T("system"), T("vendor")});
Yifan Hongd4db07e2018-10-18 17:46:27 -0700845
846 EXPECT_TRUE(bootctl_.InitPartitionMetadata(
847 target(),
848 PartitionMetadata{
849 .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
Tao Bao3406c772019-01-02 15:34:35 -0800850 SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}},
851 true));
Yifan Hongd4db07e2018-10-18 17:46:27 -0700852}
853
854INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
855 BootControlAndroidGroupTestP,
856 testing::Values(TestParam{0, 1}, TestParam{1, 0}));
857
Yifan Hong537802d2018-08-15 13:15:42 -0700858} // namespace chromeos_update_engine