• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <libsnapshot/cow_format.h>
16 #include <libsnapshot/snapshot.h>
17 
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 
24 #include <chrono>
25 #include <deque>
26 #include <future>
27 #include <iostream>
28 
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/properties.h>
32 #include <android-base/strings.h>
33 #include <android-base/unique_fd.h>
34 #include <fs_mgr/file_wait.h>
35 #include <fs_mgr/roots.h>
36 #include <fs_mgr_dm_linear.h>
37 #include <gflags/gflags.h>
38 #include <gtest/gtest.h>
39 #include <libdm/dm.h>
40 #include <libfiemap/image_manager.h>
41 #include <liblp/builder.h>
42 #include <storage_literals/storage_literals.h>
43 
44 #include <android/snapshot/snapshot.pb.h>
45 #include <libsnapshot/test_helpers.h>
46 #include "partition_cow_creator.h"
47 #include "utility.h"
48 
49 // Mock classes are not used. Header included to ensure mocked class definition aligns with the
50 // class itself.
51 #include <libsnapshot/mock_device_info.h>
52 #include <libsnapshot/mock_snapshot.h>
53 
54 DEFINE_string(force_config, "", "Force testing mode (dmsnap, vab, vabc) ignoring device config.");
55 DEFINE_string(force_iouring_disable, "",
56               "Force testing mode (iouring_disabled) - disable io_uring");
57 
58 namespace android {
59 namespace snapshot {
60 
61 using android::base::unique_fd;
62 using android::dm::DeviceMapper;
63 using android::dm::DmDeviceState;
64 using android::dm::IDeviceMapper;
65 using android::fiemap::FiemapStatus;
66 using android::fiemap::IImageManager;
67 using android::fs_mgr::BlockDeviceInfo;
68 using android::fs_mgr::CreateLogicalPartitionParams;
69 using android::fs_mgr::DestroyLogicalPartition;
70 using android::fs_mgr::EnsurePathMounted;
71 using android::fs_mgr::EnsurePathUnmounted;
72 using android::fs_mgr::Extent;
73 using android::fs_mgr::Fstab;
74 using android::fs_mgr::GetPartitionGroupName;
75 using android::fs_mgr::GetPartitionName;
76 using android::fs_mgr::Interval;
77 using android::fs_mgr::MetadataBuilder;
78 using android::fs_mgr::SlotSuffixForSlotNumber;
79 using chromeos_update_engine::DeltaArchiveManifest;
80 using chromeos_update_engine::DynamicPartitionGroup;
81 using chromeos_update_engine::PartitionUpdate;
82 using namespace ::testing;
83 using namespace android::storage_literals;
84 using namespace std::chrono_literals;
85 using namespace std::string_literals;
86 
87 // Global states. See test_helpers.h.
88 std::unique_ptr<SnapshotManager> sm;
89 TestDeviceInfo* test_device = nullptr;
90 std::string fake_super;
91 
92 void MountMetadata();
93 bool ShouldUseCompression();
94 bool IsDaemonRequired();
95 
96 class SnapshotTest : public ::testing::Test {
97   public:
SnapshotTest()98     SnapshotTest() : dm_(DeviceMapper::Instance()) {}
99 
100     // This is exposed for main.
Cleanup()101     void Cleanup() {
102         InitializeState();
103         CleanupTestArtifacts();
104     }
105 
106   protected:
SetUp()107     void SetUp() override {
108         SKIP_IF_NON_VIRTUAL_AB();
109 
110         SnapshotTestPropertyFetcher::SetUp();
111         InitializeState();
112         CleanupTestArtifacts();
113         FormatFakeSuper();
114         MountMetadata();
115         ASSERT_TRUE(sm->BeginUpdate());
116     }
117 
TearDown()118     void TearDown() override {
119         RETURN_IF_NON_VIRTUAL_AB();
120 
121         lock_ = nullptr;
122 
123         CleanupTestArtifacts();
124         SnapshotTestPropertyFetcher::TearDown();
125     }
126 
InitializeState()127     void InitializeState() {
128         ASSERT_TRUE(sm->EnsureImageManager());
129         image_manager_ = sm->image_manager();
130 
131         test_device->set_slot_suffix("_a");
132 
133         sm->set_use_first_stage_snapuserd(false);
134     }
135 
CleanupTestArtifacts()136     void CleanupTestArtifacts() {
137         // Normally cancelling inside a merge is not allowed. Since these
138         // are tests, we don't care, destroy everything that might exist.
139         // Note we hardcode this list because of an annoying quirk: when
140         // completing a merge, the snapshot stops existing, so we can't
141         // get an accurate list to remove.
142         lock_ = nullptr;
143 
144         std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
145                                               "test_partition_b"};
146         for (const auto& snapshot : snapshots) {
147             CleanupSnapshotArtifacts(snapshot);
148         }
149 
150         // Remove stale partitions in fake super.
151         std::vector<std::string> partitions = {
152                 "base-device",
153                 "test_partition_b",
154                 "test_partition_b-base",
155                 "test_partition_b-cow",
156         };
157         for (const auto& partition : partitions) {
158             DeleteDevice(partition);
159         }
160 
161         if (sm->GetUpdateState() != UpdateState::None) {
162             auto state_file = sm->GetStateFilePath();
163             unlink(state_file.c_str());
164         }
165     }
166 
CleanupSnapshotArtifacts(const std::string & snapshot)167     void CleanupSnapshotArtifacts(const std::string& snapshot) {
168         // The device-mapper stack may have been collapsed to dm-linear, so it's
169         // necessary to check what state it's in before attempting a cleanup.
170         // SnapshotManager has no path like this because we'd never remove a
171         // merged snapshot (a live partition).
172         bool is_dm_user = false;
173         DeviceMapper::TargetInfo target;
174         if (sm->IsSnapshotDevice(snapshot, &target)) {
175             is_dm_user = (DeviceMapper::GetTargetType(target.spec) == "user");
176         }
177 
178         if (is_dm_user) {
179             ASSERT_TRUE(sm->EnsureSnapuserdConnected());
180             ASSERT_TRUE(AcquireLock());
181 
182             auto local_lock = std::move(lock_);
183             ASSERT_TRUE(sm->UnmapUserspaceSnapshotDevice(local_lock.get(), snapshot));
184         }
185 
186         ASSERT_TRUE(DeleteSnapshotDevice(snapshot));
187         DeleteBackingImage(image_manager_, snapshot + "-cow-img");
188 
189         auto status_file = sm->GetSnapshotStatusFilePath(snapshot);
190         android::base::RemoveFileIfExists(status_file);
191     }
192 
AcquireLock()193     bool AcquireLock() {
194         lock_ = sm->LockExclusive();
195         return !!lock_;
196     }
197 
198     // This is so main() can instantiate this to invoke Cleanup.
TestBody()199     virtual void TestBody() override {}
200 
FormatFakeSuper()201     void FormatFakeSuper() {
202         BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4096);
203         std::vector<BlockDeviceInfo> devices = {super_device};
204 
205         auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
206         ASSERT_NE(builder, nullptr);
207 
208         auto metadata = builder->Export();
209         ASSERT_NE(metadata, nullptr);
210 
211         TestPartitionOpener opener(fake_super);
212         ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *metadata.get()));
213     }
214 
215     // If |path| is non-null, the partition will be mapped after creation.
CreatePartition(const std::string & name,uint64_t size,std::string * path=nullptr,const std::optional<std::string> group={})216     bool CreatePartition(const std::string& name, uint64_t size, std::string* path = nullptr,
217                          const std::optional<std::string> group = {}) {
218         TestPartitionOpener opener(fake_super);
219         auto builder = MetadataBuilder::New(opener, "super", 0);
220         if (!builder) return false;
221 
222         std::string partition_group = std::string(android::fs_mgr::kDefaultGroup);
223         if (group) {
224             partition_group = *group;
225         }
226         return CreatePartition(builder.get(), name, size, path, partition_group);
227     }
228 
CreatePartition(MetadataBuilder * builder,const std::string & name,uint64_t size,std::string * path,const std::string & group)229     bool CreatePartition(MetadataBuilder* builder, const std::string& name, uint64_t size,
230                          std::string* path, const std::string& group) {
231         auto partition = builder->AddPartition(name, group, 0);
232         if (!partition) return false;
233         if (!builder->ResizePartition(partition, size)) {
234             return false;
235         }
236 
237         // Update the source slot.
238         auto metadata = builder->Export();
239         if (!metadata) return false;
240 
241         TestPartitionOpener opener(fake_super);
242         if (!UpdatePartitionTable(opener, "super", *metadata.get(), 0)) {
243             return false;
244         }
245 
246         if (!path) return true;
247 
248         CreateLogicalPartitionParams params = {
249                 .block_device = fake_super,
250                 .metadata = metadata.get(),
251                 .partition_name = name,
252                 .force_writable = true,
253                 .timeout_ms = 10s,
254         };
255         return CreateLogicalPartition(params, path);
256     }
257 
MapUpdateSnapshot(const std::string & name,std::unique_ptr<ISnapshotWriter> * writer)258     AssertionResult MapUpdateSnapshot(const std::string& name,
259                                       std::unique_ptr<ISnapshotWriter>* writer) {
260         TestPartitionOpener opener(fake_super);
261         CreateLogicalPartitionParams params{
262                 .block_device = fake_super,
263                 .metadata_slot = 1,
264                 .partition_name = name,
265                 .timeout_ms = 10s,
266                 .partition_opener = &opener,
267         };
268 
269         auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name);
270         auto result = sm->OpenSnapshotWriter(params, {old_partition});
271         if (!result) {
272             return AssertionFailure() << "Cannot open snapshot for writing: " << name;
273         }
274         if (!result->Initialize()) {
275             return AssertionFailure() << "Cannot initialize snapshot for writing: " << name;
276         }
277 
278         if (writer) {
279             *writer = std::move(result);
280         }
281         return AssertionSuccess();
282     }
283 
MapUpdateSnapshot(const std::string & name,std::string * path)284     AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path) {
285         TestPartitionOpener opener(fake_super);
286         CreateLogicalPartitionParams params{
287                 .block_device = fake_super,
288                 .metadata_slot = 1,
289                 .partition_name = name,
290                 .timeout_ms = 10s,
291                 .partition_opener = &opener,
292         };
293 
294         auto result = sm->MapUpdateSnapshot(params, path);
295         if (!result) {
296             return AssertionFailure() << "Cannot open snapshot for writing: " << name;
297         }
298         return AssertionSuccess();
299     }
300 
DeleteSnapshotDevice(const std::string & snapshot)301     AssertionResult DeleteSnapshotDevice(const std::string& snapshot) {
302         AssertionResult res = AssertionSuccess();
303         if (!(res = DeleteDevice(snapshot))) return res;
304         if (!sm->UnmapDmUserDevice(snapshot + "-user-cow")) {
305             return AssertionFailure() << "Cannot delete dm-user device for " << snapshot;
306         }
307         if (!(res = DeleteDevice(snapshot + "-inner"))) return res;
308         if (!(res = DeleteDevice(snapshot + "-cow"))) return res;
309         if (!image_manager_->UnmapImageIfExists(snapshot + "-cow-img")) {
310             return AssertionFailure() << "Cannot unmap image " << snapshot << "-cow-img";
311         }
312         if (!(res = DeleteDevice(snapshot + "-base"))) return res;
313         if (!(res = DeleteDevice(snapshot + "-src"))) return res;
314         return AssertionSuccess();
315     }
316 
DeleteDevice(const std::string & device)317     AssertionResult DeleteDevice(const std::string& device) {
318         if (!dm_.DeleteDeviceIfExists(device)) {
319             return AssertionFailure() << "Can't delete " << device;
320         }
321         return AssertionSuccess();
322     }
323 
CreateCowImage(const std::string & name)324     AssertionResult CreateCowImage(const std::string& name) {
325         if (!sm->CreateCowImage(lock_.get(), name)) {
326             return AssertionFailure() << "Cannot create COW image " << name;
327         }
328         std::string cow_device;
329         auto map_res = MapCowImage(name, 10s, &cow_device);
330         if (!map_res) {
331             return map_res;
332         }
333         if (!InitializeKernelCow(cow_device)) {
334             return AssertionFailure() << "Cannot zero fill " << cow_device;
335         }
336         if (!sm->UnmapCowImage(name)) {
337             return AssertionFailure() << "Cannot unmap " << name << " after zero filling it";
338         }
339         return AssertionSuccess();
340     }
341 
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)342     AssertionResult MapCowImage(const std::string& name,
343                                 const std::chrono::milliseconds& timeout_ms, std::string* path) {
344         auto cow_image_path = sm->MapCowImage(name, timeout_ms);
345         if (!cow_image_path.has_value()) {
346             return AssertionFailure() << "Cannot map cow image " << name;
347         }
348         *path = *cow_image_path;
349         return AssertionSuccess();
350     }
351 
352     // Prepare A/B slot for a partition named "test_partition".
PrepareOneSnapshot(uint64_t device_size,std::unique_ptr<ISnapshotWriter> * writer=nullptr)353     AssertionResult PrepareOneSnapshot(uint64_t device_size,
354                                        std::unique_ptr<ISnapshotWriter>* writer = nullptr) {
355         lock_ = nullptr;
356 
357         DeltaArchiveManifest manifest;
358 
359         auto dynamic_partition_metadata = manifest.mutable_dynamic_partition_metadata();
360         dynamic_partition_metadata->set_vabc_enabled(IsCompressionEnabled());
361         dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
362 
363         auto group = dynamic_partition_metadata->add_groups();
364         group->set_name("group");
365         group->set_size(device_size * 2);
366         group->add_partition_names("test_partition");
367 
368         auto pu = manifest.add_partitions();
369         pu->set_partition_name("test_partition");
370         pu->set_estimate_cow_size(device_size);
371         SetSize(pu, device_size);
372 
373         auto extent = pu->add_operations()->add_dst_extents();
374         extent->set_start_block(0);
375         if (device_size) {
376             extent->set_num_blocks(device_size / manifest.block_size());
377         }
378 
379         TestPartitionOpener opener(fake_super);
380         auto builder = MetadataBuilder::New(opener, "super", 0);
381         if (!builder) {
382             return AssertionFailure() << "Failed to open MetadataBuilder";
383         }
384         builder->AddGroup("group_a", 16_GiB);
385         builder->AddGroup("group_b", 16_GiB);
386         if (!CreatePartition(builder.get(), "test_partition_a", device_size, nullptr, "group_a")) {
387             return AssertionFailure() << "Failed create test_partition_a";
388         }
389 
390         if (!sm->CreateUpdateSnapshots(manifest)) {
391             return AssertionFailure() << "Failed to create update snapshots";
392         }
393 
394         if (writer) {
395             auto res = MapUpdateSnapshot("test_partition_b", writer);
396             if (!res) {
397                 return res;
398             }
399         } else if (!IsCompressionEnabled()) {
400             std::string ignore;
401             if (!MapUpdateSnapshot("test_partition_b", &ignore)) {
402                 return AssertionFailure() << "Failed to map test_partition_b";
403             }
404         }
405         if (!AcquireLock()) {
406             return AssertionFailure() << "Failed to acquire lock";
407         }
408         return AssertionSuccess();
409     }
410 
411     // Simulate a reboot into the new slot.
SimulateReboot()412     AssertionResult SimulateReboot() {
413         lock_ = nullptr;
414         if (!sm->FinishedSnapshotWrites(false)) {
415             return AssertionFailure() << "Failed to finish snapshot writes";
416         }
417         if (!sm->UnmapUpdateSnapshot("test_partition_b")) {
418             return AssertionFailure() << "Failed to unmap COW for test_partition_b";
419         }
420         if (!dm_.DeleteDeviceIfExists("test_partition_b")) {
421             return AssertionFailure() << "Failed to delete test_partition_b";
422         }
423         if (!dm_.DeleteDeviceIfExists("test_partition_b-base")) {
424             return AssertionFailure() << "Failed to destroy test_partition_b-base";
425         }
426         return AssertionSuccess();
427     }
428 
NewManagerForFirstStageMount(const std::string & slot_suffix="_a")429     std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(
430             const std::string& slot_suffix = "_a") {
431         auto info = new TestDeviceInfo(fake_super, slot_suffix);
432         return NewManagerForFirstStageMount(info);
433     }
434 
NewManagerForFirstStageMount(TestDeviceInfo * info)435     std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(TestDeviceInfo* info) {
436         info->set_first_stage_init(true);
437         auto init = SnapshotManager::NewForFirstStageMount(info);
438         if (!init) {
439             return nullptr;
440         }
441         init->SetUeventRegenCallback([](const std::string& device) -> bool {
442             return android::fs_mgr::WaitForFile(device, snapshot_timeout_);
443         });
444         return init;
445     }
446 
447     static constexpr std::chrono::milliseconds snapshot_timeout_ = 5s;
448     DeviceMapper& dm_;
449     std::unique_ptr<SnapshotManager::LockedFile> lock_;
450     android::fiemap::IImageManager* image_manager_ = nullptr;
451     std::string fake_super_;
452 };
453 
TEST_F(SnapshotTest,CreateSnapshot)454 TEST_F(SnapshotTest, CreateSnapshot) {
455     ASSERT_TRUE(AcquireLock());
456 
457     PartitionCowCreator cow_creator;
458     cow_creator.compression_enabled = ShouldUseCompression();
459     if (cow_creator.compression_enabled) {
460         cow_creator.compression_algorithm = "gz";
461     } else {
462         cow_creator.compression_algorithm = "none";
463     }
464 
465     static const uint64_t kDeviceSize = 1024 * 1024;
466     SnapshotStatus status;
467     status.set_name("test-snapshot");
468     status.set_device_size(kDeviceSize);
469     status.set_snapshot_size(kDeviceSize);
470     status.set_cow_file_size(kDeviceSize);
471     ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
472     ASSERT_TRUE(CreateCowImage("test-snapshot"));
473 
474     std::vector<std::string> snapshots;
475     ASSERT_TRUE(sm->ListSnapshots(lock_.get(), &snapshots));
476     ASSERT_EQ(snapshots.size(), 1);
477     ASSERT_EQ(snapshots[0], "test-snapshot");
478 
479     // Scope so delete can re-acquire the snapshot file lock.
480     {
481         SnapshotStatus status;
482         ASSERT_TRUE(sm->ReadSnapshotStatus(lock_.get(), "test-snapshot", &status));
483         ASSERT_EQ(status.state(), SnapshotState::CREATED);
484         ASSERT_EQ(status.device_size(), kDeviceSize);
485         ASSERT_EQ(status.snapshot_size(), kDeviceSize);
486         ASSERT_EQ(status.compression_enabled(), cow_creator.compression_enabled);
487         ASSERT_EQ(status.compression_algorithm(), cow_creator.compression_algorithm);
488     }
489 
490     ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
491     ASSERT_TRUE(sm->UnmapCowImage("test-snapshot"));
492     ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
493 }
494 
TEST_F(SnapshotTest,MapSnapshot)495 TEST_F(SnapshotTest, MapSnapshot) {
496     ASSERT_TRUE(AcquireLock());
497 
498     PartitionCowCreator cow_creator;
499     cow_creator.compression_enabled = ShouldUseCompression();
500 
501     static const uint64_t kDeviceSize = 1024 * 1024;
502     SnapshotStatus status;
503     status.set_name("test-snapshot");
504     status.set_device_size(kDeviceSize);
505     status.set_snapshot_size(kDeviceSize);
506     status.set_cow_file_size(kDeviceSize);
507     ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
508     ASSERT_TRUE(CreateCowImage("test-snapshot"));
509 
510     std::string base_device;
511     ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
512 
513     std::string cow_device;
514     ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
515 
516     std::string snap_device;
517     ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
518                                 &snap_device));
519     ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
520 }
521 
TEST_F(SnapshotTest,NoMergeBeforeReboot)522 TEST_F(SnapshotTest, NoMergeBeforeReboot) {
523     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
524 
525     // Merge should fail, since the slot hasn't changed.
526     ASSERT_FALSE(sm->InitiateMerge());
527 }
528 
TEST_F(SnapshotTest,CleanFirstStageMount)529 TEST_F(SnapshotTest, CleanFirstStageMount) {
530     // If there's no update in progress, there should be no first-stage mount
531     // needed.
532     auto sm = NewManagerForFirstStageMount();
533     ASSERT_NE(sm, nullptr);
534     ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
535 }
536 
TEST_F(SnapshotTest,FirstStageMountAfterRollback)537 TEST_F(SnapshotTest, FirstStageMountAfterRollback) {
538     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
539 
540     // We didn't change the slot, so we shouldn't need snapshots.
541     auto sm = NewManagerForFirstStageMount();
542     ASSERT_NE(sm, nullptr);
543     ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
544 
545     auto indicator = sm->GetRollbackIndicatorPath();
546     ASSERT_EQ(access(indicator.c_str(), R_OK), 0);
547 }
548 
TEST_F(SnapshotTest,Merge)549 TEST_F(SnapshotTest, Merge) {
550     ASSERT_TRUE(AcquireLock());
551 
552     static const uint64_t kDeviceSize = 1024 * 1024;
553 
554     std::unique_ptr<ISnapshotWriter> writer;
555     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer));
556 
557     bool userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get());
558 
559     // Release the lock.
560     lock_ = nullptr;
561 
562     std::string test_string = "This is a test string.";
563     test_string.resize(writer->options().block_size);
564     ASSERT_TRUE(writer->AddRawBlocks(0, test_string.data(), test_string.size()));
565     ASSERT_TRUE(writer->Finalize());
566     writer = nullptr;
567 
568     // Done updating.
569     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
570 
571     ASSERT_TRUE(sm->UnmapUpdateSnapshot("test_partition_b"));
572 
573     test_device->set_slot_suffix("_b");
574     ASSERT_TRUE(sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
575     ASSERT_TRUE(sm->InitiateMerge());
576 
577     // The device should have been switched to a snapshot-merge target.
578     DeviceMapper::TargetInfo target;
579     ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
580     if (userspace_snapshots) {
581         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
582     } else {
583         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
584     }
585 
586     // We should not be able to cancel an update now.
587     ASSERT_FALSE(sm->CancelUpdate());
588 
589     ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
590     ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
591 
592     // The device should no longer be a snapshot or snapshot-merge.
593     ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
594 
595     // Test that we can read back the string we wrote to the snapshot. Note
596     // that the base device is gone now. |snap_device| contains the correct
597     // partition.
598     unique_fd fd(open("/dev/block/mapper/test_partition_b", O_RDONLY | O_CLOEXEC));
599     ASSERT_GE(fd, 0);
600 
601     std::string buffer(test_string.size(), '\0');
602     ASSERT_TRUE(android::base::ReadFully(fd, buffer.data(), buffer.size()));
603     ASSERT_EQ(test_string, buffer);
604 }
605 
TEST_F(SnapshotTest,FirstStageMountAndMerge)606 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
607     ASSERT_TRUE(AcquireLock());
608 
609     static const uint64_t kDeviceSize = 1024 * 1024;
610     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
611     ASSERT_TRUE(SimulateReboot());
612 
613     auto init = NewManagerForFirstStageMount("_b");
614     ASSERT_NE(init, nullptr);
615     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
616     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
617 
618     ASSERT_TRUE(AcquireLock());
619 
620     bool userspace_snapshots = init->UpdateUsesUserSnapshots(lock_.get());
621 
622     // Validate that we have a snapshot device.
623     SnapshotStatus status;
624     ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
625     ASSERT_EQ(status.state(), SnapshotState::CREATED);
626     if (ShouldUseCompression()) {
627         ASSERT_EQ(status.compression_algorithm(), "gz");
628     } else {
629         ASSERT_EQ(status.compression_algorithm(), "none");
630     }
631 
632     DeviceMapper::TargetInfo target;
633     ASSERT_TRUE(init->IsSnapshotDevice("test_partition_b", &target));
634     if (userspace_snapshots) {
635         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
636     } else {
637         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
638     }
639 }
640 
TEST_F(SnapshotTest,FlashSuperDuringUpdate)641 TEST_F(SnapshotTest, FlashSuperDuringUpdate) {
642     ASSERT_TRUE(AcquireLock());
643 
644     static const uint64_t kDeviceSize = 1024 * 1024;
645     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
646     ASSERT_TRUE(SimulateReboot());
647 
648     // Reflash the super partition.
649     FormatFakeSuper();
650     ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
651 
652     auto init = NewManagerForFirstStageMount("_b");
653     ASSERT_NE(init, nullptr);
654     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
655     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
656 
657     ASSERT_TRUE(AcquireLock());
658 
659     SnapshotStatus status;
660     ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
661 
662     // We should not get a snapshot device now.
663     DeviceMapper::TargetInfo target;
664     ASSERT_FALSE(init->IsSnapshotDevice("test_partition_b", &target));
665 
666     // We should see a cancelled update as well.
667     lock_ = nullptr;
668     ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
669 }
670 
TEST_F(SnapshotTest,FlashSuperDuringMerge)671 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
672     ASSERT_TRUE(AcquireLock());
673 
674     static const uint64_t kDeviceSize = 1024 * 1024;
675     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
676     ASSERT_TRUE(SimulateReboot());
677 
678     auto init = NewManagerForFirstStageMount("_b");
679     ASSERT_NE(init, nullptr);
680     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
681     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
682     ASSERT_TRUE(init->InitiateMerge());
683 
684     // Now, reflash super. Note that we haven't called ProcessUpdateState, so the
685     // status is still Merging.
686     ASSERT_TRUE(DeleteSnapshotDevice("test_partition_b"));
687     ASSERT_TRUE(init->image_manager()->UnmapImageIfExists("test_partition_b-cow-img"));
688     FormatFakeSuper();
689     ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
690     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
691     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
692 
693     // Because the status is Merging, we must call ProcessUpdateState, which should
694     // detect a cancelled update.
695     ASSERT_EQ(init->ProcessUpdateState(), UpdateState::Cancelled);
696     ASSERT_EQ(init->GetUpdateState(), UpdateState::None);
697 }
698 
TEST_F(SnapshotTest,UpdateBootControlHal)699 TEST_F(SnapshotTest, UpdateBootControlHal) {
700     ASSERT_TRUE(AcquireLock());
701 
702     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
703     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
704 
705     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
706     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
707 
708     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
709     ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
710 
711     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
712     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
713 
714     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
715     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
716 
717     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
718     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
719 
720     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
721     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
722 }
723 
TEST_F(SnapshotTest,MergeFailureCode)724 TEST_F(SnapshotTest, MergeFailureCode) {
725     ASSERT_TRUE(AcquireLock());
726 
727     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed,
728                                      MergeFailureCode::ListSnapshots));
729     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
730 
731     SnapshotUpdateStatus status = sm->ReadSnapshotUpdateStatus(lock_.get());
732     ASSERT_EQ(status.state(), UpdateState::MergeFailed);
733     ASSERT_EQ(status.merge_failure_code(), MergeFailureCode::ListSnapshots);
734 }
735 
736 enum class Request { UNKNOWN, LOCK_SHARED, LOCK_EXCLUSIVE, UNLOCK, EXIT };
operator <<(std::ostream & os,Request request)737 std::ostream& operator<<(std::ostream& os, Request request) {
738     switch (request) {
739         case Request::LOCK_SHARED:
740             return os << "Shared";
741         case Request::LOCK_EXCLUSIVE:
742             return os << "Exclusive";
743         case Request::UNLOCK:
744             return os << "Unlock";
745         case Request::EXIT:
746             return os << "Exit";
747         case Request::UNKNOWN:
748             [[fallthrough]];
749         default:
750             return os << "Unknown";
751     }
752 }
753 
754 class LockTestConsumer {
755   public:
MakeRequest(Request new_request)756     AssertionResult MakeRequest(Request new_request) {
757         {
758             std::unique_lock<std::mutex> ulock(mutex_);
759             requests_.push_back(new_request);
760         }
761         cv_.notify_all();
762         return AssertionSuccess() << "Request " << new_request << " successful";
763     }
764 
765     template <typename R, typename P>
WaitFulfill(std::chrono::duration<R,P> timeout)766     AssertionResult WaitFulfill(std::chrono::duration<R, P> timeout) {
767         std::unique_lock<std::mutex> ulock(mutex_);
768         if (cv_.wait_for(ulock, timeout, [this] { return requests_.empty(); })) {
769             return AssertionSuccess() << "All requests_ fulfilled.";
770         }
771         return AssertionFailure() << "Timeout waiting for fulfilling " << requests_.size()
772                                   << " request(s), first one is "
773                                   << (requests_.empty() ? Request::UNKNOWN : requests_.front());
774     }
775 
StartHandleRequestsInBackground()776     void StartHandleRequestsInBackground() {
777         future_ = std::async(std::launch::async, &LockTestConsumer::HandleRequests, this);
778     }
779 
780   private:
HandleRequests()781     void HandleRequests() {
782         static constexpr auto consumer_timeout = 3s;
783 
784         auto next_request = Request::UNKNOWN;
785         do {
786             // Peek next request.
787             {
788                 std::unique_lock<std::mutex> ulock(mutex_);
789                 if (cv_.wait_for(ulock, consumer_timeout, [this] { return !requests_.empty(); })) {
790                     next_request = requests_.front();
791                 } else {
792                     next_request = Request::EXIT;
793                 }
794             }
795 
796             // Handle next request.
797             switch (next_request) {
798                 case Request::LOCK_SHARED: {
799                     lock_ = sm->LockShared();
800                 } break;
801                 case Request::LOCK_EXCLUSIVE: {
802                     lock_ = sm->LockExclusive();
803                 } break;
804                 case Request::EXIT:
805                     [[fallthrough]];
806                 case Request::UNLOCK: {
807                     lock_.reset();
808                 } break;
809                 case Request::UNKNOWN:
810                     [[fallthrough]];
811                 default:
812                     break;
813             }
814 
815             // Pop next request. This thread is the only thread that
816             // pops from the front of the requests_ deque.
817             {
818                 std::unique_lock<std::mutex> ulock(mutex_);
819                 if (next_request == Request::EXIT) {
820                     requests_.clear();
821                 } else {
822                     requests_.pop_front();
823                 }
824             }
825             cv_.notify_all();
826         } while (next_request != Request::EXIT);
827     }
828 
829     std::mutex mutex_;
830     std::condition_variable cv_;
831     std::deque<Request> requests_;
832     std::unique_ptr<SnapshotManager::LockedFile> lock_;
833     std::future<void> future_;
834 };
835 
836 class LockTest : public ::testing::Test {
837   public:
SetUp()838     void SetUp() {
839         SKIP_IF_NON_VIRTUAL_AB();
840         first_consumer.StartHandleRequestsInBackground();
841         second_consumer.StartHandleRequestsInBackground();
842     }
843 
TearDown()844     void TearDown() {
845         RETURN_IF_NON_VIRTUAL_AB();
846         EXPECT_TRUE(first_consumer.MakeRequest(Request::EXIT));
847         EXPECT_TRUE(second_consumer.MakeRequest(Request::EXIT));
848     }
849 
850     static constexpr auto request_timeout = 500ms;
851     LockTestConsumer first_consumer;
852     LockTestConsumer second_consumer;
853 };
854 
TEST_F(LockTest,SharedShared)855 TEST_F(LockTest, SharedShared) {
856     ASSERT_TRUE(first_consumer.MakeRequest(Request::LOCK_SHARED));
857     ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
858     ASSERT_TRUE(second_consumer.MakeRequest(Request::LOCK_SHARED));
859     ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout));
860 }
861 
862 using LockTestParam = std::pair<Request, Request>;
863 class LockTestP : public LockTest, public ::testing::WithParamInterface<LockTestParam> {};
TEST_P(LockTestP,Test)864 TEST_P(LockTestP, Test) {
865     ASSERT_TRUE(first_consumer.MakeRequest(GetParam().first));
866     ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
867     ASSERT_TRUE(second_consumer.MakeRequest(GetParam().second));
868     ASSERT_FALSE(second_consumer.WaitFulfill(request_timeout))
869             << "Should not be able to " << GetParam().second << " while separate thread "
870             << GetParam().first;
871     ASSERT_TRUE(first_consumer.MakeRequest(Request::UNLOCK));
872     ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout))
873             << "Should be able to hold lock that is released by separate thread";
874 }
875 INSTANTIATE_TEST_SUITE_P(
876         LockTest, LockTestP,
877         testing::Values(LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_EXCLUSIVE},
878                         LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_SHARED},
879                         LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
__anon581dab5a0402(const testing::TestParamInfo<LockTestP::ParamType>& info) 880         [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
881             std::stringstream ss;
882             ss << info.param.first << info.param.second;
883             return ss.str();
884         });
885 
886 class SnapshotUpdateTest : public SnapshotTest {
887   public:
SetUp()888     void SetUp() override {
889         SKIP_IF_NON_VIRTUAL_AB();
890 
891         SnapshotTest::SetUp();
892         Cleanup();
893 
894         // Cleanup() changes slot suffix, so initialize it again.
895         test_device->set_slot_suffix("_a");
896 
897         opener_ = std::make_unique<TestPartitionOpener>(fake_super);
898 
899         auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
900         dynamic_partition_metadata->set_vabc_enabled(ShouldUseCompression());
901         dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
902 
903         // Create a fake update package metadata.
904         // Not using full name "system", "vendor", "product" because these names collide with the
905         // mapped partitions on the running device.
906         // Each test modifies manifest_ slightly to indicate changes to the partition layout.
907         group_ = dynamic_partition_metadata->add_groups();
908         group_->set_name("group");
909         group_->set_size(kGroupSize);
910         group_->add_partition_names("sys");
911         group_->add_partition_names("vnd");
912         group_->add_partition_names("prd");
913         sys_ = manifest_.add_partitions();
914         sys_->set_partition_name("sys");
915         sys_->set_estimate_cow_size(2_MiB);
916         SetSize(sys_, 3_MiB);
917         vnd_ = manifest_.add_partitions();
918         vnd_->set_partition_name("vnd");
919         vnd_->set_estimate_cow_size(2_MiB);
920         SetSize(vnd_, 3_MiB);
921         prd_ = manifest_.add_partitions();
922         prd_->set_partition_name("prd");
923         prd_->set_estimate_cow_size(2_MiB);
924         SetSize(prd_, 3_MiB);
925 
926         // Initialize source partition metadata using |manifest_|.
927         src_ = MetadataBuilder::New(*opener_, "super", 0);
928         ASSERT_NE(src_, nullptr);
929         ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
930         // Add sys_b which is like system_other.
931         ASSERT_TRUE(src_->AddGroup("group_b", kGroupSize));
932         auto partition = src_->AddPartition("sys_b", "group_b", 0);
933         ASSERT_NE(nullptr, partition);
934         ASSERT_TRUE(src_->ResizePartition(partition, 1_MiB));
935         auto metadata = src_->Export();
936         ASSERT_NE(nullptr, metadata);
937         ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
938 
939         // Map source partitions.
940         std::string path;
941         for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
942             ASSERT_TRUE(CreateLogicalPartition(
943                     CreateLogicalPartitionParams{
944                             .block_device = fake_super,
945                             .metadata_slot = 0,
946                             .partition_name = name,
947                             .timeout_ms = 1s,
948                             .partition_opener = opener_.get(),
949                     },
950                     &path));
951             ASSERT_TRUE(WriteRandomData(path));
952             auto hash = GetHash(path);
953             ASSERT_TRUE(hash.has_value());
954             hashes_[name] = *hash;
955         }
956 
957         // OTA client blindly unmaps all partitions that are possibly mapped.
958         for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
959             ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
960         }
961     }
TearDown()962     void TearDown() override {
963         RETURN_IF_NON_VIRTUAL_AB();
964 
965         Cleanup();
966         SnapshotTest::TearDown();
967     }
Cleanup()968     void Cleanup() {
969         if (!image_manager_) {
970             InitializeState();
971         }
972         MountMetadata();
973         for (const auto& suffix : {"_a", "_b"}) {
974             test_device->set_slot_suffix(suffix);
975 
976             // Cheat our way out of merge failed states.
977             if (sm->ProcessUpdateState() == UpdateState::MergeFailed) {
978                 ASSERT_TRUE(AcquireLock());
979                 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
980                 lock_ = {};
981             }
982 
983             EXPECT_TRUE(sm->CancelUpdate()) << suffix;
984         }
985         EXPECT_TRUE(UnmapAll());
986     }
987 
IsPartitionUnchanged(const std::string & name)988     AssertionResult IsPartitionUnchanged(const std::string& name) {
989         std::string path;
990         if (!dm_.GetDmDevicePathByName(name, &path)) {
991             return AssertionFailure() << "Path of " << name << " cannot be determined";
992         }
993         auto hash = GetHash(path);
994         if (!hash.has_value()) {
995             return AssertionFailure() << "Cannot read partition " << name << ": " << path;
996         }
997         auto it = hashes_.find(name);
998         if (it == hashes_.end()) {
999             return AssertionFailure() << "No existing hash for " << name << ". Bad test code?";
1000         }
1001         if (it->second != *hash) {
1002             return AssertionFailure() << "Content of " << name << " has changed";
1003         }
1004         return AssertionSuccess();
1005     }
1006 
GetSnapshotSize(const std::string & name)1007     std::optional<uint64_t> GetSnapshotSize(const std::string& name) {
1008         if (!AcquireLock()) {
1009             return std::nullopt;
1010         }
1011         auto local_lock = std::move(lock_);
1012 
1013         SnapshotStatus status;
1014         if (!sm->ReadSnapshotStatus(local_lock.get(), name, &status)) {
1015             return std::nullopt;
1016         }
1017         return status.snapshot_size();
1018     }
1019 
UnmapAll()1020     AssertionResult UnmapAll() {
1021         for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) {
1022             if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
1023                 return AssertionFailure() << "Cannot unmap " << name << "_a";
1024             }
1025             if (!DeleteSnapshotDevice(name + "_b"s)) {
1026                 return AssertionFailure() << "Cannot delete snapshot " << name << "_b";
1027             }
1028         }
1029         return AssertionSuccess();
1030     }
1031 
MapOneUpdateSnapshot(const std::string & name)1032     AssertionResult MapOneUpdateSnapshot(const std::string& name) {
1033         if (ShouldUseCompression()) {
1034             std::unique_ptr<ISnapshotWriter> writer;
1035             return MapUpdateSnapshot(name, &writer);
1036         } else {
1037             std::string path;
1038             return MapUpdateSnapshot(name, &path);
1039         }
1040     }
1041 
WriteSnapshotAndHash(const std::string & name)1042     AssertionResult WriteSnapshotAndHash(const std::string& name) {
1043         if (ShouldUseCompression()) {
1044             std::unique_ptr<ISnapshotWriter> writer;
1045             auto res = MapUpdateSnapshot(name, &writer);
1046             if (!res) {
1047                 return res;
1048             }
1049             if (!WriteRandomData(writer.get(), &hashes_[name])) {
1050                 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1051             }
1052             if (!writer->Finalize()) {
1053                 return AssertionFailure() << "Unable to finalize COW for " << name;
1054             }
1055         } else {
1056             std::string path;
1057             auto res = MapUpdateSnapshot(name, &path);
1058             if (!res) {
1059                 return res;
1060             }
1061             if (!WriteRandomData(path, std::nullopt, &hashes_[name])) {
1062                 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1063             }
1064         }
1065 
1066         // Make sure updates to one device are seen by all devices.
1067         sync();
1068 
1069         return AssertionSuccess() << "Written random data to snapshot " << name
1070                                   << ", hash: " << hashes_[name];
1071     }
1072 
1073     // Generate a snapshot that moves all the upper blocks down to the start.
1074     // It doesn't really matter the order, we just want copies that reference
1075     // blocks that won't exist if the partition shrinks.
ShiftAllSnapshotBlocks(const std::string & name,uint64_t old_size)1076     AssertionResult ShiftAllSnapshotBlocks(const std::string& name, uint64_t old_size) {
1077         std::unique_ptr<ISnapshotWriter> writer;
1078         if (auto res = MapUpdateSnapshot(name, &writer); !res) {
1079             return res;
1080         }
1081         if (!writer->options().max_blocks || !*writer->options().max_blocks) {
1082             return AssertionFailure() << "No max blocks set for " << name << " writer";
1083         }
1084 
1085         uint64_t src_block = (old_size / writer->options().block_size) - 1;
1086         uint64_t dst_block = 0;
1087         uint64_t max_blocks = *writer->options().max_blocks;
1088         while (dst_block < max_blocks && dst_block < src_block) {
1089             if (!writer->AddCopy(dst_block, src_block)) {
1090                 return AssertionFailure() << "Unable to add copy for " << name << " for blocks "
1091                                           << src_block << ", " << dst_block;
1092             }
1093             dst_block++;
1094             src_block--;
1095         }
1096         if (!writer->Finalize()) {
1097             return AssertionFailure() << "Unable to finalize writer for " << name;
1098         }
1099 
1100         auto hash = HashSnapshot(writer.get());
1101         if (hash.empty()) {
1102             return AssertionFailure() << "Unable to hash snapshot writer for " << name;
1103         }
1104         hashes_[name] = hash;
1105 
1106         return AssertionSuccess();
1107     }
1108 
MapUpdateSnapshots(const std::vector<std::string> & names={"sys_b", "vnd_b", "prd_b"})1109     AssertionResult MapUpdateSnapshots(const std::vector<std::string>& names = {"sys_b", "vnd_b",
1110                                                                                 "prd_b"}) {
1111         for (const auto& name : names) {
1112             auto res = MapOneUpdateSnapshot(name);
1113             if (!res) {
1114                 return res;
1115             }
1116         }
1117         return AssertionSuccess();
1118     }
1119 
1120     // Create fake install operations to grow the COW device size.
AddOperation(PartitionUpdate * partition_update,uint64_t size_bytes=0)1121     void AddOperation(PartitionUpdate* partition_update, uint64_t size_bytes = 0) {
1122         auto e = partition_update->add_operations()->add_dst_extents();
1123         e->set_start_block(0);
1124         if (size_bytes == 0) {
1125             size_bytes = GetSize(partition_update);
1126         }
1127         e->set_num_blocks(size_bytes / manifest_.block_size());
1128     }
1129 
AddOperationForPartitions(std::vector<PartitionUpdate * > partitions={})1130     void AddOperationForPartitions(std::vector<PartitionUpdate*> partitions = {}) {
1131         if (partitions.empty()) {
1132             partitions = {sys_, vnd_, prd_};
1133         }
1134         for (auto* partition : partitions) {
1135             AddOperation(partition);
1136         }
1137     }
1138 
1139     std::unique_ptr<TestPartitionOpener> opener_;
1140     DeltaArchiveManifest manifest_;
1141     std::unique_ptr<MetadataBuilder> src_;
1142     std::map<std::string, std::string> hashes_;
1143 
1144     PartitionUpdate* sys_ = nullptr;
1145     PartitionUpdate* vnd_ = nullptr;
1146     PartitionUpdate* prd_ = nullptr;
1147     DynamicPartitionGroup* group_ = nullptr;
1148 };
1149 
1150 // Test full update flow executed by update_engine. Some partitions uses super empty space,
1151 // some uses images, and some uses both.
1152 // Also test UnmapUpdateSnapshot unmaps everything.
1153 // Also test first stage mount and merge after this.
TEST_F(SnapshotUpdateTest,FullUpdateFlow)1154 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
1155     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
1156     // fit in super, but not |prd|.
1157     constexpr uint64_t partition_size = 3788_KiB;
1158     SetSize(sys_, partition_size);
1159     SetSize(vnd_, partition_size);
1160     SetSize(prd_, 18_MiB);
1161 
1162     // Make sure |prd| does not fit in super at all. On VABC, this means we
1163     // fake an extra large COW for |vnd| to fill up super.
1164     vnd_->set_estimate_cow_size(30_MiB);
1165     prd_->set_estimate_cow_size(30_MiB);
1166 
1167     AddOperationForPartitions();
1168 
1169     // Execute the update.
1170     ASSERT_TRUE(sm->BeginUpdate());
1171     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1172 
1173     // Test that partitions prioritize using space in super.
1174     auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1175     ASSERT_NE(tgt, nullptr);
1176     ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
1177     ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
1178     ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
1179 
1180     // Write some data to target partitions.
1181     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1182         ASSERT_TRUE(WriteSnapshotAndHash(name));
1183     }
1184 
1185     // Assert that source partitions aren't affected.
1186     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1187         ASSERT_TRUE(IsPartitionUnchanged(name));
1188     }
1189 
1190     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1191 
1192     // Simulate shutting down the device.
1193     ASSERT_TRUE(UnmapAll());
1194 
1195     // After reboot, init does first stage mount.
1196     auto init = NewManagerForFirstStageMount("_b");
1197     ASSERT_NE(init, nullptr);
1198     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1199     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1200 
1201     auto indicator = sm->GetRollbackIndicatorPath();
1202     ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1203 
1204     // Check that the target partitions have the same content.
1205     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1206         ASSERT_TRUE(IsPartitionUnchanged(name));
1207     }
1208 
1209     // Initiate the merge and wait for it to be completed.
1210     ASSERT_TRUE(init->InitiateMerge());
1211     ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1212     {
1213         // We should have started in SECOND_PHASE since nothing shrinks.
1214         ASSERT_TRUE(AcquireLock());
1215         auto local_lock = std::move(lock_);
1216         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1217         ASSERT_EQ(status.merge_phase(), MergePhase::SECOND_PHASE);
1218     }
1219     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1220 
1221     // Make sure the second phase ran and deleted snapshots.
1222     {
1223         ASSERT_TRUE(AcquireLock());
1224         auto local_lock = std::move(lock_);
1225         std::vector<std::string> snapshots;
1226         ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1227         ASSERT_TRUE(snapshots.empty());
1228     }
1229 
1230     // Check that the target partitions have the same content after the merge.
1231     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1232         ASSERT_TRUE(IsPartitionUnchanged(name))
1233                 << "Content of " << name << " changes after the merge";
1234     }
1235 }
1236 
TEST_F(SnapshotUpdateTest,DuplicateOps)1237 TEST_F(SnapshotUpdateTest, DuplicateOps) {
1238     if (!ShouldUseCompression()) {
1239         GTEST_SKIP() << "Compression-only test";
1240     }
1241 
1242     // Execute the update.
1243     ASSERT_TRUE(sm->BeginUpdate());
1244     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1245 
1246     // Write some data to target partitions.
1247     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1248         ASSERT_TRUE(WriteSnapshotAndHash(name));
1249     }
1250 
1251     std::vector<PartitionUpdate*> partitions = {sys_, vnd_, prd_};
1252     for (auto* partition : partitions) {
1253         AddOperation(partition);
1254 
1255         std::unique_ptr<ISnapshotWriter> writer;
1256         auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer);
1257         ASSERT_TRUE(res);
1258         ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1259         ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1260         ASSERT_TRUE(writer->Finalize());
1261     }
1262 
1263     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1264 
1265     // Simulate shutting down the device.
1266     ASSERT_TRUE(UnmapAll());
1267 
1268     // After reboot, init does first stage mount.
1269     auto init = NewManagerForFirstStageMount("_b");
1270     ASSERT_NE(init, nullptr);
1271     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1272     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1273 
1274     // Initiate the merge and wait for it to be completed.
1275     ASSERT_TRUE(init->InitiateMerge());
1276     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1277 }
1278 
1279 // Test that shrinking and growing partitions at the same time is handled
1280 // correctly in VABC.
TEST_F(SnapshotUpdateTest,SpaceSwapUpdate)1281 TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {
1282     if (!ShouldUseCompression()) {
1283         // b/179111359
1284         GTEST_SKIP() << "Skipping Virtual A/B Compression test";
1285     }
1286 
1287     auto old_sys_size = GetSize(sys_);
1288     auto old_prd_size = GetSize(prd_);
1289 
1290     // Grow |sys| but shrink |prd|.
1291     SetSize(sys_, old_sys_size * 2);
1292     sys_->set_estimate_cow_size(8_MiB);
1293     SetSize(prd_, old_prd_size / 2);
1294     prd_->set_estimate_cow_size(1_MiB);
1295 
1296     AddOperationForPartitions();
1297 
1298     ASSERT_TRUE(sm->BeginUpdate());
1299     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1300 
1301     // Check that the old partition sizes were saved correctly.
1302     {
1303         ASSERT_TRUE(AcquireLock());
1304         auto local_lock = std::move(lock_);
1305 
1306         SnapshotStatus status;
1307         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "prd_b", &status));
1308         ASSERT_EQ(status.old_partition_size(), 3145728);
1309         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "sys_b", &status));
1310         ASSERT_EQ(status.old_partition_size(), 3145728);
1311     }
1312 
1313     ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
1314     ASSERT_TRUE(WriteSnapshotAndHash("vnd_b"));
1315     ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1316 
1317     sync();
1318 
1319     // Assert that source partitions aren't affected.
1320     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1321         ASSERT_TRUE(IsPartitionUnchanged(name));
1322     }
1323 
1324     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1325 
1326     // Simulate shutting down the device.
1327     ASSERT_TRUE(UnmapAll());
1328 
1329     // After reboot, init does first stage mount.
1330     auto init = NewManagerForFirstStageMount("_b");
1331     ASSERT_NE(init, nullptr);
1332     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1333     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1334 
1335     auto indicator = sm->GetRollbackIndicatorPath();
1336     ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1337 
1338     // Check that the target partitions have the same content.
1339     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1340         ASSERT_TRUE(IsPartitionUnchanged(name));
1341     }
1342 
1343     // Initiate the merge and wait for it to be completed.
1344     ASSERT_TRUE(init->InitiateMerge());
1345     ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1346     {
1347         // Check that the merge phase is FIRST_PHASE until at least one call
1348         // to ProcessUpdateState() occurs.
1349         ASSERT_TRUE(AcquireLock());
1350         auto local_lock = std::move(lock_);
1351         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1352         ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1353     }
1354 
1355     // Simulate shutting down the device and creating partitions again.
1356     ASSERT_TRUE(UnmapAll());
1357     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1358 
1359     // Check that we used the correct types after rebooting mid-merge.
1360     DeviceMapper::TargetInfo target;
1361     ASSERT_TRUE(init->IsSnapshotDevice("prd_b", &target));
1362 
1363     bool userspace_snapshots = init->UpdateUsesUserSnapshots();
1364     if (userspace_snapshots) {
1365         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1366         ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1367         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1368         ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1369         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1370     } else {
1371         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
1372         ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1373         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1374         ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1375         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1376     }
1377 
1378     // Complete the merge.
1379     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1380 
1381     // Make sure the second phase ran and deleted snapshots.
1382     {
1383         ASSERT_TRUE(AcquireLock());
1384         auto local_lock = std::move(lock_);
1385         std::vector<std::string> snapshots;
1386         ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1387         ASSERT_TRUE(snapshots.empty());
1388     }
1389 
1390     // Check that the target partitions have the same content after the merge.
1391     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1392         ASSERT_TRUE(IsPartitionUnchanged(name))
1393                 << "Content of " << name << " changes after the merge";
1394     }
1395 }
1396 
1397 // Test that a transient merge consistency check failure can resume properly.
TEST_F(SnapshotUpdateTest,ConsistencyCheckResume)1398 TEST_F(SnapshotUpdateTest, ConsistencyCheckResume) {
1399     if (!ShouldUseCompression()) {
1400         // b/179111359
1401         GTEST_SKIP() << "Skipping Virtual A/B Compression test";
1402     }
1403 
1404     auto old_sys_size = GetSize(sys_);
1405     auto old_prd_size = GetSize(prd_);
1406 
1407     // Grow |sys| but shrink |prd|.
1408     SetSize(sys_, old_sys_size * 2);
1409     sys_->set_estimate_cow_size(8_MiB);
1410     SetSize(prd_, old_prd_size / 2);
1411     prd_->set_estimate_cow_size(1_MiB);
1412 
1413     AddOperationForPartitions();
1414 
1415     ASSERT_TRUE(sm->BeginUpdate());
1416     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1417     ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
1418     ASSERT_TRUE(WriteSnapshotAndHash("vnd_b"));
1419     ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1420 
1421     sync();
1422 
1423     // Assert that source partitions aren't affected.
1424     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1425         ASSERT_TRUE(IsPartitionUnchanged(name));
1426     }
1427 
1428     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1429 
1430     // Simulate shutting down the device.
1431     ASSERT_TRUE(UnmapAll());
1432 
1433     // After reboot, init does first stage mount.
1434     auto init = NewManagerForFirstStageMount("_b");
1435     ASSERT_NE(init, nullptr);
1436     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1437     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1438 
1439     // Check that the target partitions have the same content.
1440     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1441         ASSERT_TRUE(IsPartitionUnchanged(name));
1442     }
1443 
1444     auto old_checker = init->merge_consistency_checker();
1445 
1446     init->set_merge_consistency_checker(
1447             [](const std::string&, const SnapshotStatus&) -> MergeFailureCode {
1448                 return MergeFailureCode::WrongMergeCountConsistencyCheck;
1449             });
1450 
1451     // Initiate the merge and wait for it to be completed.
1452     ASSERT_TRUE(init->InitiateMerge());
1453     ASSERT_EQ(init->IsSnapuserdRequired(), IsDaemonRequired());
1454     {
1455         // Check that the merge phase is FIRST_PHASE until at least one call
1456         // to ProcessUpdateState() occurs.
1457         ASSERT_TRUE(AcquireLock());
1458         auto local_lock = std::move(lock_);
1459         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1460         ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1461     }
1462 
1463     // Merge should have failed.
1464     ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
1465 
1466     // Simulate shutting down the device and creating partitions again.
1467     ASSERT_TRUE(UnmapAll());
1468 
1469     // Restore the checker.
1470     init->set_merge_consistency_checker(std::move(old_checker));
1471 
1472     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1473 
1474     // Complete the merge.
1475     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1476 
1477     // Check that the target partitions have the same content after the merge.
1478     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1479         ASSERT_TRUE(IsPartitionUnchanged(name))
1480                 << "Content of " << name << " changes after the merge";
1481     }
1482 }
1483 
1484 // Test that if new system partitions uses empty space in super, that region is not snapshotted.
TEST_F(SnapshotUpdateTest,DirectWriteEmptySpace)1485 TEST_F(SnapshotUpdateTest, DirectWriteEmptySpace) {
1486     GTEST_SKIP() << "b/141889746";
1487     SetSize(sys_, 4_MiB);
1488     // vnd_b and prd_b are unchanged.
1489     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1490     ASSERT_EQ(3_MiB, GetSnapshotSize("sys_b").value_or(0));
1491 }
1492 
1493 // Test that if new system partitions uses space of old vendor partition, that region is
1494 // snapshotted.
TEST_F(SnapshotUpdateTest,SnapshotOldPartitions)1495 TEST_F(SnapshotUpdateTest, SnapshotOldPartitions) {
1496     SetSize(sys_, 4_MiB);  // grows
1497     SetSize(vnd_, 2_MiB);  // shrinks
1498     // prd_b is unchanged
1499     ASSERT_TRUE(sm->BeginUpdate());
1500     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1501     ASSERT_EQ(4_MiB, GetSnapshotSize("sys_b").value_or(0));
1502 }
1503 
1504 // Test that even if there seem to be empty space in target metadata, COW partition won't take
1505 // it because they are used by old partitions.
TEST_F(SnapshotUpdateTest,CowPartitionDoNotTakeOldPartitions)1506 TEST_F(SnapshotUpdateTest, CowPartitionDoNotTakeOldPartitions) {
1507     SetSize(sys_, 2_MiB);  // shrinks
1508     // vnd_b and prd_b are unchanged.
1509     ASSERT_TRUE(sm->BeginUpdate());
1510     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1511 
1512     auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1513     ASSERT_NE(nullptr, tgt);
1514     auto metadata = tgt->Export();
1515     ASSERT_NE(nullptr, metadata);
1516     std::vector<std::string> written;
1517     // Write random data to all COW partitions in super
1518     for (auto p : metadata->partitions) {
1519         if (GetPartitionGroupName(metadata->groups[p.group_index]) != kCowGroupName) {
1520             continue;
1521         }
1522         std::string path;
1523         ASSERT_TRUE(CreateLogicalPartition(
1524                 CreateLogicalPartitionParams{
1525                         .block_device = fake_super,
1526                         .metadata = metadata.get(),
1527                         .partition = &p,
1528                         .timeout_ms = 1s,
1529                         .partition_opener = opener_.get(),
1530                 },
1531                 &path));
1532         ASSERT_TRUE(WriteRandomData(path));
1533         written.push_back(GetPartitionName(p));
1534     }
1535     ASSERT_FALSE(written.empty())
1536             << "No COW partitions are created even if there are empty space in super partition";
1537 
1538     // Make sure source partitions aren't affected.
1539     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1540         ASSERT_TRUE(IsPartitionUnchanged(name));
1541     }
1542 }
1543 
1544 // Test that it crashes after creating snapshot status file but before creating COW image, then
1545 // calling CreateUpdateSnapshots again works.
TEST_F(SnapshotUpdateTest,SnapshotStatusFileWithoutCow)1546 TEST_F(SnapshotUpdateTest, SnapshotStatusFileWithoutCow) {
1547     // Write some trash snapshot files to simulate leftovers from previous runs.
1548     {
1549         ASSERT_TRUE(AcquireLock());
1550         auto local_lock = std::move(lock_);
1551         SnapshotStatus status;
1552         status.set_name("sys_b");
1553         ASSERT_TRUE(sm->WriteSnapshotStatus(local_lock.get(), status));
1554         ASSERT_TRUE(image_manager_->CreateBackingImage("sys_b-cow-img", 1_MiB,
1555                                                        IImageManager::CREATE_IMAGE_DEFAULT));
1556     }
1557 
1558     // Redo the update.
1559     ASSERT_TRUE(sm->BeginUpdate());
1560     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1561 
1562     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1563 
1564     // Check that target partitions can be mapped.
1565     EXPECT_TRUE(MapUpdateSnapshots());
1566 }
1567 
1568 // Test that the old partitions are not modified.
TEST_F(SnapshotUpdateTest,TestRollback)1569 TEST_F(SnapshotUpdateTest, TestRollback) {
1570     // Execute the update.
1571     ASSERT_TRUE(sm->BeginUpdate());
1572     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1573 
1574     AddOperationForPartitions();
1575 
1576     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1577 
1578     // Write some data to target partitions.
1579     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1580         ASSERT_TRUE(WriteSnapshotAndHash(name));
1581     }
1582 
1583     // Assert that source partitions aren't affected.
1584     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1585         ASSERT_TRUE(IsPartitionUnchanged(name));
1586     }
1587 
1588     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1589 
1590     // Simulate shutting down the device.
1591     ASSERT_TRUE(UnmapAll());
1592 
1593     // After reboot, init does first stage mount.
1594     auto init = NewManagerForFirstStageMount("_b");
1595     ASSERT_NE(init, nullptr);
1596     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1597     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1598 
1599     // Check that the target partitions have the same content.
1600     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1601         ASSERT_TRUE(IsPartitionUnchanged(name));
1602     }
1603 
1604     // Simulate shutting down the device again.
1605     ASSERT_TRUE(UnmapAll());
1606     init = NewManagerForFirstStageMount("_a");
1607     ASSERT_NE(init, nullptr);
1608     ASSERT_FALSE(init->NeedSnapshotsInFirstStageMount());
1609     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1610 
1611     // Assert that the source partitions aren't affected.
1612     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1613         ASSERT_TRUE(IsPartitionUnchanged(name));
1614     }
1615 }
1616 
1617 // Test that if an update is applied but not booted into, it can be canceled.
TEST_F(SnapshotUpdateTest,CancelAfterApply)1618 TEST_F(SnapshotUpdateTest, CancelAfterApply) {
1619     ASSERT_TRUE(sm->BeginUpdate());
1620     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1621     ASSERT_TRUE(sm->CancelUpdate());
1622 }
1623 
ToIntervals(const std::vector<std::unique_ptr<Extent>> & extents)1624 static std::vector<Interval> ToIntervals(const std::vector<std::unique_ptr<Extent>>& extents) {
1625     std::vector<Interval> ret;
1626     std::transform(extents.begin(), extents.end(), std::back_inserter(ret),
1627                    [](const auto& extent) { return extent->AsLinearExtent()->AsInterval(); });
1628     return ret;
1629 }
1630 
1631 // Test that at the second update, old COW partition spaces are reclaimed.
TEST_F(SnapshotUpdateTest,ReclaimCow)1632 TEST_F(SnapshotUpdateTest, ReclaimCow) {
1633     // Make sure VABC cows are small enough that they fit in fake_super.
1634     sys_->set_estimate_cow_size(64_KiB);
1635     vnd_->set_estimate_cow_size(64_KiB);
1636     prd_->set_estimate_cow_size(64_KiB);
1637 
1638     // Execute the first update.
1639     ASSERT_TRUE(sm->BeginUpdate());
1640     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1641     ASSERT_TRUE(MapUpdateSnapshots());
1642     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1643 
1644     // Simulate shutting down the device.
1645     ASSERT_TRUE(UnmapAll());
1646 
1647     // After reboot, init does first stage mount.
1648     auto init = NewManagerForFirstStageMount("_b");
1649     ASSERT_NE(init, nullptr);
1650     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1651     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1652     init = nullptr;
1653 
1654     // Initiate the merge and wait for it to be completed.
1655     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1656     ASSERT_TRUE(new_sm->InitiateMerge());
1657     ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
1658 
1659     // Execute the second update.
1660     ASSERT_TRUE(new_sm->BeginUpdate());
1661     ASSERT_TRUE(new_sm->CreateUpdateSnapshots(manifest_));
1662 
1663     // Check that the old COW space is reclaimed and does not occupy space of mapped partitions.
1664     auto src = MetadataBuilder::New(*opener_, "super", 1);
1665     ASSERT_NE(src, nullptr);
1666     auto tgt = MetadataBuilder::New(*opener_, "super", 0);
1667     ASSERT_NE(tgt, nullptr);
1668     for (const auto& cow_part_name : {"sys_a-cow", "vnd_a-cow", "prd_a-cow"}) {
1669         auto* cow_part = tgt->FindPartition(cow_part_name);
1670         ASSERT_NE(nullptr, cow_part) << cow_part_name << " does not exist in target metadata";
1671         auto cow_intervals = ToIntervals(cow_part->extents());
1672         for (const auto& old_part_name : {"sys_b", "vnd_b", "prd_b"}) {
1673             auto* old_part = src->FindPartition(old_part_name);
1674             ASSERT_NE(nullptr, old_part) << old_part_name << " does not exist in source metadata";
1675             auto old_intervals = ToIntervals(old_part->extents());
1676 
1677             auto intersect = Interval::Intersect(cow_intervals, old_intervals);
1678             ASSERT_TRUE(intersect.empty()) << "COW uses space of source partitions";
1679         }
1680     }
1681 }
1682 
TEST_F(SnapshotUpdateTest,RetrofitAfterRegularAb)1683 TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) {
1684     constexpr auto kRetrofitGroupSize = kGroupSize / 2;
1685 
1686     // Initialize device-mapper / disk
1687     ASSERT_TRUE(UnmapAll());
1688     FormatFakeSuper();
1689 
1690     // Setup source partition metadata to have both _a and _b partitions.
1691     src_ = MetadataBuilder::New(*opener_, "super", 0);
1692     ASSERT_NE(nullptr, src_);
1693     for (const auto& suffix : {"_a"s, "_b"s}) {
1694         ASSERT_TRUE(src_->AddGroup(group_->name() + suffix, kRetrofitGroupSize));
1695         for (const auto& name : {"sys"s, "vnd"s, "prd"s}) {
1696             auto partition = src_->AddPartition(name + suffix, group_->name() + suffix, 0);
1697             ASSERT_NE(nullptr, partition);
1698             ASSERT_TRUE(src_->ResizePartition(partition, 2_MiB));
1699         }
1700     }
1701     auto metadata = src_->Export();
1702     ASSERT_NE(nullptr, metadata);
1703     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1704 
1705     // Flash source partitions
1706     std::string path;
1707     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1708         ASSERT_TRUE(CreateLogicalPartition(
1709                 CreateLogicalPartitionParams{
1710                         .block_device = fake_super,
1711                         .metadata_slot = 0,
1712                         .partition_name = name,
1713                         .timeout_ms = 1s,
1714                         .partition_opener = opener_.get(),
1715                 },
1716                 &path));
1717         ASSERT_TRUE(WriteRandomData(path));
1718         auto hash = GetHash(path);
1719         ASSERT_TRUE(hash.has_value());
1720         hashes_[name] = *hash;
1721     }
1722 
1723     // Setup manifest.
1724     group_->set_size(kRetrofitGroupSize);
1725     for (auto* partition : {sys_, vnd_, prd_}) {
1726         SetSize(partition, 2_MiB);
1727     }
1728     AddOperationForPartitions();
1729 
1730     ASSERT_TRUE(sm->BeginUpdate());
1731     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1732 
1733     // Test that COW image should not be created for retrofit devices; super
1734     // should be big enough.
1735     ASSERT_FALSE(image_manager_->BackingImageExists("sys_b-cow-img"));
1736     ASSERT_FALSE(image_manager_->BackingImageExists("vnd_b-cow-img"));
1737     ASSERT_FALSE(image_manager_->BackingImageExists("prd_b-cow-img"));
1738 
1739     // Write some data to target partitions.
1740     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1741         ASSERT_TRUE(WriteSnapshotAndHash(name));
1742     }
1743 
1744     // Assert that source partitions aren't affected.
1745     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1746         ASSERT_TRUE(IsPartitionUnchanged(name));
1747     }
1748 
1749     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1750 }
1751 
TEST_F(SnapshotUpdateTest,MergeCannotRemoveCow)1752 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
1753     // Make source partitions as big as possible to force COW image to be created.
1754     SetSize(sys_, 10_MiB);
1755     SetSize(vnd_, 10_MiB);
1756     SetSize(prd_, 10_MiB);
1757     sys_->set_estimate_cow_size(12_MiB);
1758     vnd_->set_estimate_cow_size(12_MiB);
1759     prd_->set_estimate_cow_size(12_MiB);
1760 
1761     src_ = MetadataBuilder::New(*opener_, "super", 0);
1762     ASSERT_NE(src_, nullptr);
1763     src_->RemoveGroupAndPartitions(group_->name() + "_a");
1764     src_->RemoveGroupAndPartitions(group_->name() + "_b");
1765     ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
1766     auto metadata = src_->Export();
1767     ASSERT_NE(nullptr, metadata);
1768     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1769 
1770     // Add operations for sys. The whole device is written.
1771     AddOperation(sys_);
1772 
1773     // Execute the update.
1774     ASSERT_TRUE(sm->BeginUpdate());
1775     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1776     ASSERT_TRUE(MapUpdateSnapshots());
1777     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1778 
1779     // Simulate shutting down the device.
1780     ASSERT_TRUE(UnmapAll());
1781 
1782     // After reboot, init does first stage mount.
1783     // Normally we should use NewManagerForFirstStageMount, but if so,
1784     // "gsid.mapped_image.sys_b-cow-img" won't be set.
1785     auto init = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1786     ASSERT_NE(init, nullptr);
1787     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1788 
1789     // Keep an open handle to the cow device. This should cause the merge to
1790     // be incomplete.
1791     auto cow_path = android::base::GetProperty("gsid.mapped_image.sys_b-cow-img", "");
1792     unique_fd fd(open(cow_path.c_str(), O_RDONLY | O_CLOEXEC));
1793     ASSERT_GE(fd, 0);
1794 
1795     // COW cannot be removed due to open fd, so expect a soft failure.
1796     ASSERT_TRUE(init->InitiateMerge());
1797     ASSERT_EQ(UpdateState::MergeNeedsReboot, init->ProcessUpdateState());
1798 
1799     // Simulate shutting down the device.
1800     fd.reset();
1801     ASSERT_TRUE(UnmapAll());
1802 
1803     // init does first stage mount again.
1804     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1805 
1806     // sys_b should be mapped as a dm-linear device directly.
1807     ASSERT_FALSE(sm->IsSnapshotDevice("sys_b", nullptr));
1808 
1809     // Merge should be able to complete now.
1810     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1811 }
1812 
1813 class MetadataMountedTest : public ::testing::Test {
1814   public:
1815     // This is so main() can instantiate this to invoke Cleanup.
TestBody()1816     virtual void TestBody() override {}
SetUp()1817     void SetUp() override {
1818         SKIP_IF_NON_VIRTUAL_AB();
1819         metadata_dir_ = test_device->GetMetadataDir();
1820         ASSERT_TRUE(ReadDefaultFstab(&fstab_));
1821     }
TearDown()1822     void TearDown() override {
1823         RETURN_IF_NON_VIRTUAL_AB();
1824         SetUp();
1825         // Remount /metadata
1826         test_device->set_recovery(false);
1827         EXPECT_TRUE(android::fs_mgr::EnsurePathMounted(&fstab_, metadata_dir_));
1828     }
IsMetadataMounted()1829     AssertionResult IsMetadataMounted() {
1830         Fstab mounted_fstab;
1831         if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
1832             ADD_FAILURE() << "Failed to scan mounted volumes";
1833             return AssertionFailure() << "Failed to scan mounted volumes";
1834         }
1835 
1836         auto entry = GetEntryForPath(&fstab_, metadata_dir_);
1837         if (entry == nullptr) {
1838             return AssertionFailure() << "No mount point found in fstab for path " << metadata_dir_;
1839         }
1840 
1841         auto mv = GetEntryForMountPoint(&mounted_fstab, entry->mount_point);
1842         if (mv == nullptr) {
1843             return AssertionFailure() << metadata_dir_ << " is not mounted";
1844         }
1845         return AssertionSuccess() << metadata_dir_ << " is mounted";
1846     }
1847     std::string metadata_dir_;
1848     Fstab fstab_;
1849 };
1850 
MountMetadata()1851 void MountMetadata() {
1852     MetadataMountedTest().TearDown();
1853 }
1854 
TEST_F(MetadataMountedTest,Android)1855 TEST_F(MetadataMountedTest, Android) {
1856     auto device = sm->EnsureMetadataMounted();
1857     EXPECT_NE(nullptr, device);
1858     device.reset();
1859 
1860     EXPECT_TRUE(IsMetadataMounted());
1861     EXPECT_TRUE(sm->CancelUpdate()) << "Metadata dir should never be unmounted in Android mode";
1862 }
1863 
TEST_F(MetadataMountedTest,Recovery)1864 TEST_F(MetadataMountedTest, Recovery) {
1865     test_device->set_recovery(true);
1866     metadata_dir_ = test_device->GetMetadataDir();
1867 
1868     EXPECT_TRUE(android::fs_mgr::EnsurePathUnmounted(&fstab_, metadata_dir_));
1869     EXPECT_FALSE(IsMetadataMounted());
1870 
1871     auto device = sm->EnsureMetadataMounted();
1872     EXPECT_NE(nullptr, device);
1873     EXPECT_TRUE(IsMetadataMounted());
1874 
1875     device.reset();
1876     EXPECT_FALSE(IsMetadataMounted());
1877 }
1878 
1879 // Test that during a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,MergeInRecovery)1880 TEST_F(SnapshotUpdateTest, MergeInRecovery) {
1881     // Execute the first update.
1882     ASSERT_TRUE(sm->BeginUpdate());
1883     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1884     ASSERT_TRUE(MapUpdateSnapshots());
1885     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1886 
1887     // Simulate shutting down the device.
1888     ASSERT_TRUE(UnmapAll());
1889 
1890     // After reboot, init does first stage mount.
1891     auto init = NewManagerForFirstStageMount("_b");
1892     ASSERT_NE(init, nullptr);
1893     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1894     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1895     init = nullptr;
1896 
1897     // Initiate the merge and then immediately stop it to simulate a reboot.
1898     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1899     ASSERT_TRUE(new_sm->InitiateMerge());
1900     ASSERT_TRUE(UnmapAll());
1901 
1902     // Simulate a reboot into recovery.
1903     auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1904     test_device->set_recovery(true);
1905     new_sm = NewManagerForFirstStageMount(test_device.release());
1906 
1907     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1908     ASSERT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1909 }
1910 
1911 // Test that a merge does not clear the snapshot state in fastboot.
TEST_F(SnapshotUpdateTest,MergeInFastboot)1912 TEST_F(SnapshotUpdateTest, MergeInFastboot) {
1913     // Execute the first update.
1914     ASSERT_TRUE(sm->BeginUpdate());
1915     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1916     ASSERT_TRUE(MapUpdateSnapshots());
1917     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1918 
1919     // Simulate shutting down the device.
1920     ASSERT_TRUE(UnmapAll());
1921 
1922     // After reboot, init does first stage mount.
1923     auto init = NewManagerForFirstStageMount("_b");
1924     ASSERT_NE(init, nullptr);
1925     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1926     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1927     init = nullptr;
1928 
1929     // Initiate the merge and then immediately stop it to simulate a reboot.
1930     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1931     ASSERT_TRUE(new_sm->InitiateMerge());
1932     ASSERT_TRUE(UnmapAll());
1933 
1934     // Simulate a reboot into recovery.
1935     auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1936     test_device->set_recovery(true);
1937     new_sm = NewManagerForFirstStageMount(test_device.release());
1938 
1939     ASSERT_TRUE(new_sm->FinishMergeInRecovery());
1940 
1941     ASSERT_TRUE(UnmapAll());
1942 
1943     auto mount = new_sm->EnsureMetadataMounted();
1944     ASSERT_TRUE(mount && mount->HasDevice());
1945     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1946 
1947     // Finish the merge in a normal boot.
1948     test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1949     init = NewManagerForFirstStageMount(test_device.release());
1950     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1951     init = nullptr;
1952 
1953     test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1954     new_sm = NewManagerForFirstStageMount(test_device.release());
1955     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1956     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::None);
1957 }
1958 
1959 // Test that after an OTA, before a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeRollbackInRecovery)1960 TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) {
1961     // Execute the first update.
1962     ASSERT_TRUE(sm->BeginUpdate());
1963     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1964     ASSERT_TRUE(MapUpdateSnapshots());
1965     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1966 
1967     // Simulate shutting down the device.
1968     ASSERT_TRUE(UnmapAll());
1969 
1970     // Simulate a reboot into recovery.
1971     auto test_device = new TestDeviceInfo(fake_super, "_b");
1972     test_device->set_recovery(true);
1973     auto new_sm = NewManagerForFirstStageMount(test_device);
1974 
1975     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1976     // Manually mount metadata so that we can call GetUpdateState() below.
1977     MountMetadata();
1978     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1979     EXPECT_TRUE(test_device->IsSlotUnbootable(1));
1980     EXPECT_FALSE(test_device->IsSlotUnbootable(0));
1981 }
1982 
1983 // Test that after an OTA and a bootloader rollback with no merge, we can wipe
1984 // data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeAfterRollback)1985 TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) {
1986     // Execute the first update.
1987     ASSERT_TRUE(sm->BeginUpdate());
1988     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1989     ASSERT_TRUE(MapUpdateSnapshots());
1990     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1991 
1992     // Simulate shutting down the device.
1993     ASSERT_TRUE(UnmapAll());
1994 
1995     // Simulate a rollback, with reboot into recovery.
1996     auto test_device = new TestDeviceInfo(fake_super, "_a");
1997     test_device->set_recovery(true);
1998     auto new_sm = NewManagerForFirstStageMount(test_device);
1999 
2000     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2001     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2002     EXPECT_FALSE(test_device->IsSlotUnbootable(0));
2003     EXPECT_FALSE(test_device->IsSlotUnbootable(1));
2004 }
2005 
2006 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeRequiredInPackage)2007 TEST_F(SnapshotUpdateTest, DataWipeRequiredInPackage) {
2008     AddOperationForPartitions();
2009     // Execute the update.
2010     ASSERT_TRUE(sm->BeginUpdate());
2011     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2012 
2013     // Write some data to target partitions.
2014     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2015         ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
2016     }
2017 
2018     ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2019 
2020     // Simulate shutting down the device.
2021     ASSERT_TRUE(UnmapAll());
2022 
2023     // Simulate a reboot into recovery.
2024     auto test_device = new TestDeviceInfo(fake_super, "_b");
2025     test_device->set_recovery(true);
2026     auto new_sm = NewManagerForFirstStageMount(test_device);
2027 
2028     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2029     // Manually mount metadata so that we can call GetUpdateState() below.
2030     MountMetadata();
2031     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2032     ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2033     ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2034 
2035     ASSERT_TRUE(UnmapAll());
2036 
2037     // Now reboot into new slot.
2038     test_device = new TestDeviceInfo(fake_super, "_b");
2039     auto init = NewManagerForFirstStageMount(test_device);
2040     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2041     // Verify that we are on the downgraded build.
2042     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2043         ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2044     }
2045 }
2046 
2047 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeWithStaleSnapshots)2048 TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
2049     AddOperationForPartitions();
2050 
2051     // Execute the update.
2052     ASSERT_TRUE(sm->BeginUpdate());
2053     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2054 
2055     // Write some data to target partitions.
2056     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2057         ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
2058     }
2059 
2060     // Create a stale snapshot that should not exist.
2061     {
2062         ASSERT_TRUE(AcquireLock());
2063 
2064         PartitionCowCreator cow_creator = {
2065                 .compression_enabled = ShouldUseCompression(),
2066                 .compression_algorithm = ShouldUseCompression() ? "gz" : "none",
2067         };
2068         SnapshotStatus status;
2069         status.set_name("sys_a");
2070         status.set_device_size(1_MiB);
2071         status.set_snapshot_size(2_MiB);
2072         status.set_cow_partition_size(2_MiB);
2073 
2074         ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
2075         lock_ = nullptr;
2076 
2077         ASSERT_TRUE(sm->EnsureImageManager());
2078         ASSERT_TRUE(sm->image_manager()->CreateBackingImage("sys_a", 1_MiB, 0));
2079     }
2080 
2081     ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2082 
2083     // Simulate shutting down the device.
2084     ASSERT_TRUE(UnmapAll());
2085 
2086     // Simulate a reboot into recovery.
2087     auto test_device = new TestDeviceInfo(fake_super, "_b");
2088     test_device->set_recovery(true);
2089     auto new_sm = NewManagerForFirstStageMount(test_device);
2090 
2091     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2092     // Manually mount metadata so that we can call GetUpdateState() below.
2093     MountMetadata();
2094     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2095     ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2096     ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2097 
2098     ASSERT_TRUE(UnmapAll());
2099 
2100     // Now reboot into new slot.
2101     test_device = new TestDeviceInfo(fake_super, "_b");
2102     auto init = NewManagerForFirstStageMount(test_device);
2103     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2104     // Verify that we are on the downgraded build.
2105     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2106         ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2107     }
2108 }
2109 
TEST_F(SnapshotUpdateTest,Hashtree)2110 TEST_F(SnapshotUpdateTest, Hashtree) {
2111     constexpr auto partition_size = 4_MiB;
2112     constexpr auto data_size = 3_MiB;
2113     constexpr auto hashtree_size = 512_KiB;
2114     constexpr auto fec_size = partition_size - data_size - hashtree_size;
2115 
2116     const auto block_size = manifest_.block_size();
2117     SetSize(sys_, partition_size);
2118     AddOperation(sys_, data_size);
2119 
2120     sys_->set_estimate_cow_size(partition_size + data_size);
2121 
2122     // Set hastree extents.
2123     sys_->mutable_hash_tree_data_extent()->set_start_block(0);
2124     sys_->mutable_hash_tree_data_extent()->set_num_blocks(data_size / block_size);
2125 
2126     sys_->mutable_hash_tree_extent()->set_start_block(data_size / block_size);
2127     sys_->mutable_hash_tree_extent()->set_num_blocks(hashtree_size / block_size);
2128 
2129     // Set FEC extents.
2130     sys_->mutable_fec_data_extent()->set_start_block(0);
2131     sys_->mutable_fec_data_extent()->set_num_blocks((data_size + hashtree_size) / block_size);
2132 
2133     sys_->mutable_fec_extent()->set_start_block((data_size + hashtree_size) / block_size);
2134     sys_->mutable_fec_extent()->set_num_blocks(fec_size / block_size);
2135 
2136     ASSERT_TRUE(sm->BeginUpdate());
2137     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2138 
2139     // Map and write some data to target partition.
2140     ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2141     ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
2142 
2143     // Finish update.
2144     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2145 
2146     // Simulate shutting down the device.
2147     ASSERT_TRUE(UnmapAll());
2148 
2149     // After reboot, init does first stage mount.
2150     auto init = NewManagerForFirstStageMount("_b");
2151     ASSERT_NE(init, nullptr);
2152     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2153     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2154 
2155     // Check that the target partition have the same content. Hashtree and FEC extents
2156     // should be accounted for.
2157     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2158 }
2159 
2160 // Test for overflow bit after update
TEST_F(SnapshotUpdateTest,Overflow)2161 TEST_F(SnapshotUpdateTest, Overflow) {
2162     if (ShouldUseCompression()) {
2163         GTEST_SKIP() << "No overflow bit set for userspace COWs";
2164     }
2165 
2166     const auto actual_write_size = GetSize(sys_);
2167     const auto declared_write_size = actual_write_size - 1_MiB;
2168 
2169     AddOperation(sys_, declared_write_size);
2170 
2171     // Execute the update.
2172     ASSERT_TRUE(sm->BeginUpdate());
2173     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2174 
2175     // Map and write some data to target partitions.
2176     ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2177     ASSERT_TRUE(WriteSnapshotAndHash("sys_b"));
2178 
2179     std::vector<android::dm::DeviceMapper::TargetInfo> table;
2180     ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
2181     ASSERT_EQ(1u, table.size());
2182     EXPECT_TRUE(table[0].IsOverflowSnapshot());
2183 
2184     ASSERT_FALSE(sm->FinishedSnapshotWrites(false))
2185             << "FinishedSnapshotWrites should detect overflow of CoW device.";
2186 }
2187 
TEST_F(SnapshotUpdateTest,LowSpace)2188 TEST_F(SnapshotUpdateTest, LowSpace) {
2189     static constexpr auto kMaxFree = 10_MiB;
2190     auto userdata = std::make_unique<LowSpaceUserdata>();
2191     ASSERT_TRUE(userdata->Init(kMaxFree));
2192 
2193     // Grow all partitions to 10_MiB, total 30_MiB. This requires 30 MiB of CoW space. After
2194     // using the empty space in super (< 1 MiB), it uses 30 MiB of /userdata space.
2195     constexpr uint64_t partition_size = 10_MiB;
2196     SetSize(sys_, partition_size);
2197     SetSize(vnd_, partition_size);
2198     SetSize(prd_, partition_size);
2199     sys_->set_estimate_cow_size(partition_size);
2200     vnd_->set_estimate_cow_size(partition_size);
2201     prd_->set_estimate_cow_size(partition_size);
2202 
2203     AddOperationForPartitions();
2204 
2205     // Execute the update.
2206     ASSERT_TRUE(sm->BeginUpdate());
2207     auto res = sm->CreateUpdateSnapshots(manifest_);
2208     ASSERT_FALSE(res);
2209     ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code());
2210     ASSERT_GE(res.required_size(), 14_MiB);
2211     ASSERT_LT(res.required_size(), 40_MiB);
2212 }
2213 
TEST_F(SnapshotUpdateTest,AddPartition)2214 TEST_F(SnapshotUpdateTest, AddPartition) {
2215     group_->add_partition_names("dlkm");
2216 
2217     auto dlkm = manifest_.add_partitions();
2218     dlkm->set_partition_name("dlkm");
2219     dlkm->set_estimate_cow_size(2_MiB);
2220     SetSize(dlkm, 3_MiB);
2221 
2222     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2223     // fit in super, but not |prd|.
2224     constexpr uint64_t partition_size = 3788_KiB;
2225     SetSize(sys_, partition_size);
2226     SetSize(vnd_, partition_size);
2227     SetSize(prd_, partition_size);
2228     SetSize(dlkm, partition_size);
2229 
2230     AddOperationForPartitions({sys_, vnd_, prd_, dlkm});
2231 
2232     // Execute the update.
2233     ASSERT_TRUE(sm->BeginUpdate());
2234     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2235 
2236     // Write some data to target partitions.
2237     for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
2238         ASSERT_TRUE(WriteSnapshotAndHash(name));
2239     }
2240 
2241     // Assert that source partitions aren't affected.
2242     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2243         ASSERT_TRUE(IsPartitionUnchanged(name));
2244     }
2245 
2246     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2247 
2248     // Simulate shutting down the device.
2249     ASSERT_TRUE(UnmapAll());
2250 
2251     // After reboot, init does first stage mount.
2252     auto init = NewManagerForFirstStageMount("_b");
2253     ASSERT_NE(init, nullptr);
2254 
2255     ASSERT_TRUE(init->EnsureSnapuserdConnected());
2256     init->set_use_first_stage_snapuserd(true);
2257 
2258     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2259     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2260 
2261     // Check that the target partitions have the same content.
2262     std::vector<std::string> partitions = {"sys_b", "vnd_b", "prd_b", "dlkm_b"};
2263     for (const auto& name : partitions) {
2264         ASSERT_TRUE(IsPartitionUnchanged(name));
2265     }
2266 
2267     ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2268     for (const auto& name : partitions) {
2269         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete(name + "-user-cow-init"));
2270     }
2271 
2272     // Initiate the merge and wait for it to be completed.
2273     ASSERT_TRUE(init->InitiateMerge());
2274     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2275 
2276     // Check that the target partitions have the same content after the merge.
2277     for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
2278         ASSERT_TRUE(IsPartitionUnchanged(name))
2279                 << "Content of " << name << " changes after the merge";
2280     }
2281 }
2282 
2283 class AutoKill final {
2284   public:
AutoKill(pid_t pid)2285     explicit AutoKill(pid_t pid) : pid_(pid) {}
~AutoKill()2286     ~AutoKill() {
2287         if (pid_ > 0) kill(pid_, SIGKILL);
2288     }
2289 
valid() const2290     bool valid() const { return pid_ > 0; }
2291 
2292   private:
2293     pid_t pid_;
2294 };
2295 
TEST_F(SnapshotUpdateTest,DaemonTransition)2296 TEST_F(SnapshotUpdateTest, DaemonTransition) {
2297     if (!ShouldUseCompression()) {
2298         GTEST_SKIP() << "Skipping Virtual A/B Compression test";
2299     }
2300 
2301     // Ensure a connection to the second-stage daemon, but use the first-stage
2302     // code paths thereafter.
2303     ASSERT_TRUE(sm->EnsureSnapuserdConnected());
2304     sm->set_use_first_stage_snapuserd(true);
2305 
2306     AddOperationForPartitions();
2307     // Execute the update.
2308     ASSERT_TRUE(sm->BeginUpdate());
2309     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2310     ASSERT_TRUE(MapUpdateSnapshots());
2311     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2312     ASSERT_TRUE(UnmapAll());
2313 
2314     auto init = NewManagerForFirstStageMount("_b");
2315     ASSERT_NE(init, nullptr);
2316 
2317     ASSERT_TRUE(init->EnsureSnapuserdConnected());
2318     init->set_use_first_stage_snapuserd(true);
2319 
2320     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2321     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2322 
2323     bool userspace_snapshots = init->UpdateUsesUserSnapshots();
2324 
2325     if (userspace_snapshots) {
2326         ASSERT_EQ(access("/dev/dm-user/sys_b-init", F_OK), 0);
2327         ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), -1);
2328     } else {
2329         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow-init", F_OK), 0);
2330         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), -1);
2331     }
2332 
2333     ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2334 
2335     // :TODO: this is a workaround to ensure the handler list stays empty. We
2336     // should make this test more like actual init, and spawn two copies of
2337     // snapuserd, given how many other tests we now have for normal snapuserd.
2338     if (userspace_snapshots) {
2339         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-init"));
2340         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-init"));
2341         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-init"));
2342 
2343         // The control device should have been renamed.
2344         ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-init", 10s));
2345         ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), 0);
2346     } else {
2347         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-user-cow-init"));
2348         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-user-cow-init"));
2349         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-user-cow-init"));
2350 
2351         // The control device should have been renamed.
2352         ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-user-cow-init", 10s));
2353         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), 0);
2354     }
2355 }
2356 
TEST_F(SnapshotUpdateTest,MapAllSnapshots)2357 TEST_F(SnapshotUpdateTest, MapAllSnapshots) {
2358     AddOperationForPartitions();
2359     // Execute the update.
2360     ASSERT_TRUE(sm->BeginUpdate());
2361     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2362     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2363         ASSERT_TRUE(WriteSnapshotAndHash(name));
2364     }
2365     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2366     ASSERT_TRUE(sm->MapAllSnapshots(10s));
2367 
2368     // Read bytes back and verify they match the cache.
2369     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2370 
2371     ASSERT_TRUE(sm->UnmapAllSnapshots());
2372 }
2373 
TEST_F(SnapshotUpdateTest,CancelOnTargetSlot)2374 TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
2375     AddOperationForPartitions();
2376 
2377     ASSERT_TRUE(UnmapAll());
2378 
2379     // Execute the update from B->A.
2380     test_device->set_slot_suffix("_b");
2381     ASSERT_TRUE(sm->BeginUpdate());
2382     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2383 
2384     std::string path;
2385     ASSERT_TRUE(CreateLogicalPartition(
2386             CreateLogicalPartitionParams{
2387                     .block_device = fake_super,
2388                     .metadata_slot = 0,
2389                     .partition_name = "sys_a",
2390                     .timeout_ms = 1s,
2391                     .partition_opener = opener_.get(),
2392             },
2393             &path));
2394 
2395     bool userspace_snapshots = sm->UpdateUsesUserSnapshots();
2396 
2397     unique_fd fd;
2398     if (!userspace_snapshots) {
2399         // Hold sys_a open so it can't be unmapped.
2400         fd.reset(open(path.c_str(), O_RDONLY));
2401     }
2402 
2403     // Switch back to "A", make sure we can cancel. Instead of unmapping sys_a
2404     // we should simply delete the old snapshots.
2405     test_device->set_slot_suffix("_a");
2406     ASSERT_TRUE(sm->BeginUpdate());
2407 }
2408 
TEST_F(SnapshotUpdateTest,QueryStatusError)2409 TEST_F(SnapshotUpdateTest, QueryStatusError) {
2410     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2411     // fit in super, but not |prd|.
2412     constexpr uint64_t partition_size = 3788_KiB;
2413     SetSize(sys_, partition_size);
2414     SetSize(vnd_, partition_size);
2415     SetSize(prd_, 18_MiB);
2416 
2417     // Make sure |prd| does not fit in super at all. On VABC, this means we
2418     // fake an extra large COW for |vnd| to fill up super.
2419     vnd_->set_estimate_cow_size(30_MiB);
2420     prd_->set_estimate_cow_size(30_MiB);
2421 
2422     AddOperationForPartitions();
2423 
2424     // Execute the update.
2425     ASSERT_TRUE(sm->BeginUpdate());
2426     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2427 
2428     if (sm->UpdateUsesUserSnapshots()) {
2429         GTEST_SKIP() << "Test does not apply to userspace snapshots";
2430     }
2431 
2432     // Test that partitions prioritize using space in super.
2433     auto tgt = MetadataBuilder::New(*opener_, "super", 1);
2434     ASSERT_NE(tgt, nullptr);
2435     ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
2436     ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
2437     ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
2438 
2439     // Write some data to target partitions.
2440     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2441         ASSERT_TRUE(WriteSnapshotAndHash(name));
2442     }
2443 
2444     // Assert that source partitions aren't affected.
2445     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2446         ASSERT_TRUE(IsPartitionUnchanged(name));
2447     }
2448 
2449     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2450 
2451     ASSERT_TRUE(UnmapAll());
2452 
2453     class DmStatusFailure final : public DeviceMapperWrapper {
2454       public:
2455         bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) override {
2456             if (!DeviceMapperWrapper::GetTableStatus(name, table)) {
2457                 return false;
2458             }
2459             if (name == "sys_b" && !table->empty()) {
2460                 auto& info = table->at(0);
2461                 if (DeviceMapper::GetTargetType(info.spec) == "snapshot-merge") {
2462                     info.data = "Merge failed";
2463                 }
2464             }
2465             return true;
2466         }
2467     };
2468     DmStatusFailure wrapper;
2469 
2470     // After reboot, init does first stage mount.
2471     auto info = new TestDeviceInfo(fake_super, "_b");
2472     info->set_dm(&wrapper);
2473 
2474     auto init = NewManagerForFirstStageMount(info);
2475     ASSERT_NE(init, nullptr);
2476 
2477     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2478     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2479 
2480     // Initiate the merge and wait for it to be completed.
2481     ASSERT_TRUE(init->InitiateMerge());
2482     ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
2483 
2484     // Simulate a reboot that tries the merge again, with the non-failing dm.
2485     ASSERT_TRUE(UnmapAll());
2486     init = NewManagerForFirstStageMount("_b");
2487     ASSERT_NE(init, nullptr);
2488     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2489     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2490 }
2491 
2492 class FlashAfterUpdateTest : public SnapshotUpdateTest,
2493                              public WithParamInterface<std::tuple<uint32_t, bool>> {
2494   public:
InitiateMerge(const std::string & slot_suffix)2495     AssertionResult InitiateMerge(const std::string& slot_suffix) {
2496         auto sm = SnapshotManager::New(new TestDeviceInfo(fake_super, slot_suffix));
2497         if (!sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)) {
2498             return AssertionFailure() << "Cannot CreateLogicalAndSnapshotPartitions";
2499         }
2500         if (!sm->InitiateMerge()) {
2501             return AssertionFailure() << "Cannot initiate merge";
2502         }
2503         return AssertionSuccess();
2504     }
2505 };
2506 
TEST_P(FlashAfterUpdateTest,FlashSlotAfterUpdate)2507 TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) {
2508     // Execute the update.
2509     ASSERT_TRUE(sm->BeginUpdate());
2510     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2511     ASSERT_TRUE(MapUpdateSnapshots());
2512     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2513 
2514     // Simulate shutting down the device.
2515     ASSERT_TRUE(UnmapAll());
2516 
2517     bool after_merge = std::get<1>(GetParam());
2518     if (after_merge) {
2519         ASSERT_TRUE(InitiateMerge("_b"));
2520         // Simulate shutting down the device after merge has initiated.
2521         ASSERT_TRUE(UnmapAll());
2522     }
2523 
2524     auto flashed_slot = std::get<0>(GetParam());
2525     auto flashed_slot_suffix = SlotSuffixForSlotNumber(flashed_slot);
2526 
2527     // Simulate flashing |flashed_slot|. This clears the UPDATED flag.
2528     auto flashed_builder = MetadataBuilder::New(*opener_, "super", flashed_slot);
2529     ASSERT_NE(flashed_builder, nullptr);
2530     flashed_builder->RemoveGroupAndPartitions(group_->name() + flashed_slot_suffix);
2531     flashed_builder->RemoveGroupAndPartitions(kCowGroupName);
2532     ASSERT_TRUE(FillFakeMetadata(flashed_builder.get(), manifest_, flashed_slot_suffix));
2533 
2534     // Deliberately remove a partition from this build so that
2535     // InitiateMerge do not switch state to "merging". This is possible in
2536     // practice because the list of dynamic partitions may change.
2537     ASSERT_NE(nullptr, flashed_builder->FindPartition("prd" + flashed_slot_suffix));
2538     flashed_builder->RemovePartition("prd" + flashed_slot_suffix);
2539 
2540     // Note that fastbootd always updates the partition table of both slots.
2541     auto flashed_metadata = flashed_builder->Export();
2542     ASSERT_NE(nullptr, flashed_metadata);
2543     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 0));
2544     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 1));
2545 
2546     std::string path;
2547     for (const auto& name : {"sys", "vnd"}) {
2548         ASSERT_TRUE(CreateLogicalPartition(
2549                 CreateLogicalPartitionParams{
2550                         .block_device = fake_super,
2551                         .metadata_slot = flashed_slot,
2552                         .partition_name = name + flashed_slot_suffix,
2553                         .timeout_ms = 1s,
2554                         .partition_opener = opener_.get(),
2555                 },
2556                 &path));
2557         ASSERT_TRUE(WriteRandomData(path));
2558         auto hash = GetHash(path);
2559         ASSERT_TRUE(hash.has_value());
2560         hashes_[name + flashed_slot_suffix] = *hash;
2561     }
2562 
2563     // Simulate shutting down the device after flash.
2564     ASSERT_TRUE(UnmapAll());
2565 
2566     // Simulate reboot. After reboot, init does first stage mount.
2567     auto init = NewManagerForFirstStageMount(flashed_slot_suffix);
2568     ASSERT_NE(init, nullptr);
2569 
2570     if (flashed_slot && after_merge) {
2571         ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2572     }
2573     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2574 
2575     // Check that the target partitions have the same content.
2576     for (const auto& name : {"sys", "vnd"}) {
2577         ASSERT_TRUE(IsPartitionUnchanged(name + flashed_slot_suffix));
2578     }
2579 
2580     // There should be no snapshot to merge.
2581     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
2582     if (flashed_slot == 0 && after_merge) {
2583         ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
2584     } else {
2585         // update_engine calls ProcessUpdateState first -- should see Cancelled.
2586         ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
2587     }
2588 
2589     // Next OTA calls CancelUpdate no matter what.
2590     ASSERT_TRUE(new_sm->CancelUpdate());
2591 }
2592 
2593 INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
__anon581dab5a0702(const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) 2594                          [](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
2595                              return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
2596                                     "Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
2597                                     "Merge"s;
2598                          });
2599 
2600 // Test behavior of ImageManager::Create on low space scenario. These tests assumes image manager
2601 // uses /data as backup device.
2602 class ImageManagerTest : public SnapshotTest, public WithParamInterface<uint64_t> {
2603   protected:
SetUp()2604     void SetUp() override {
2605         SKIP_IF_NON_VIRTUAL_AB();
2606         SnapshotTest::SetUp();
2607         userdata_ = std::make_unique<LowSpaceUserdata>();
2608         ASSERT_TRUE(userdata_->Init(GetParam()));
2609     }
TearDown()2610     void TearDown() override {
2611         RETURN_IF_NON_VIRTUAL_AB();
2612 
2613         EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
2614                     image_manager_->DeleteBackingImage(kImageName));
2615     }
2616     static constexpr const char* kImageName = "my_image";
2617     std::unique_ptr<LowSpaceUserdata> userdata_;
2618 };
2619 
TEST_P(ImageManagerTest,CreateImageNoSpace)2620 TEST_P(ImageManagerTest, CreateImageNoSpace) {
2621     uint64_t to_allocate = userdata_->free_space() + userdata_->bsize();
2622     auto res = image_manager_->CreateBackingImage(kImageName, to_allocate,
2623                                                   IImageManager::CREATE_IMAGE_DEFAULT);
2624     ASSERT_FALSE(res) << "Should not be able to create image with size = " << to_allocate
2625                       << " bytes because only " << userdata_->free_space() << " bytes are free";
2626     ASSERT_EQ(FiemapStatus::ErrorCode::NO_SPACE, res.error_code()) << res.string();
2627 }
2628 
ImageManagerTestParams()2629 std::vector<uint64_t> ImageManagerTestParams() {
2630     std::vector<uint64_t> ret;
2631     for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
2632         ret.push_back(size);
2633     }
2634     return ret;
2635 }
2636 
2637 INSTANTIATE_TEST_SUITE_P(ImageManagerTest, ImageManagerTest, ValuesIn(ImageManagerTestParams()));
2638 
Mkdir(const std::string & path)2639 bool Mkdir(const std::string& path) {
2640     if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
2641         std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
2642         return false;
2643     }
2644     return true;
2645 }
2646 
2647 class SnapshotTestEnvironment : public ::testing::Environment {
2648   public:
~SnapshotTestEnvironment()2649     ~SnapshotTestEnvironment() override {}
2650     void SetUp() override;
2651     void TearDown() override;
2652 
2653   private:
2654     bool CreateFakeSuper();
2655 
2656     std::unique_ptr<IImageManager> super_images_;
2657 };
2658 
CreateFakeSuper()2659 bool SnapshotTestEnvironment::CreateFakeSuper() {
2660     // Create and map the fake super partition.
2661     static constexpr int kImageFlags =
2662             IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
2663     if (!super_images_->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
2664         LOG(ERROR) << "Could not create fake super partition";
2665         return false;
2666     }
2667     if (!super_images_->MapImageDevice("fake-super", 10s, &fake_super)) {
2668         LOG(ERROR) << "Could not map fake super partition";
2669         return false;
2670     }
2671     test_device->set_fake_super(fake_super);
2672     return true;
2673 }
2674 
SetUp()2675 void SnapshotTestEnvironment::SetUp() {
2676     // b/163082876: GTEST_SKIP in Environment will make atest report incorrect results. Until
2677     // that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
2678     // suites.
2679     RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
2680 
2681     std::vector<std::string> paths = {
2682             // clang-format off
2683             "/data/gsi/ota/test",
2684             "/data/gsi/ota/test/super",
2685             "/metadata/gsi/ota/test",
2686             "/metadata/gsi/ota/test/super",
2687             "/metadata/ota/test",
2688             "/metadata/ota/test/snapshots",
2689             // clang-format on
2690     };
2691     for (const auto& path : paths) {
2692         ASSERT_TRUE(Mkdir(path));
2693     }
2694 
2695     // Create this once, otherwise, gsid will start/stop between each test.
2696     test_device = new TestDeviceInfo();
2697     sm = SnapshotManager::New(test_device);
2698     ASSERT_NE(nullptr, sm) << "Could not create snapshot manager";
2699 
2700     // Use a separate image manager for our fake super partition.
2701     super_images_ = IImageManager::Open("ota/test/super", 10s);
2702     ASSERT_NE(nullptr, super_images_) << "Could not create image manager";
2703 
2704     // Map the old image if one exists so we can safely unmap everything that
2705     // depends on it.
2706     bool recreate_fake_super;
2707     if (super_images_->BackingImageExists("fake-super")) {
2708         if (super_images_->IsImageMapped("fake-super")) {
2709             ASSERT_TRUE(super_images_->GetMappedImageDevice("fake-super", &fake_super));
2710         } else {
2711             ASSERT_TRUE(super_images_->MapImageDevice("fake-super", 10s, &fake_super));
2712         }
2713         test_device->set_fake_super(fake_super);
2714         recreate_fake_super = true;
2715     } else {
2716         ASSERT_TRUE(CreateFakeSuper());
2717         recreate_fake_super = false;
2718     }
2719 
2720     // Clean up previous run.
2721     MetadataMountedTest().TearDown();
2722     SnapshotUpdateTest().Cleanup();
2723     SnapshotTest().Cleanup();
2724 
2725     if (recreate_fake_super) {
2726         // Clean up any old copy.
2727         DeleteBackingImage(super_images_.get(), "fake-super");
2728         ASSERT_TRUE(CreateFakeSuper());
2729     }
2730 }
2731 
TearDown()2732 void SnapshotTestEnvironment::TearDown() {
2733     RETURN_IF_NON_VIRTUAL_AB();
2734     if (super_images_ != nullptr) {
2735         DeleteBackingImage(super_images_.get(), "fake-super");
2736     }
2737 }
2738 
IsDaemonRequired()2739 bool IsDaemonRequired() {
2740     if (FLAGS_force_config == "dmsnap") {
2741         return false;
2742     }
2743 
2744     if (!IsCompressionEnabled()) {
2745         return false;
2746     }
2747 
2748     const std::string UNKNOWN = "unknown";
2749     const std::string vendor_release =
2750             android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
2751 
2752     // No userspace snapshots if vendor partition is on Android 12
2753     // However, for GRF devices, snapuserd daemon will be on
2754     // vendor ramdisk in Android 12.
2755     if (vendor_release.find("12") != std::string::npos) {
2756         return true;
2757     }
2758 
2759     if (!FLAGS_force_config.empty()) {
2760         return true;
2761     }
2762 
2763     return IsUserspaceSnapshotsEnabled();
2764 }
2765 
ShouldUseCompression()2766 bool ShouldUseCompression() {
2767     if (FLAGS_force_config == "vab" || FLAGS_force_config == "dmsnap") {
2768         return false;
2769     }
2770     if (FLAGS_force_config == "vabc") {
2771         return true;
2772     }
2773     return IsCompressionEnabled();
2774 }
2775 
2776 }  // namespace snapshot
2777 }  // namespace android
2778 
main(int argc,char ** argv)2779 int main(int argc, char** argv) {
2780     ::testing::InitGoogleTest(&argc, argv);
2781     ::testing::AddGlobalTestEnvironment(new ::android::snapshot::SnapshotTestEnvironment());
2782     gflags::ParseCommandLineFlags(&argc, &argv, false);
2783 
2784     android::base::SetProperty("ctl.stop", "snapuserd");
2785 
2786     std::unordered_set<std::string> configs = {"", "dmsnap", "vab", "vabc"};
2787     if (configs.count(FLAGS_force_config) == 0) {
2788         std::cerr << "Unexpected force_config argument\n";
2789         return 1;
2790     }
2791 
2792     if (FLAGS_force_config == "dmsnap") {
2793         if (!android::base::SetProperty("snapuserd.test.dm.snapshots", "1")) {
2794             return testing::AssertionFailure()
2795                    << "Failed to disable property: virtual_ab.userspace.snapshots.enabled";
2796         }
2797     }
2798 
2799     if (FLAGS_force_iouring_disable == "iouring_disabled") {
2800         if (!android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1")) {
2801             return testing::AssertionFailure()
2802                    << "Failed to disable property: snapuserd.test.io_uring.disabled";
2803         }
2804     }
2805 
2806     int ret = RUN_ALL_TESTS();
2807 
2808     if (FLAGS_force_config == "dmsnap") {
2809         android::base::SetProperty("snapuserd.test.dm.snapshots", "0");
2810     }
2811 
2812     if (FLAGS_force_iouring_disable == "iouring_disabled") {
2813         android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
2814     }
2815 
2816     return ret;
2817 }
2818