health.storage: Add VTS test.
Test: run test Bug: 111655771 Change-Id: I353026bcf882fcdafa9986e4f60d5853abac7e54
This commit is contained in:
parent
c922f43176
commit
14eea6bb3f
2 changed files with 219 additions and 0 deletions
26
health/storage/1.0/vts/functional/Android.bp
Normal file
26
health/storage/1.0/vts/functional/Android.bp
Normal file
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Copyright (C) 2018 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_test {
|
||||
name: "VtsHalHealthStorageV1_0TargetTest",
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
|
||||
static_libs: ["android.hardware.health.storage@1.0"],
|
||||
shared_libs: [
|
||||
"libhidltransport"
|
||||
],
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <VtsHalHidlTargetTestEnvBase.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/hardware/health/storage/1.0/IStorage.h>
|
||||
#include <hidl/HidlTransportSupport.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace health {
|
||||
namespace storage {
|
||||
namespace V1_0 {
|
||||
|
||||
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};
|
||||
// Time accounted for RPC calls.
|
||||
const std::chrono::milliseconds kRpcTime{100};
|
||||
|
||||
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);
|
||||
return Void();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a specific "timeout". If GC has finished, test that the result
|
||||
* is equal to the "expected" value.
|
||||
*/
|
||||
template <typename R, typename P>
|
||||
void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (waitLocked(&lock, timeout)) {
|
||||
EXPECT_EQ(expected, mResult);
|
||||
} else {
|
||||
LOG(INFO) << "timeout after " << toString(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Result mResult{Result::UNKNOWN_ERROR};
|
||||
};
|
||||
|
||||
/** Test environment for Health Storage HIDL HAL. */
|
||||
class HealthStorageHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
|
||||
public:
|
||||
/** get the test environment singleton */
|
||||
static HealthStorageHidlEnvironment* Instance() {
|
||||
static HealthStorageHidlEnvironment* instance = new HealthStorageHidlEnvironment();
|
||||
return instance;
|
||||
}
|
||||
virtual void registerTestServices() override { registerTestService<IStorage>(); }
|
||||
|
||||
private:
|
||||
HealthStorageHidlEnvironment() {}
|
||||
};
|
||||
|
||||
class HealthStorageHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
||||
public:
|
||||
virtual void SetUp() override {
|
||||
fs = ::testing::VtsHalHidlTargetTestBase::getService<IStorage>(
|
||||
HealthStorageHidlEnvironment::Instance()->getServiceName<IStorage>());
|
||||
|
||||
ASSERT_NE(fs, nullptr);
|
||||
LOG(INFO) << "Service is remote " << fs->isRemote();
|
||||
}
|
||||
|
||||
virtual void TearDown() override {
|
||||
EXPECT_TRUE(ping(kRpcTime))
|
||||
<< "Service is not responsive; expect subsequent tests to fail.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the service and expect it to return after "timeout". Return true
|
||||
* iff the service is responsive within "timeout".
|
||||
*/
|
||||
template <typename R, typename P>
|
||||
bool ping(std::chrono::duration<R, P> timeout) {
|
||||
// Ensure the service is responsive after the test.
|
||||
sp<IStorage> service = fs;
|
||||
auto pingFlag = std::make_shared<Flag>();
|
||||
std::thread([service, pingFlag] {
|
||||
service->ping();
|
||||
pingFlag->onFinish();
|
||||
})
|
||||
.detach();
|
||||
return pingFlag->wait(timeout);
|
||||
}
|
||||
|
||||
sp<IStorage> fs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure garbage collection works on null callback.
|
||||
*/
|
||||
TEST_F(HealthStorageHidlTest, GcNullCallback) {
|
||||
auto ret = fs->garbageCollect(kDevGcTimeoutSec, nullptr);
|
||||
|
||||
ASSERT_OK(ret);
|
||||
|
||||
// Hold test process because HAL can be single-threaded and doing GC.
|
||||
ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime))
|
||||
<< "Service must be available after " << toString(kDevGcTimeout + kRpcTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure garbage collection works on non-null callback.
|
||||
*/
|
||||
TEST_F(HealthStorageHidlTest, GcNonNullCallback) {
|
||||
sp<GcCallback> cb = new GcCallback();
|
||||
auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb);
|
||||
ASSERT_OK(ret);
|
||||
cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS);
|
||||
}
|
||||
|
||||
} // namespace V1_0
|
||||
} // namespace storage
|
||||
} // namespace health
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using ::android::hardware::configureRpcThreadpool;
|
||||
using ::android::hardware::health::storage::V1_0::HealthStorageHidlEnvironment;
|
||||
|
||||
configureRpcThreadpool(1, false /* callerWillJoin*/);
|
||||
::testing::AddGlobalTestEnvironment(HealthStorageHidlEnvironment::Instance());
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
HealthStorageHidlEnvironment::Instance()->init(&argc, argv);
|
||||
int status = RUN_ALL_TESTS();
|
||||
LOG(INFO) << "Test result = " << status;
|
||||
return status;
|
||||
}
|
Loading…
Reference in a new issue