summaryrefslogtreecommitdiffstats
path: root/health
diff options
context:
space:
mode:
authorYifan Hong <elsk@google.com>2018-08-08 17:51:10 -0700
committerYifan Hong <elsk@google.com>2018-09-21 12:25:24 -0700
commit14eea6bb3f5b40b68a22da50db93b6a94b055d8d (patch)
treeea02c0ffe7c58b06ec5829bc111324574137f2d4 /health
parentc922f43176776391d15010c5552bd60161de5dc3 (diff)
downloadandroid_hardware_interfaces-14eea6bb3f5b40b68a22da50db93b6a94b055d8d.tar.gz
android_hardware_interfaces-14eea6bb3f5b40b68a22da50db93b6a94b055d8d.tar.bz2
android_hardware_interfaces-14eea6bb3f5b40b68a22da50db93b6a94b055d8d.zip
health.storage: Add VTS test.
Test: run test Bug: 111655771 Change-Id: I353026bcf882fcdafa9986e4f60d5853abac7e54
Diffstat (limited to 'health')
-rw-r--r--health/storage/1.0/vts/functional/Android.bp26
-rw-r--r--health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp193
2 files changed, 219 insertions, 0 deletions
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
new file mode 100644
index 000000000..63591cf12
--- /dev/null
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -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"
+ ],
+}
+
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
new file mode 100644
index 000000000..5ad561cef
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -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;
+}