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

Commit 571f9269 authored by Yifan Hong's avatar Yifan Hong
Browse files

health storage: refactor common code for test

Test: pass
Bug: 177470478
Change-Id: I7be46664df08fd600143ca018885c64030e8d6a1
parent feed84d1
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ cc_test {
    defaults: ["VtsHalTargetTestDefaults"],
    srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
    static_libs: ["android.hardware.health.storage@1.0"],
    header_libs: [
        "libhealth_storage_test_common_headers",
    ],
    shared_libs: [
        "libhidlbase",
    ],
+18 −59
Original line number Diff line number Diff line
@@ -14,14 +14,17 @@
 * limitations under the License.
 */

#include <unistd.h>

#include <thread>

#include <android-base/logging.h>
#include <android/hardware/health/storage/1.0/IStorage.h>
#include <gtest/gtest.h>
#include <health-storage-test/common.h>
#include <hidl/GtestPrinter.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/ServiceManagement.h>
#include <unistd.h>
#include <thread>

namespace android {
namespace hardware {
@@ -29,61 +32,17 @@ namespace health {
namespace storage {
namespace V1_0 {

using namespace ::android::hardware::health::storage::test;
using ::std::literals::chrono_literals::operator""ms;

#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()

// Dev GC timeout. This is the timeout used by vold.
const uint64_t kDevGcTimeoutSec = 120;
const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
// Dev GC timeout tolerance. The HAL may not immediately return after the
// timeout, so include an acceptable tolerance.
const std::chrono::seconds kDevGcTolerance{3};
// Time accounted for RPC calls.
const std::chrono::milliseconds kRpcTime{1000};

template <typename R>
std::string toString(std::chrono::duration<R, std::milli> time) {
    return std::to_string(time.count()) + "ms";
}

/** An atomic boolean flag that indicates whether a task has finished. */
class Flag {
   public:
    void onFinish() {
        std::unique_lock<std::mutex> lock(mMutex);
        onFinishLocked(&lock);
    }
    template <typename R, typename P>
    bool wait(std::chrono::duration<R, P> duration) {
        std::unique_lock<std::mutex> lock(mMutex);
        return waitLocked(&lock, duration);
    }

   protected:
    /** Will unlock. */
    void onFinishLocked(std::unique_lock<std::mutex>* lock) {
        mFinished = true;
        lock->unlock();
        mCv.notify_all();
    }
    template <typename R, typename P>
    bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
        mCv.wait_for(*lock, duration, [this] { return mFinished; });
        return mFinished;
    }

    bool mFinished{false};
    std::mutex mMutex;
    std::condition_variable mCv;
};

class GcCallback : public IGarbageCollectCallback, public Flag {
  public:
    Return<void> onFinish(Result result) override {
        std::unique_lock<std::mutex> lock(mMutex);
        mResult = result;
        Flag::onFinishLocked(&lock);
        std::unique_lock<std::mutex> lock(mutex_);
        result_ = result;
        Flag::OnFinishLocked(&lock);
        return Void();
    }

@@ -93,13 +52,13 @@ class GcCallback : public IGarbageCollectCallback, public Flag {
     */
    template <typename R, typename P>
    void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
        std::unique_lock<std::mutex> lock(mMutex);
        ASSERT_TRUE(waitLocked(&lock, timeout)) << "timeout after " << toString(timeout);
        EXPECT_EQ(expected, mResult);
        std::unique_lock<std::mutex> lock(mutex_);
        ASSERT_TRUE(WaitLocked(&lock, timeout)) << "timeout after " << to_string(timeout);
        EXPECT_EQ(expected, result_);
    }

  private:
    Result mResult{Result::UNKNOWN_ERROR};
    Result result_{Result::UNKNOWN_ERROR};
};

class HealthStorageHidlTest : public ::testing::TestWithParam<std::string> {
@@ -127,10 +86,10 @@ class HealthStorageHidlTest : public ::testing::TestWithParam<std::string> {
        auto pingFlag = std::make_shared<Flag>();
        std::thread([service, pingFlag] {
            service->ping();
            pingFlag->onFinish();
            pingFlag->OnFinish();
        })
            .detach();
        return pingFlag->wait(timeout);
        return pingFlag->Wait(timeout);
    }

    sp<IStorage> fs;
@@ -147,7 +106,7 @@ TEST_P(HealthStorageHidlTest, GcNullCallback) {
    // Hold test process because HAL can be single-threaded and doing GC.
    ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime))
            << "Service must be available after "
            << toString(kDevGcTimeout + kDevGcTolerance + kRpcTime);
            << to_string(kDevGcTimeout + kDevGcTolerance + kRpcTime);
}

/**
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.
 */

cc_library_headers {
    name: "libhealth_storage_test_common_headers",
    export_include_dirs: ["include"],
}
+69 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 <chrono>
#include <string>

namespace android::hardware::health::storage::test {

// Dev GC timeout. This is the timeout used by vold.
const uint64_t kDevGcTimeoutSec = 120;
const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
// Dev GC timeout tolerance. The HAL may not immediately return after the
// timeout, so include an acceptable tolerance.
const std::chrono::seconds kDevGcTolerance{3};
// Time accounted for RPC calls.
const std::chrono::milliseconds kRpcTime{1000};

template <typename R>
std::string to_string(std::chrono::duration<R, std::milli> time) {
    return std::to_string(time.count()) + "ms";
}

/** An atomic boolean flag that indicates whether a task has finished. */
class Flag {
  public:
    void OnFinish() {
        std::unique_lock<std::mutex> lock(mutex_);
        OnFinishLocked(&lock);
    }
    template <typename R, typename P>
    bool Wait(std::chrono::duration<R, P> duration) {
        std::unique_lock<std::mutex> lock(mutex_);
        return WaitLocked(&lock, duration);
    }

  protected:
    /** Will unlock. */
    void OnFinishLocked(std::unique_lock<std::mutex>* lock) {
        finished_ = true;
        lock->unlock();
        cv_.notify_all();
    }
    template <typename R, typename P>
    bool WaitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
        cv_.wait_for(*lock, duration, [this] { return finished_; });
        return finished_;
    }

    bool finished_{false};
    std::mutex mutex_;
    std::condition_variable cv_;
};

}  // namespace android::hardware::health::storage::test