Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ac8fb1c authored by David Anderson's avatar David Anderson Committed by Automerger Merge Worker
Browse files

Merge changes Iedc94613,I58621281 am: 811eed3b

parents c55c68fe 811eed3b
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <unordered_set>

#include <android-base/file.h>
@@ -165,27 +166,25 @@ class DeviceMapperWrapper : public android::dm::IDeviceMapper {
    android::dm::IDeviceMapper& impl_;
};

class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
class SnapshotTestPropertyFetcher : public android::fs_mgr::IPropertyFetcher {
  public:
    SnapshotTestPropertyFetcher(const std::string& slot_suffix) {
        using testing::Return;
        ON_CALL(*this, GetProperty("ro.boot.slot_suffix", _)).WillByDefault(Return(slot_suffix));
        ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions", _))
                .WillByDefault(Return(true));
        ON_CALL(*this, GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
                .WillByDefault(Return(false));
        ON_CALL(*this, GetBoolProperty("ro.virtual_ab.enabled", _)).WillByDefault(Return(true));
    }
    explicit SnapshotTestPropertyFetcher(const std::string& slot_suffix,
                                         std::unordered_map<std::string, std::string>&& props = {});

    static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); }
    std::string GetProperty(const std::string& key, const std::string& defaultValue) override;
    bool GetBoolProperty(const std::string& key, bool defaultValue) override;

    static void SetUp(const std::string& slot_suffix = "_a") { Reset(slot_suffix); }
    static void TearDown() { Reset("_a"); }

  private:
    static void Reset(const std::string& slot_suffix) {
        IPropertyFetcher::OverrideForTesting(
                std::make_unique<NiceMock<SnapshotTestPropertyFetcher>>(slot_suffix));
                std::make_unique<SnapshotTestPropertyFetcher>(slot_suffix));
    }

  private:
    std::unordered_map<std::string, std::string> properties_;
};

// Helper for error-spam-free cleanup.
+80 −47
Original line number Diff line number Diff line
@@ -53,9 +53,11 @@
#include <libsnapshot/mock_device_info.h>
#include <libsnapshot/mock_snapshot.h>

DEFINE_string(force_config, "", "Force testing mode (dmsnap, vab, vabc) ignoring device config.");
DEFINE_string(force_mode, "",
              "Force testing older modes (vab-legacy, vabc-legacy) ignoring device config.");
DEFINE_string(force_iouring_disable, "",
              "Force testing mode (iouring_disabled) - disable io_uring");
DEFINE_string(compression_method, "gz", "Default compression algorithm.");

namespace android {
namespace snapshot {
@@ -90,7 +92,6 @@ using namespace std::string_literals;
std::unique_ptr<SnapshotManager> sm;
TestDeviceInfo* test_device = nullptr;
std::string fake_super;
bool gIsSnapuserdRequired;

void MountMetadata();

@@ -108,7 +109,7 @@ class SnapshotTest : public ::testing::Test {
    void SetUp() override {
        SKIP_IF_NON_VIRTUAL_AB();

        SnapshotTestPropertyFetcher::SetUp();
        SetupProperties();
        InitializeState();
        CleanupTestArtifacts();
        FormatFakeSuper();
@@ -116,6 +117,38 @@ class SnapshotTest : public ::testing::Test {
        ASSERT_TRUE(sm->BeginUpdate());
    }

    void SetupProperties() {
        std::unordered_map<std::string, std::string> properties;

        ASSERT_TRUE(android::base::SetProperty("snapuserd.test.dm.snapshots", "0"))
                << "Failed to disable property: virtual_ab.userspace.snapshots.enabled";
        ASSERT_TRUE(android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0"))
                << "Failed to set property: snapuserd.test.io_uring.disabled";

        if (FLAGS_force_mode == "vabc-legacy") {
            ASSERT_TRUE(android::base::SetProperty("snapuserd.test.dm.snapshots", "1"))
                    << "Failed to disable property: virtual_ab.userspace.snapshots.enabled";
            properties["ro.virtual_ab.compression.enabled"] = "true";
            properties["ro.virtual_ab.userspace.snapshots.enabled"] = "false";
        } else if (FLAGS_force_mode == "vab-legacy") {
            properties["ro.virtual_ab.compression.enabled"] = "false";
            properties["ro.virtual_ab.userspace.snapshots.enabled"] = "false";
        }

        if (FLAGS_force_iouring_disable == "iouring_disabled") {
            ASSERT_TRUE(android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1"))
                    << "Failed to set property: snapuserd.test.io_uring.disabled";
            properties["ro.virtual_ab.io_uring.enabled"] = "false";
        }

        auto fetcher = std::make_unique<SnapshotTestPropertyFetcher>("_a", std::move(properties));
        IPropertyFetcher::OverrideForTesting(std::move(fetcher));

        if (GetLegacyCompressionEnabledProperty() || CanUseUserspaceSnapshots()) {
            snapuserd_required_ = true;
        }
    }

    void TearDown() override {
        RETURN_IF_NON_VIRTUAL_AB();

@@ -358,8 +391,11 @@ class SnapshotTest : public ::testing::Test {
        DeltaArchiveManifest manifest;

        auto dynamic_partition_metadata = manifest.mutable_dynamic_partition_metadata();
        dynamic_partition_metadata->set_vabc_enabled(gIsSnapuserdRequired);
        dynamic_partition_metadata->set_vabc_enabled(snapuserd_required_);
        dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
        if (snapuserd_required_) {
            dynamic_partition_metadata->set_vabc_compression_param(FLAGS_compression_method);
        }

        auto group = dynamic_partition_metadata->add_groups();
        group->set_name("group");
@@ -397,7 +433,7 @@ class SnapshotTest : public ::testing::Test {
            if (!res) {
                return res;
            }
        } else if (!gIsSnapuserdRequired) {
        } else if (!snapuserd_required_) {
            std::string ignore;
            if (!MapUpdateSnapshot("test_partition_b", &ignore)) {
                return AssertionFailure() << "Failed to map test_partition_b";
@@ -450,15 +486,16 @@ class SnapshotTest : public ::testing::Test {
    std::unique_ptr<SnapshotManager::LockedFile> lock_;
    android::fiemap::IImageManager* image_manager_ = nullptr;
    std::string fake_super_;
    bool snapuserd_required_ = false;
};

TEST_F(SnapshotTest, CreateSnapshot) {
    ASSERT_TRUE(AcquireLock());

    PartitionCowCreator cow_creator;
    cow_creator.using_snapuserd = gIsSnapuserdRequired;
    cow_creator.using_snapuserd = snapuserd_required_;
    if (cow_creator.using_snapuserd) {
        cow_creator.compression_algorithm = "gz";
        cow_creator.compression_algorithm = FLAGS_compression_method;
    } else {
        cow_creator.compression_algorithm = "none";
    }
@@ -497,7 +534,7 @@ TEST_F(SnapshotTest, MapSnapshot) {
    ASSERT_TRUE(AcquireLock());

    PartitionCowCreator cow_creator;
    cow_creator.using_snapuserd = gIsSnapuserdRequired;
    cow_creator.using_snapuserd = snapuserd_required_;

    static const uint64_t kDeviceSize = 1024 * 1024;
    SnapshotStatus status;
@@ -624,10 +661,10 @@ TEST_F(SnapshotTest, FirstStageMountAndMerge) {
    SnapshotStatus status;
    ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
    ASSERT_EQ(status.state(), SnapshotState::CREATED);
    if (gIsSnapuserdRequired) {
        ASSERT_EQ(status.compression_algorithm(), "gz");
    if (snapuserd_required_) {
        ASSERT_EQ(status.compression_algorithm(), FLAGS_compression_method);
    } else {
        ASSERT_EQ(status.compression_algorithm(), "none");
        ASSERT_EQ(status.compression_algorithm(), "");
    }

    DeviceMapper::TargetInfo target;
@@ -898,8 +935,11 @@ class SnapshotUpdateTest : public SnapshotTest {
        opener_ = std::make_unique<TestPartitionOpener>(fake_super);

        auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
        dynamic_partition_metadata->set_vabc_enabled(gIsSnapuserdRequired);
        dynamic_partition_metadata->set_vabc_enabled(snapuserd_required_);
        dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
        if (snapuserd_required_) {
            dynamic_partition_metadata->set_vabc_compression_param(FLAGS_compression_method);
        }

        // Create a fake update package metadata.
        // Not using full name "system", "vendor", "product" because these names collide with the
@@ -1031,7 +1071,7 @@ class SnapshotUpdateTest : public SnapshotTest {
    }

    AssertionResult MapOneUpdateSnapshot(const std::string& name) {
        if (gIsSnapuserdRequired) {
        if (snapuserd_required_) {
            std::unique_ptr<ISnapshotWriter> writer;
            return MapUpdateSnapshot(name, &writer);
        } else {
@@ -1052,7 +1092,7 @@ class SnapshotUpdateTest : public SnapshotTest {

    AssertionResult WriteSnapshotAndHash(PartitionUpdate* partition) {
        std::string name = partition->partition_name() + "_b";
        if (gIsSnapuserdRequired) {
        if (snapuserd_required_) {
            std::unique_ptr<ISnapshotWriter> writer;
            auto res = MapUpdateSnapshot(name, &writer);
            if (!res) {
@@ -1254,7 +1294,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) {

    // Initiate the merge and wait for it to be completed.
    ASSERT_TRUE(init->InitiateMerge());
    ASSERT_EQ(init->IsSnapuserdRequired(), gIsSnapuserdRequired);
    ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
    {
        // We should have started in SECOND_PHASE since nothing shrinks.
        ASSERT_TRUE(AcquireLock());
@@ -1281,7 +1321,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
}

TEST_F(SnapshotUpdateTest, DuplicateOps) {
    if (!gIsSnapuserdRequired) {
    if (!snapuserd_required_) {
        GTEST_SKIP() << "snapuserd-only test";
    }

@@ -1323,7 +1363,7 @@ TEST_F(SnapshotUpdateTest, DuplicateOps) {
// Test that shrinking and growing partitions at the same time is handled
// correctly in VABC.
TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {
    if (!gIsSnapuserdRequired) {
    if (!snapuserd_required_) {
        // b/179111359
        GTEST_SKIP() << "Skipping snapuserd test";
    }
@@ -1386,7 +1426,7 @@ TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {

    // Initiate the merge and wait for it to be completed.
    ASSERT_TRUE(init->InitiateMerge());
    ASSERT_EQ(init->IsSnapuserdRequired(), gIsSnapuserdRequired);
    ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
    {
        // Check that the merge phase is FIRST_PHASE until at least one call
        // to ProcessUpdateState() occurs.
@@ -1440,7 +1480,7 @@ TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {

// Test that a transient merge consistency check failure can resume properly.
TEST_F(SnapshotUpdateTest, ConsistencyCheckResume) {
    if (!gIsSnapuserdRequired) {
    if (!snapuserd_required_) {
        // b/179111359
        GTEST_SKIP() << "Skipping snapuserd test";
    }
@@ -1494,7 +1534,7 @@ TEST_F(SnapshotUpdateTest, ConsistencyCheckResume) {

    // Initiate the merge and wait for it to be completed.
    ASSERT_TRUE(init->InitiateMerge());
    ASSERT_EQ(init->IsSnapuserdRequired(), gIsSnapuserdRequired);
    ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
    {
        // Check that the merge phase is FIRST_PHASE until at least one call
        // to ProcessUpdateState() occurs.
@@ -2098,8 +2138,8 @@ TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
        ASSERT_TRUE(AcquireLock());

        PartitionCowCreator cow_creator = {
                .using_snapuserd = gIsSnapuserdRequired,
                .compression_algorithm = gIsSnapuserdRequired ? "gz" : "",
                .using_snapuserd = snapuserd_required_,
                .compression_algorithm = snapuserd_required_ ? FLAGS_compression_method : "",
        };
        SnapshotStatus status;
        status.set_name("sys_a");
@@ -2195,7 +2235,7 @@ TEST_F(SnapshotUpdateTest, Hashtree) {

// Test for overflow bit after update
TEST_F(SnapshotUpdateTest, Overflow) {
    if (gIsSnapuserdRequired) {
    if (snapuserd_required_) {
        GTEST_SKIP() << "No overflow bit set for snapuserd COWs";
    }

@@ -2330,7 +2370,7 @@ class AutoKill final {
};

TEST_F(SnapshotUpdateTest, DaemonTransition) {
    if (!gIsSnapuserdRequired) {
    if (!snapuserd_required_) {
        GTEST_SKIP() << "Skipping snapuserd test";
    }

@@ -2761,21 +2801,17 @@ void SnapshotTestEnvironment::TearDown() {
    }
}

void SetGlobalConfigOptions() {
    if (FLAGS_force_config == "dmsnap") {
        ASSERT_TRUE(android::base::SetProperty("snapuserd.test.dm.snapshots", "1"))
                << "Failed to disable property: virtual_ab.userspace.snapshots.enabled";
    }

    if (FLAGS_force_iouring_disable == "iouring_disabled") {
        ASSERT_TRUE(android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1"))
                << "Failed to disable property: snapuserd.test.io_uring.disabled";
void KillSnapuserd() {
    auto status = android::base::GetProperty("init.svc.snapuserd", "stopped");
    if (status == "stopped") {
        return;
    }

    if (FLAGS_force_config != "dmsnap" &&
        (GetLegacyCompressionEnabledProperty() || CanUseUserspaceSnapshots())) {
        gIsSnapuserdRequired = true;
    auto snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s);
    if (!snapuserd_client) {
        return;
    }
    snapuserd_client->DetachSnapuserd();
    snapuserd_client->CloseConnection();
}

}  // namespace snapshot
@@ -2788,23 +2824,20 @@ int main(int argc, char** argv) {

    android::base::SetProperty("ctl.stop", "snapuserd");

    std::unordered_set<std::string> configs = {"", "dmsnap", "vab", "vabc"};
    if (configs.count(FLAGS_force_config) == 0) {
    std::unordered_set<std::string> modes = {"", "vab-legacy", "vabc-legacy"};
    if (modes.count(FLAGS_force_mode) == 0) {
        std::cerr << "Unexpected force_config argument\n";
        return 1;
    }

    android::snapshot::SetGlobalConfigOptions();
    // This is necessary if the configuration we're testing doesn't match the device.
    android::snapshot::KillSnapuserd();

    int ret = RUN_ALL_TESTS();

    if (FLAGS_force_config == "dmsnap") {
    android::base::SetProperty("snapuserd.test.dm.snapshots", "0");
    }

    if (FLAGS_force_iouring_disable == "iouring_disabled") {
    android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
    }

    android::snapshot::KillSnapuserd();
    return ret;
}
+35 −0
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parsebool.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <liblp/property_fetcher.h>
#include <openssl/sha.h>
#include <payload_consumer/file_descriptor.h>

@@ -278,5 +280,38 @@ bool IsVirtualAbEnabled() {
    return android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
}

SnapshotTestPropertyFetcher::SnapshotTestPropertyFetcher(
        const std::string& slot_suffix, std::unordered_map<std::string, std::string>&& props)
    : properties_(std::move(props)) {
    properties_["ro.boot.slot_suffix"] = slot_suffix;
    properties_["ro.boot.dynamic_partitions"] = "true";
    properties_["ro.boot.dynamic_partitions_retrofit"] = "false";
    properties_["ro.virtual_ab.enabled"] = "true";
}

std::string SnapshotTestPropertyFetcher::GetProperty(const std::string& key,
                                                     const std::string& defaultValue) {
    auto iter = properties_.find(key);
    if (iter == properties_.end()) {
        return android::base::GetProperty(key, defaultValue);
    }
    return iter->second;
}

bool SnapshotTestPropertyFetcher::GetBoolProperty(const std::string& key, bool defaultValue) {
    auto iter = properties_.find(key);
    if (iter == properties_.end()) {
        return android::base::GetBoolProperty(key, defaultValue);
    }
    switch (android::base::ParseBool(iter->second)) {
        case android::base::ParseBoolResult::kTrue:
            return true;
        case android::base::ParseBoolResult::kFalse:
            return false;
        default:
            return defaultValue;
    }
}

}  // namespace snapshot
}  // namespace android
+15 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <fs_mgr/roots.h>
#include <liblp/property_fetcher.h>

using android::dm::kSectorSize;
using android::fiemap::FiemapStatus;
@@ -33,6 +34,7 @@ using android::fs_mgr::EnsurePathMounted;
using android::fs_mgr::EnsurePathUnmounted;
using android::fs_mgr::Fstab;
using android::fs_mgr::GetEntryForPath;
using android::fs_mgr::IPropertyFetcher;
using android::fs_mgr::MetadataBuilder;
using android::fs_mgr::Partition;
using android::fs_mgr::ReadDefaultFstab;
@@ -185,11 +187,13 @@ void AppendExtent(RepeatedPtrField<chromeos_update_engine::Extent>* extents, uin
}

bool GetLegacyCompressionEnabledProperty() {
    return android::base::GetBoolProperty("ro.virtual_ab.compression.enabled", false);
    auto fetcher = IPropertyFetcher::GetInstance();
    return fetcher->GetBoolProperty("ro.virtual_ab.compression.enabled", false);
}

bool GetUserspaceSnapshotsEnabledProperty() {
    return android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
    auto fetcher = IPropertyFetcher::GetInstance();
    return fetcher->GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
}

bool CanUseUserspaceSnapshots() {
@@ -197,9 +201,11 @@ bool CanUseUserspaceSnapshots() {
        return false;
    }

    auto fetcher = IPropertyFetcher::GetInstance();

    const std::string UNKNOWN = "unknown";
    const std::string vendor_release =
            android::base::GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);
            fetcher->GetProperty("ro.vendor.build.version.release_or_codename", UNKNOWN);

    // No user-space snapshots if vendor partition is on Android 12
    if (vendor_release.find("12") != std::string::npos) {
@@ -217,11 +223,13 @@ bool CanUseUserspaceSnapshots() {
}

bool GetIouringEnabledProperty() {
    return android::base::GetBoolProperty("ro.virtual_ab.io_uring.enabled", false);
    auto fetcher = IPropertyFetcher::GetInstance();
    return fetcher->GetBoolProperty("ro.virtual_ab.io_uring.enabled", false);
}

bool GetXorCompressionEnabledProperty() {
    return android::base::GetBoolProperty("ro.virtual_ab.compression.xor.enabled", false);
    auto fetcher = IPropertyFetcher::GetInstance();
    return fetcher->GetBoolProperty("ro.virtual_ab.compression.xor.enabled", false);
}

std::string GetOtherPartitionName(const std::string& name) {
@@ -233,7 +241,8 @@ std::string GetOtherPartitionName(const std::string& name) {
}

bool IsDmSnapshotTestingEnabled() {
    return android::base::GetBoolProperty("snapuserd.test.dm.snapshots", false);
    auto fetcher = IPropertyFetcher::GetInstance();
    return fetcher->GetBoolProperty("snapuserd.test.dm.snapshots", false);
}

}  // namespace snapshot