boot_control_android_unittest.cc 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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. #include "update_engine/boot_control_android.h"
  17. #include <set>
  18. #include <vector>
  19. #include <base/logging.h>
  20. #include <base/strings/string_util.h>
  21. #include <fs_mgr.h>
  22. #include <gmock/gmock.h>
  23. #include <gtest/gtest.h>
  24. #include <libdm/dm.h>
  25. #include "update_engine/mock_boot_control_hal.h"
  26. #include "update_engine/mock_dynamic_partition_control.h"
  27. using android::dm::DmDeviceState;
  28. using android::fs_mgr::MetadataBuilder;
  29. using android::hardware::Void;
  30. using std::string;
  31. using testing::_;
  32. using testing::AnyNumber;
  33. using testing::Contains;
  34. using testing::Eq;
  35. using testing::Invoke;
  36. using testing::Key;
  37. using testing::MakeMatcher;
  38. using testing::Matcher;
  39. using testing::MatcherInterface;
  40. using testing::MatchResultListener;
  41. using testing::NiceMock;
  42. using testing::Not;
  43. using testing::Return;
  44. namespace chromeos_update_engine {
  45. constexpr const uint32_t kMaxNumSlots = 2;
  46. constexpr const char* kSlotSuffixes[kMaxNumSlots] = {"_a", "_b"};
  47. constexpr const char* kFakeDevicePath = "/fake/dev/path/";
  48. constexpr const char* kFakeDmDevicePath = "/fake/dm/dev/path/";
  49. constexpr const uint32_t kFakeMetadataSize = 65536;
  50. constexpr const char* kDefaultGroup = "foo";
  51. // A map describing the size of each partition.
  52. // "{name, size}"
  53. using PartitionSizes = std::map<string, uint64_t>;
  54. // "{name_a, size}"
  55. using PartitionSuffixSizes = std::map<string, uint64_t>;
  56. using PartitionMetadata = BootControlInterface::PartitionMetadata;
  57. // C++ standards do not allow uint64_t (aka unsigned long) to be the parameter
  58. // of user-defined literal operators.
  59. constexpr unsigned long long operator"" _MiB(unsigned long long x) { // NOLINT
  60. return x << 20;
  61. }
  62. constexpr unsigned long long operator"" _GiB(unsigned long long x) { // NOLINT
  63. return x << 30;
  64. }
  65. constexpr uint64_t kDefaultGroupSize = 5_GiB;
  66. // Super device size. 1 MiB for metadata.
  67. constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
  68. template <typename U, typename V>
  69. std::ostream& operator<<(std::ostream& os, const std::map<U, V>& param) {
  70. os << "{";
  71. bool first = true;
  72. for (const auto& pair : param) {
  73. if (!first)
  74. os << ", ";
  75. os << pair.first << ":" << pair.second;
  76. first = false;
  77. }
  78. return os << "}";
  79. }
  80. template <typename T>
  81. std::ostream& operator<<(std::ostream& os, const std::vector<T>& param) {
  82. os << "[";
  83. bool first = true;
  84. for (const auto& e : param) {
  85. if (!first)
  86. os << ", ";
  87. os << e;
  88. first = false;
  89. }
  90. return os << "]";
  91. }
  92. std::ostream& operator<<(std::ostream& os,
  93. const PartitionMetadata::Partition& p) {
  94. return os << "{" << p.name << ", " << p.size << "}";
  95. }
  96. std::ostream& operator<<(std::ostream& os, const PartitionMetadata::Group& g) {
  97. return os << "{" << g.name << ", " << g.size << ", " << g.partitions << "}";
  98. }
  99. std::ostream& operator<<(std::ostream& os, const PartitionMetadata& m) {
  100. return os << m.groups;
  101. }
  102. inline string GetDevice(const string& name) {
  103. return kFakeDevicePath + name;
  104. }
  105. inline string GetDmDevice(const string& name) {
  106. return kFakeDmDevicePath + name;
  107. }
  108. // TODO(elsk): fs_mgr_get_super_partition_name should be mocked.
  109. inline string GetSuperDevice(uint32_t slot) {
  110. return GetDevice(fs_mgr_get_super_partition_name(slot));
  111. }
  112. struct TestParam {
  113. uint32_t source;
  114. uint32_t target;
  115. };
  116. std::ostream& operator<<(std::ostream& os, const TestParam& param) {
  117. return os << "{source: " << param.source << ", target:" << param.target
  118. << "}";
  119. }
  120. // To support legacy tests, auto-convert {name_a: size} map to
  121. // PartitionMetadata.
  122. PartitionMetadata partitionSuffixSizesToMetadata(
  123. const PartitionSuffixSizes& partition_sizes) {
  124. PartitionMetadata metadata;
  125. for (const char* suffix : kSlotSuffixes) {
  126. metadata.groups.push_back(
  127. {string(kDefaultGroup) + suffix, kDefaultGroupSize, {}});
  128. }
  129. for (const auto& pair : partition_sizes) {
  130. for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
  131. if (base::EndsWith(pair.first,
  132. kSlotSuffixes[suffix_idx],
  133. base::CompareCase::SENSITIVE)) {
  134. metadata.groups[suffix_idx].partitions.push_back(
  135. {pair.first, pair.second});
  136. }
  137. }
  138. }
  139. return metadata;
  140. }
  141. // To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
  142. PartitionMetadata partitionSizesToMetadata(
  143. const PartitionSizes& partition_sizes) {
  144. PartitionMetadata metadata;
  145. metadata.groups.push_back({string{kDefaultGroup}, kDefaultGroupSize, {}});
  146. for (const auto& pair : partition_sizes) {
  147. metadata.groups[0].partitions.push_back({pair.first, pair.second});
  148. }
  149. return metadata;
  150. }
  151. std::unique_ptr<MetadataBuilder> NewFakeMetadata(
  152. const PartitionMetadata& metadata) {
  153. auto builder =
  154. MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
  155. EXPECT_GE(builder->AllocatableSpace(), kDefaultGroupSize * 2);
  156. EXPECT_NE(nullptr, builder);
  157. if (builder == nullptr)
  158. return nullptr;
  159. for (const auto& group : metadata.groups) {
  160. EXPECT_TRUE(builder->AddGroup(group.name, group.size));
  161. for (const auto& partition : group.partitions) {
  162. auto p = builder->AddPartition(partition.name, group.name, 0 /* attr */);
  163. EXPECT_TRUE(p && builder->ResizePartition(p, partition.size));
  164. }
  165. }
  166. return builder;
  167. }
  168. class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
  169. public:
  170. explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
  171. : partition_metadata_(partitionSuffixSizesToMetadata(partition_sizes)) {}
  172. explicit MetadataMatcher(const PartitionMetadata& partition_metadata)
  173. : partition_metadata_(partition_metadata) {}
  174. bool MatchAndExplain(MetadataBuilder* metadata,
  175. MatchResultListener* listener) const override {
  176. bool success = true;
  177. for (const auto& group : partition_metadata_.groups) {
  178. for (const auto& partition : group.partitions) {
  179. auto p = metadata->FindPartition(partition.name);
  180. if (p == nullptr) {
  181. if (!success)
  182. *listener << "; ";
  183. *listener << "No partition " << partition.name;
  184. success = false;
  185. continue;
  186. }
  187. if (p->size() != partition.size) {
  188. if (!success)
  189. *listener << "; ";
  190. *listener << "Partition " << partition.name << " has size "
  191. << p->size() << ", expected " << partition.size;
  192. success = false;
  193. }
  194. if (p->group_name() != group.name) {
  195. if (!success)
  196. *listener << "; ";
  197. *listener << "Partition " << partition.name << " has group "
  198. << p->group_name() << ", expected " << group.name;
  199. success = false;
  200. }
  201. }
  202. }
  203. return success;
  204. }
  205. void DescribeTo(std::ostream* os) const override {
  206. *os << "expect: " << partition_metadata_;
  207. }
  208. void DescribeNegationTo(std::ostream* os) const override {
  209. *os << "expect not: " << partition_metadata_;
  210. }
  211. private:
  212. PartitionMetadata partition_metadata_;
  213. };
  214. inline Matcher<MetadataBuilder*> MetadataMatches(
  215. const PartitionSuffixSizes& partition_sizes) {
  216. return MakeMatcher(new MetadataMatcher(partition_sizes));
  217. }
  218. inline Matcher<MetadataBuilder*> MetadataMatches(
  219. const PartitionMetadata& partition_metadata) {
  220. return MakeMatcher(new MetadataMatcher(partition_metadata));
  221. }
  222. MATCHER_P(HasGroup, group, " has group " + group) {
  223. auto groups = arg->ListGroups();
  224. return std::find(groups.begin(), groups.end(), group) != groups.end();
  225. }
  226. class BootControlAndroidTest : public ::testing::Test {
  227. protected:
  228. void SetUp() override {
  229. // Fake init bootctl_
  230. bootctl_.module_ = new NiceMock<MockBootControlHal>();
  231. bootctl_.dynamic_control_ =
  232. std::make_unique<NiceMock<MockDynamicPartitionControl>>();
  233. ON_CALL(module(), getNumberSlots()).WillByDefault(Invoke([] {
  234. return kMaxNumSlots;
  235. }));
  236. ON_CALL(module(), getSuffix(_, _))
  237. .WillByDefault(Invoke([](auto slot, auto cb) {
  238. EXPECT_LE(slot, kMaxNumSlots);
  239. cb(slot < kMaxNumSlots ? kSlotSuffixes[slot] : "");
  240. return Void();
  241. }));
  242. ON_CALL(dynamicControl(), IsDynamicPartitionsEnabled())
  243. .WillByDefault(Return(true));
  244. ON_CALL(dynamicControl(), IsDynamicPartitionsRetrofit())
  245. .WillByDefault(Return(false));
  246. ON_CALL(dynamicControl(), DeviceExists(_)).WillByDefault(Return(true));
  247. ON_CALL(dynamicControl(), GetDeviceDir(_))
  248. .WillByDefault(Invoke([](auto path) {
  249. *path = kFakeDevicePath;
  250. return true;
  251. }));
  252. ON_CALL(dynamicControl(), GetDmDevicePathByName(_, _))
  253. .WillByDefault(Invoke([](auto partition_name_suffix, auto device) {
  254. *device = GetDmDevice(partition_name_suffix);
  255. return true;
  256. }));
  257. }
  258. // Return the mocked HAL module.
  259. NiceMock<MockBootControlHal>& module() {
  260. return static_cast<NiceMock<MockBootControlHal>&>(*bootctl_.module_);
  261. }
  262. // Return the mocked DynamicPartitionControlInterface.
  263. NiceMock<MockDynamicPartitionControl>& dynamicControl() {
  264. return static_cast<NiceMock<MockDynamicPartitionControl>&>(
  265. *bootctl_.dynamic_control_);
  266. }
  267. // Set the fake metadata to return when LoadMetadataBuilder is called on
  268. // |slot|.
  269. void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
  270. SetMetadata(slot, partitionSuffixSizesToMetadata(sizes));
  271. }
  272. void SetMetadata(uint32_t slot, const PartitionMetadata& metadata) {
  273. EXPECT_CALL(dynamicControl(),
  274. LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
  275. .Times(AnyNumber())
  276. .WillRepeatedly(Invoke([metadata](auto, auto, auto) {
  277. return NewFakeMetadata(metadata);
  278. }));
  279. }
  280. // Expect that UnmapPartitionOnDeviceMapper is called on target() metadata
  281. // slot with each partition in |partitions|.
  282. void ExpectUnmap(const std::set<string>& partitions) {
  283. // Error when UnmapPartitionOnDeviceMapper is called on unknown arguments.
  284. ON_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _))
  285. .WillByDefault(Return(false));
  286. for (const auto& partition : partitions) {
  287. EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(partition, _))
  288. .WillOnce(Invoke([this](auto partition, auto) {
  289. mapped_devices_.erase(partition);
  290. return true;
  291. }));
  292. }
  293. }
  294. void ExpectDevicesAreMapped(const std::set<string>& partitions) {
  295. ASSERT_EQ(partitions.size(), mapped_devices_.size());
  296. for (const auto& partition : partitions) {
  297. EXPECT_THAT(mapped_devices_, Contains(Key(Eq(partition))))
  298. << "Expect that " << partition << " is mapped, but it is not.";
  299. }
  300. }
  301. void ExpectStoreMetadata(const PartitionSuffixSizes& partition_sizes) {
  302. ExpectStoreMetadataMatch(MetadataMatches(partition_sizes));
  303. }
  304. virtual void ExpectStoreMetadataMatch(
  305. const Matcher<MetadataBuilder*>& matcher) {
  306. EXPECT_CALL(dynamicControl(),
  307. StoreMetadata(GetSuperDevice(target()), matcher, target()))
  308. .WillOnce(Return(true));
  309. }
  310. uint32_t source() { return slots_.source; }
  311. uint32_t target() { return slots_.target; }
  312. // Return partition names with suffix of source().
  313. string S(const string& name) { return name + kSlotSuffixes[source()]; }
  314. // Return partition names with suffix of target().
  315. string T(const string& name) { return name + kSlotSuffixes[target()]; }
  316. // Set source and target slots to use before testing.
  317. void SetSlots(const TestParam& slots) {
  318. slots_ = slots;
  319. ON_CALL(module(), getCurrentSlot()).WillByDefault(Invoke([this] {
  320. return source();
  321. }));
  322. // Should not store metadata to source slot.
  323. EXPECT_CALL(dynamicControl(),
  324. StoreMetadata(GetSuperDevice(source()), _, source()))
  325. .Times(0);
  326. // Should not load metadata from target slot.
  327. EXPECT_CALL(dynamicControl(),
  328. LoadMetadataBuilder(GetSuperDevice(target()), target(), _))
  329. .Times(0);
  330. }
  331. bool InitPartitionMetadata(uint32_t slot,
  332. PartitionSizes partition_sizes,
  333. bool update_metadata = true) {
  334. auto m = partitionSizesToMetadata(partition_sizes);
  335. LOG(INFO) << m;
  336. return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
  337. }
  338. BootControlAndroid bootctl_; // BootControlAndroid under test.
  339. TestParam slots_;
  340. // mapped devices through MapPartitionOnDeviceMapper.
  341. std::map<string, string> mapped_devices_;
  342. };
  343. class BootControlAndroidTestP
  344. : public BootControlAndroidTest,
  345. public ::testing::WithParamInterface<TestParam> {
  346. public:
  347. void SetUp() override {
  348. BootControlAndroidTest::SetUp();
  349. SetSlots(GetParam());
  350. }
  351. };
  352. // Test resize case. Grow if target metadata contains a partition with a size
  353. // less than expected.
  354. TEST_P(BootControlAndroidTestP, NeedGrowIfSizeNotMatchWhenResizing) {
  355. SetMetadata(source(),
  356. {{S("system"), 2_GiB},
  357. {S("vendor"), 1_GiB},
  358. {T("system"), 2_GiB},
  359. {T("vendor"), 1_GiB}});
  360. ExpectStoreMetadata({{S("system"), 2_GiB},
  361. {S("vendor"), 1_GiB},
  362. {T("system"), 3_GiB},
  363. {T("vendor"), 1_GiB}});
  364. ExpectUnmap({T("system"), T("vendor")});
  365. EXPECT_TRUE(
  366. InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 1_GiB}}));
  367. }
  368. // Test resize case. Shrink if target metadata contains a partition with a size
  369. // greater than expected.
  370. TEST_P(BootControlAndroidTestP, NeedShrinkIfSizeNotMatchWhenResizing) {
  371. SetMetadata(source(),
  372. {{S("system"), 2_GiB},
  373. {S("vendor"), 1_GiB},
  374. {T("system"), 2_GiB},
  375. {T("vendor"), 1_GiB}});
  376. ExpectStoreMetadata({{S("system"), 2_GiB},
  377. {S("vendor"), 1_GiB},
  378. {T("system"), 2_GiB},
  379. {T("vendor"), 150_MiB}});
  380. ExpectUnmap({T("system"), T("vendor")});
  381. EXPECT_TRUE(InitPartitionMetadata(target(),
  382. {{"system", 2_GiB}, {"vendor", 150_MiB}}));
  383. }
  384. // Test adding partitions on the first run.
  385. TEST_P(BootControlAndroidTestP, AddPartitionToEmptyMetadata) {
  386. SetMetadata(source(), PartitionSuffixSizes{});
  387. ExpectStoreMetadata({{T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
  388. ExpectUnmap({T("system"), T("vendor")});
  389. EXPECT_TRUE(
  390. InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
  391. }
  392. // Test subsequent add case.
  393. TEST_P(BootControlAndroidTestP, AddAdditionalPartition) {
  394. SetMetadata(source(), {{S("system"), 2_GiB}, {T("system"), 2_GiB}});
  395. ExpectStoreMetadata(
  396. {{S("system"), 2_GiB}, {T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
  397. ExpectUnmap({T("system"), T("vendor")});
  398. EXPECT_TRUE(
  399. InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
  400. }
  401. // Test delete one partition.
  402. TEST_P(BootControlAndroidTestP, DeletePartition) {
  403. SetMetadata(source(),
  404. {{S("system"), 2_GiB},
  405. {S("vendor"), 1_GiB},
  406. {T("system"), 2_GiB},
  407. {T("vendor"), 1_GiB}});
  408. // No T("vendor")
  409. ExpectStoreMetadata(
  410. {{S("system"), 2_GiB}, {S("vendor"), 1_GiB}, {T("system"), 2_GiB}});
  411. ExpectUnmap({T("system")});
  412. EXPECT_TRUE(InitPartitionMetadata(target(), {{"system", 2_GiB}}));
  413. }
  414. // Test delete all partitions.
  415. TEST_P(BootControlAndroidTestP, DeleteAll) {
  416. SetMetadata(source(),
  417. {{S("system"), 2_GiB},
  418. {S("vendor"), 1_GiB},
  419. {T("system"), 2_GiB},
  420. {T("vendor"), 1_GiB}});
  421. ExpectStoreMetadata({{S("system"), 2_GiB}, {S("vendor"), 1_GiB}});
  422. EXPECT_TRUE(InitPartitionMetadata(target(), {}));
  423. }
  424. // Test corrupt source metadata case.
  425. TEST_P(BootControlAndroidTestP, CorruptedSourceMetadata) {
  426. EXPECT_CALL(dynamicControl(),
  427. LoadMetadataBuilder(GetSuperDevice(source()), source(), _))
  428. .WillOnce(Invoke([](auto, auto, auto) { return nullptr; }));
  429. ExpectUnmap({T("system")});
  430. EXPECT_FALSE(InitPartitionMetadata(target(), {{"system", 1_GiB}}))
  431. << "Should not be able to continue with corrupt source metadata";
  432. }
  433. // Test that InitPartitionMetadata fail if there is not enough space on the
  434. // device.
  435. TEST_P(BootControlAndroidTestP, NotEnoughSpace) {
  436. SetMetadata(source(),
  437. {{S("system"), 3_GiB},
  438. {S("vendor"), 2_GiB},
  439. {T("system"), 0},
  440. {T("vendor"), 0}});
  441. EXPECT_FALSE(
  442. InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
  443. << "Should not be able to fit 11GiB data into 10GiB space";
  444. }
  445. TEST_P(BootControlAndroidTestP, NotEnoughSpaceForSlot) {
  446. SetMetadata(source(),
  447. {{S("system"), 1_GiB},
  448. {S("vendor"), 1_GiB},
  449. {T("system"), 0},
  450. {T("vendor"), 0}});
  451. EXPECT_FALSE(
  452. InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
  453. << "Should not be able to grow over size of super / 2";
  454. }
  455. // Test applying retrofit update on a build with dynamic partitions enabled.
  456. TEST_P(BootControlAndroidTestP,
  457. ApplyRetrofitUpdateOnDynamicPartitionsEnabledBuild) {
  458. SetMetadata(source(),
  459. {{S("system"), 2_GiB},
  460. {S("vendor"), 1_GiB},
  461. {T("system"), 2_GiB},
  462. {T("vendor"), 1_GiB}});
  463. // Should not try to unmap any target partition.
  464. EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _)).Times(0);
  465. // Should not store metadata to target slot.
  466. EXPECT_CALL(dynamicControl(),
  467. StoreMetadata(GetSuperDevice(target()), _, target()))
  468. .Times(0);
  469. // Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
  470. // we don't want any default group in the PartitionMetadata.
  471. EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
  472. // Should use dynamic source partitions.
  473. EXPECT_CALL(dynamicControl(), GetState(S("system")))
  474. .Times(1)
  475. .WillOnce(Return(DmDeviceState::ACTIVE));
  476. string system_device;
  477. EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
  478. EXPECT_EQ(GetDmDevice(S("system")), system_device);
  479. // Should use static target partitions without querying dynamic control.
  480. EXPECT_CALL(dynamicControl(), GetState(T("system"))).Times(0);
  481. EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
  482. EXPECT_EQ(GetDevice(T("system")), system_device);
  483. // Static partition "bar".
  484. EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
  485. std::string bar_device;
  486. EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
  487. EXPECT_EQ(GetDevice(S("bar")), bar_device);
  488. EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
  489. EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
  490. EXPECT_EQ(GetDevice(T("bar")), bar_device);
  491. }
  492. TEST_P(BootControlAndroidTestP, GetPartitionDeviceWhenResumingUpdate) {
  493. // Both of the two slots contain valid partition metadata, since this is
  494. // resuming an update.
  495. SetMetadata(source(),
  496. {{S("system"), 2_GiB},
  497. {S("vendor"), 1_GiB},
  498. {T("system"), 2_GiB},
  499. {T("vendor"), 1_GiB}});
  500. SetMetadata(target(),
  501. {{S("system"), 2_GiB},
  502. {S("vendor"), 1_GiB},
  503. {T("system"), 2_GiB},
  504. {T("vendor"), 1_GiB}});
  505. EXPECT_CALL(dynamicControl(),
  506. StoreMetadata(GetSuperDevice(target()), _, target()))
  507. .Times(0);
  508. EXPECT_TRUE(InitPartitionMetadata(
  509. target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
  510. // Dynamic partition "system".
  511. EXPECT_CALL(dynamicControl(), GetState(S("system")))
  512. .Times(1)
  513. .WillOnce(Return(DmDeviceState::ACTIVE));
  514. string system_device;
  515. EXPECT_TRUE(bootctl_.GetPartitionDevice("system", source(), &system_device));
  516. EXPECT_EQ(GetDmDevice(S("system")), system_device);
  517. EXPECT_CALL(dynamicControl(), GetState(T("system")))
  518. .Times(AnyNumber())
  519. .WillOnce(Return(DmDeviceState::ACTIVE));
  520. EXPECT_CALL(dynamicControl(),
  521. MapPartitionOnDeviceMapper(
  522. GetSuperDevice(target()), T("system"), target(), _, _))
  523. .Times(AnyNumber())
  524. .WillRepeatedly(
  525. Invoke([](const auto&, const auto& name, auto, auto, auto* device) {
  526. *device = "/fake/remapped/" + name;
  527. return true;
  528. }));
  529. EXPECT_TRUE(bootctl_.GetPartitionDevice("system", target(), &system_device));
  530. EXPECT_EQ("/fake/remapped/" + T("system"), system_device);
  531. // Static partition "bar".
  532. EXPECT_CALL(dynamicControl(), GetState(S("bar"))).Times(0);
  533. std::string bar_device;
  534. EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", source(), &bar_device));
  535. EXPECT_EQ(GetDevice(S("bar")), bar_device);
  536. EXPECT_CALL(dynamicControl(), GetState(T("bar"))).Times(0);
  537. EXPECT_TRUE(bootctl_.GetPartitionDevice("bar", target(), &bar_device));
  538. EXPECT_EQ(GetDevice(T("bar")), bar_device);
  539. }
  540. INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
  541. BootControlAndroidTestP,
  542. testing::Values(TestParam{0, 1}, TestParam{1, 0}));
  543. const PartitionSuffixSizes update_sizes_0() {
  544. // Initial state is 0 for "other" slot.
  545. return {
  546. {"grown_a", 2_GiB},
  547. {"shrunk_a", 1_GiB},
  548. {"same_a", 100_MiB},
  549. {"deleted_a", 150_MiB},
  550. // no added_a
  551. {"grown_b", 200_MiB},
  552. // simulate system_other
  553. {"shrunk_b", 0},
  554. {"same_b", 0},
  555. {"deleted_b", 0},
  556. // no added_b
  557. };
  558. }
  559. const PartitionSuffixSizes update_sizes_1() {
  560. return {
  561. {"grown_a", 2_GiB},
  562. {"shrunk_a", 1_GiB},
  563. {"same_a", 100_MiB},
  564. {"deleted_a", 150_MiB},
  565. // no added_a
  566. {"grown_b", 3_GiB},
  567. {"shrunk_b", 150_MiB},
  568. {"same_b", 100_MiB},
  569. {"added_b", 150_MiB},
  570. // no deleted_b
  571. };
  572. }
  573. const PartitionSuffixSizes update_sizes_2() {
  574. return {
  575. {"grown_a", 4_GiB},
  576. {"shrunk_a", 100_MiB},
  577. {"same_a", 100_MiB},
  578. {"deleted_a", 64_MiB},
  579. // no added_a
  580. {"grown_b", 3_GiB},
  581. {"shrunk_b", 150_MiB},
  582. {"same_b", 100_MiB},
  583. {"added_b", 150_MiB},
  584. // no deleted_b
  585. };
  586. }
  587. // Test case for first update after the device is manufactured, in which
  588. // case the "other" slot is likely of size "0" (except system, which is
  589. // non-zero because of system_other partition)
  590. TEST_F(BootControlAndroidTest, SimulatedFirstUpdate) {
  591. SetSlots({0, 1});
  592. SetMetadata(source(), update_sizes_0());
  593. SetMetadata(target(), update_sizes_0());
  594. ExpectStoreMetadata(update_sizes_1());
  595. ExpectUnmap({"grown_b", "shrunk_b", "same_b", "added_b"});
  596. EXPECT_TRUE(InitPartitionMetadata(target(),
  597. {{"grown", 3_GiB},
  598. {"shrunk", 150_MiB},
  599. {"same", 100_MiB},
  600. {"added", 150_MiB}}));
  601. }
  602. // After first update, test for the second update. In the second update, the
  603. // "added" partition is deleted and "deleted" partition is re-added.
  604. TEST_F(BootControlAndroidTest, SimulatedSecondUpdate) {
  605. SetSlots({1, 0});
  606. SetMetadata(source(), update_sizes_1());
  607. SetMetadata(target(), update_sizes_0());
  608. ExpectStoreMetadata(update_sizes_2());
  609. ExpectUnmap({"grown_a", "shrunk_a", "same_a", "deleted_a"});
  610. EXPECT_TRUE(InitPartitionMetadata(target(),
  611. {{"grown", 4_GiB},
  612. {"shrunk", 100_MiB},
  613. {"same", 100_MiB},
  614. {"deleted", 64_MiB}}));
  615. }
  616. TEST_F(BootControlAndroidTest, ApplyingToCurrentSlot) {
  617. SetSlots({1, 1});
  618. EXPECT_FALSE(InitPartitionMetadata(target(), {}))
  619. << "Should not be able to apply to current slot.";
  620. }
  621. class BootControlAndroidGroupTestP : public BootControlAndroidTestP {
  622. public:
  623. void SetUp() override {
  624. BootControlAndroidTestP::SetUp();
  625. SetMetadata(
  626. source(),
  627. {.groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
  628. SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB),
  629. SimpleGroup(T("android"), 3_GiB, T("system"), 0),
  630. SimpleGroup(T("oem"), 2_GiB, T("vendor"), 0)}});
  631. }
  632. // Return a simple group with only one partition.
  633. PartitionMetadata::Group SimpleGroup(const string& group,
  634. uint64_t group_size,
  635. const string& partition,
  636. uint64_t partition_size) {
  637. return {.name = group,
  638. .size = group_size,
  639. .partitions = {{.name = partition, .size = partition_size}}};
  640. }
  641. void ExpectStoreMetadata(const PartitionMetadata& partition_metadata) {
  642. ExpectStoreMetadataMatch(MetadataMatches(partition_metadata));
  643. }
  644. // Expect that target slot is stored with target groups.
  645. void ExpectStoreMetadataMatch(
  646. const Matcher<MetadataBuilder*>& matcher) override {
  647. BootControlAndroidTestP::ExpectStoreMetadataMatch(AllOf(
  648. MetadataMatches(PartitionMetadata{
  649. .groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
  650. SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB)}}),
  651. matcher));
  652. }
  653. };
  654. // Allow to resize within group.
  655. TEST_P(BootControlAndroidGroupTestP, ResizeWithinGroup) {
  656. ExpectStoreMetadata(PartitionMetadata{
  657. .groups = {SimpleGroup(T("android"), 3_GiB, T("system"), 3_GiB),
  658. SimpleGroup(T("oem"), 2_GiB, T("vendor"), 2_GiB)}});
  659. ExpectUnmap({T("system"), T("vendor")});
  660. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  661. target(),
  662. PartitionMetadata{
  663. .groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
  664. SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
  665. true));
  666. }
  667. TEST_P(BootControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
  668. EXPECT_FALSE(bootctl_.InitPartitionMetadata(
  669. target(),
  670. PartitionMetadata{
  671. .groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
  672. SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}},
  673. true))
  674. << "Should not be able to grow over maximum size of group";
  675. }
  676. TEST_P(BootControlAndroidGroupTestP, GroupTooBig) {
  677. EXPECT_FALSE(bootctl_.InitPartitionMetadata(
  678. target(),
  679. PartitionMetadata{.groups = {{.name = "android", .size = 3_GiB},
  680. {.name = "oem", .size = 3_GiB}}},
  681. true))
  682. << "Should not be able to grow over size of super / 2";
  683. }
  684. TEST_P(BootControlAndroidGroupTestP, AddPartitionToGroup) {
  685. ExpectStoreMetadata(PartitionMetadata{
  686. .groups = {
  687. {.name = T("android"),
  688. .size = 3_GiB,
  689. .partitions = {{.name = T("system"), .size = 2_GiB},
  690. {.name = T("product_services"), .size = 1_GiB}}}}});
  691. ExpectUnmap({T("system"), T("vendor"), T("product_services")});
  692. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  693. target(),
  694. PartitionMetadata{
  695. .groups = {{.name = "android",
  696. .size = 3_GiB,
  697. .partitions = {{.name = "system", .size = 2_GiB},
  698. {.name = "product_services",
  699. .size = 1_GiB}}},
  700. SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
  701. true));
  702. }
  703. TEST_P(BootControlAndroidGroupTestP, RemovePartitionFromGroup) {
  704. ExpectStoreMetadata(PartitionMetadata{
  705. .groups = {{.name = T("android"), .size = 3_GiB, .partitions = {}}}});
  706. ExpectUnmap({T("vendor")});
  707. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  708. target(),
  709. PartitionMetadata{
  710. .groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
  711. SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
  712. true));
  713. }
  714. TEST_P(BootControlAndroidGroupTestP, AddGroup) {
  715. ExpectStoreMetadata(PartitionMetadata{
  716. .groups = {
  717. SimpleGroup(T("new_group"), 2_GiB, T("new_partition"), 2_GiB)}});
  718. ExpectUnmap({T("system"), T("vendor"), T("new_partition")});
  719. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  720. target(),
  721. PartitionMetadata{
  722. .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
  723. SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
  724. SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}},
  725. true));
  726. }
  727. TEST_P(BootControlAndroidGroupTestP, RemoveGroup) {
  728. ExpectStoreMetadataMatch(Not(HasGroup(T("oem"))));
  729. ExpectUnmap({T("system")});
  730. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  731. target(),
  732. PartitionMetadata{
  733. .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}},
  734. true));
  735. }
  736. TEST_P(BootControlAndroidGroupTestP, ResizeGroup) {
  737. ExpectStoreMetadata(PartitionMetadata{
  738. .groups = {SimpleGroup(T("android"), 2_GiB, T("system"), 2_GiB),
  739. SimpleGroup(T("oem"), 3_GiB, T("vendor"), 3_GiB)}});
  740. ExpectUnmap({T("system"), T("vendor")});
  741. EXPECT_TRUE(bootctl_.InitPartitionMetadata(
  742. target(),
  743. PartitionMetadata{
  744. .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
  745. SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}},
  746. true));
  747. }
  748. INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
  749. BootControlAndroidGroupTestP,
  750. testing::Values(TestParam{0, 1}, TestParam{1, 0}));
  751. } // namespace chromeos_update_engine