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

Commit 26d7d953 authored by Yifan Hong's avatar Yifan Hong
Browse files

libsnapshot: tests for public APIs.

Test: libsnapshot_test

Change-Id: I411ae32e77914845ed4037d7e67620598f8218cf
parent 0e13bbad
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <stdint.h>
#include <stdlib.h>

namespace android {
namespace digital_storage {

template <size_t Power>
struct Size {
    static constexpr size_t power = Power;
    constexpr Size(uint64_t count) : value_(count) {}

    constexpr uint64_t bytes() const { return value_ << (Power * 10); }
    constexpr uint64_t count() const { return value_; }
    operator uint64_t() const { return bytes(); }

  private:
    uint64_t value_;
};

using B = Size<0>;
using KiB = Size<1>;
using MiB = Size<2>;
using GiB = Size<3>;

constexpr B operator""_B(unsigned long long v) {  // NOLINT
    return B{v};
}

constexpr KiB operator""_KiB(unsigned long long v) {  // NOLINT
    return KiB{v};
}

constexpr MiB operator""_MiB(unsigned long long v) {  // NOLINT
    return MiB{v};
}

constexpr GiB operator""_GiB(unsigned long long v) {  // NOLINT
    return GiB{v};
}

template <typename Dest, typename Src>
constexpr Dest size_cast(Src src) {
    if (Src::power < Dest::power) {
        return Dest(src.count() >> ((Dest::power - Src::power) * 10));
    }
    if (Src::power > Dest::power) {
        return Dest(src.count() << ((Src::power - Dest::power) * 10));
    }
    return Dest(src.count());
}

static_assert((1_B).bytes() == 1);
static_assert((1_KiB).bytes() == 1 << 10);
static_assert((1_MiB).bytes() == 1 << 20);
static_assert((1_GiB).bytes() == 1 << 30);
static_assert(size_cast<KiB>(1_B).count() == 0);
static_assert(size_cast<KiB>(1024_B).count() == 1);
static_assert(size_cast<KiB>(1_MiB).count() == 1024);

}  // namespace digital_storage
}  // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -200,7 +200,9 @@ class SnapshotManager final {
    FRIEND_TEST(SnapshotTest, Merge);
    FRIEND_TEST(SnapshotTest, MergeCannotRemoveCow);
    FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
    FRIEND_TEST(SnapshotUpdateTest, SnapshotStatusFileWithoutCow);
    friend class SnapshotTest;
    friend class SnapshotUpdateTest;
    friend struct AutoDeleteCowImage;
    friend struct AutoDeleteSnapshot;
    friend struct PartitionCowCreator;
+436 −13

File changed.

Preview size limit exceeded, changes collapsed.

+57 −0
Original line number Diff line number Diff line
@@ -14,11 +14,18 @@

#include "test_helpers.h"

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <openssl/sha.h>

namespace android {
namespace snapshot {

using android::base::ReadFully;
using android::base::unique_fd;
using android::base::WriteFully;
using android::fiemap::IImageManager;

void DeleteBackingImage(IImageManager* manager, const std::string& name) {
@@ -53,5 +60,55 @@ std::string TestPartitionOpener::GetDeviceString(const std::string& partition_na
    return PartitionOpener::GetDeviceString(partition_name);
}

bool WriteRandomData(const std::string& path) {
    unique_fd rand(open("/dev/urandom", O_RDONLY));
    unique_fd fd(open(path.c_str(), O_WRONLY));

    char buf[4096];
    while (true) {
        ssize_t n = TEMP_FAILURE_RETRY(read(rand.get(), buf, sizeof(buf)));
        if (n <= 0) return false;
        if (!WriteFully(fd.get(), buf, n)) {
            if (errno == ENOSPC) {
                return true;
            }
            PLOG(ERROR) << "Cannot write " << path;
            return false;
        }
    }
}

std::string ToHexString(const uint8_t* buf, size_t len) {
    char lookup[] = "0123456789abcdef";
    std::string out(len * 2 + 1, '\0');
    char* outp = out.data();
    for (; len > 0; len--, buf++) {
        *outp++ = (char)lookup[*buf >> 4];
        *outp++ = (char)lookup[*buf & 0xf];
    }
    return out;
}

std::optional<std::string> GetHash(const std::string& path) {
    unique_fd fd(open(path.c_str(), O_RDONLY));
    char buf[4096];
    SHA256_CTX ctx;
    SHA256_Init(&ctx);
    while (true) {
        ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf)));
        if (n < 0) {
            PLOG(ERROR) << "Cannot read " << path;
            return std::nullopt;
        }
        if (n == 0) {
            break;
        }
        SHA256_Update(&ctx, buf, n);
    }
    uint8_t out[32];
    SHA256_Final(out, &ctx);
    return ToHexString(out, sizeof(out));
}

}  // namespace snapshot
}  // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

#pragma once

#include <optional>
#include <string>

#include <libfiemap/image_manager.h>
@@ -66,5 +67,10 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
// Helper for error-spam-free cleanup.
void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::string& name);

// Write some random data to the given device. Will write until reaching end of the device.
bool WriteRandomData(const std::string& device);

std::optional<std::string> GetHash(const std::string& path);

}  // namespace snapshot
}  // namespace android