libsnapshot_fuzzer: construct valid super partition metadata.

This should hopefully achieve more coverage.

Test: pass
Bug: 154633114
Change-Id: Ice575f2d8c3e22b80465c133d055e7c4368ebdfa
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
index 7e8559b..77b2245 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
@@ -77,7 +77,15 @@
 message SnapshotFuzzData {
     FuzzDeviceInfoData device_info_data = 1;
     FuzzSnapshotManagerData manager_data = 2;
+
+    // If true:
+    // - if super_data is empty, create empty super partition metadata.
+    // - otherwise, create super partition metadata accordingly.
+    // If false, no valid super partition metadata (it is zeroed)
+    bool is_super_metadata_valid = 3;
+    chromeos_update_engine.DeltaArchiveManifest super_data = 4;
+
     // More data used to prep the test before running actions.
-    reserved 3 to 9999;
+    reserved 5 to 9999;
     repeated SnapshotManagerActionProto actions = 10000;
 }
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
index dfac3ef..8101d03 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
@@ -47,6 +47,9 @@
 using android::dm::LoopControl;
 using android::fiemap::IImageManager;
 using android::fiemap::ImageManager;
+using android::fs_mgr::BlockDeviceInfo;
+using android::fs_mgr::IPartitionOpener;
+using chromeos_update_engine::DynamicPartitionMetadata;
 
 // This directory is exempted from pinning in ImageManager.
 static const char MNT_DIR[] = "/data/gsi/ota/test/";
@@ -252,6 +255,7 @@
 std::unique_ptr<ISnapshotManager> SnapshotFuzzEnv::CheckCreateSnapshotManager(
         const SnapshotFuzzData& data) {
     auto partition_opener = std::make_unique<TestPartitionOpener>(super());
+    CheckWriteSuperMetadata(data, *partition_opener);
     auto metadata_dir = fake_root_->tmp_path() + "/snapshot_metadata";
     PCHECK(Mkdir(metadata_dir));
 
@@ -268,4 +272,43 @@
     return fake_super_;
 }
 
+void SnapshotFuzzEnv::CheckWriteSuperMetadata(const SnapshotFuzzData& data,
+                                              const IPartitionOpener& opener) {
+    if (!data.is_super_metadata_valid()) {
+        // Leave it zero.
+        return;
+    }
+
+    BlockDeviceInfo super_device("super", SUPER_IMAGE_SIZE, 0, 0, 4096);
+    std::vector<BlockDeviceInfo> devices = {super_device};
+    auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
+    CHECK(builder != nullptr);
+
+    // Attempt to create a super partition metadata using proto. All errors are ignored.
+    for (const auto& group_proto : data.super_data().dynamic_partition_metadata().groups()) {
+        (void)builder->AddGroup(group_proto.name(), group_proto.size());
+        for (const auto& partition_name : group_proto.partition_names()) {
+            (void)builder->AddPartition(partition_name, group_proto.name(),
+                                        LP_PARTITION_ATTR_READONLY);
+        }
+    }
+
+    for (const auto& partition_proto : data.super_data().partitions()) {
+        auto p = builder->FindPartition(partition_proto.partition_name());
+        if (p == nullptr) continue;
+        (void)builder->ResizePartition(p, partition_proto.new_partition_info().size());
+    }
+
+    auto metadata = builder->Export();
+    // metadata may be nullptr if it is not valid (e.g. partition name too long).
+    // In this case, just use empty super partition data.
+    if (metadata == nullptr) {
+        builder = MetadataBuilder::New(devices, "super", 65536, 2);
+        CHECK(builder != nullptr);
+        metadata = builder->Export();
+        CHECK(metadata != nullptr);
+    }
+    CHECK(FlashPartitionTable(opener, super(), *metadata.get()));
+}
+
 }  // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
index 66a6181..5533def 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
@@ -16,8 +16,10 @@
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android/snapshot/snapshot_fuzz.pb.h>
 #include <libdm/loop_control.h>
 #include <libfiemap/image_manager.h>
+#include <liblp/liblp.h>
 #include <libsnapshot/auto_device.h>
 #include <libsnapshot/test_helpers.h>
 
@@ -68,6 +70,9 @@
     static std::unique_ptr<AutoDevice> CheckMapSuper(const std::string& fake_persist_path,
                                                      android::dm::LoopControl* control,
                                                      std::string* fake_super);
+
+    void CheckWriteSuperMetadata(const SnapshotFuzzData& proto,
+                                 const android::fs_mgr::IPartitionOpener& opener);
 };
 
 class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {