]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android/platform-hardware-interfaces.git/blob - health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
health.storage: Add VTS test.
[android/platform-hardware-interfaces.git] / health / storage / 1.0 / vts / functional / VtsHalHealthStorageV1_0TargetTest.cpp
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 #include <VtsHalHidlTargetTestBase.h>
18 #include <VtsHalHidlTargetTestEnvBase.h>
19 #include <android-base/logging.h>
20 #include <android/hardware/health/storage/1.0/IStorage.h>
21 #include <hidl/HidlTransportSupport.h>
22 #include <unistd.h>
23 #include <thread>
25 namespace android {
26 namespace hardware {
27 namespace health {
28 namespace storage {
29 namespace V1_0 {
31 using ::std::literals::chrono_literals::operator""ms;
33 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()
35 // Dev GC timeout. This is the timeout used by vold.
36 const uint64_t kDevGcTimeoutSec = 120;
37 const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
38 // Time accounted for RPC calls.
39 const std::chrono::milliseconds kRpcTime{100};
41 template <typename R>
42 std::string toString(std::chrono::duration<R, std::milli> time) {
43     return std::to_string(time.count()) + "ms";
44 }
46 /** An atomic boolean flag that indicates whether a task has finished. */
47 class Flag {
48    public:
49     void onFinish() {
50         std::unique_lock<std::mutex> lock(mMutex);
51         onFinishLocked(&lock);
52     }
53     template <typename R, typename P>
54     bool wait(std::chrono::duration<R, P> duration) {
55         std::unique_lock<std::mutex> lock(mMutex);
56         return waitLocked(&lock, duration);
57     }
59    protected:
60     /** Will unlock. */
61     void onFinishLocked(std::unique_lock<std::mutex>* lock) {
62         mFinished = true;
63         lock->unlock();
64         mCv.notify_all();
65     }
66     template <typename R, typename P>
67     bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
68         mCv.wait_for(*lock, duration, [this] { return mFinished; });
69         return mFinished;
70     }
72     bool mFinished{false};
73     std::mutex mMutex;
74     std::condition_variable mCv;
75 };
77 class GcCallback : public IGarbageCollectCallback, public Flag {
78    public:
79     Return<void> onFinish(Result result) override {
80         std::unique_lock<std::mutex> lock(mMutex);
81         mResult = result;
82         Flag::onFinishLocked(&lock);
83         return Void();
84     }
86     /**
87      * Wait for a specific "timeout". If GC has finished, test that the result
88      * is equal to the "expected" value.
89      */
90     template <typename R, typename P>
91     void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
92         std::unique_lock<std::mutex> lock(mMutex);
93         if (waitLocked(&lock, timeout)) {
94             EXPECT_EQ(expected, mResult);
95         } else {
96             LOG(INFO) << "timeout after " << toString(timeout);
97         }
98     }
100    private:
101     Result mResult{Result::UNKNOWN_ERROR};
102 };
104 /** Test environment for Health Storage HIDL HAL. */
105 class HealthStorageHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
106    public:
107     /** get the test environment singleton */
108     static HealthStorageHidlEnvironment* Instance() {
109         static HealthStorageHidlEnvironment* instance = new HealthStorageHidlEnvironment();
110         return instance;
111     }
112     virtual void registerTestServices() override { registerTestService<IStorage>(); }
114    private:
115     HealthStorageHidlEnvironment() {}
116 };
118 class HealthStorageHidlTest : public ::testing::VtsHalHidlTargetTestBase {
119    public:
120     virtual void SetUp() override {
121         fs = ::testing::VtsHalHidlTargetTestBase::getService<IStorage>(
122             HealthStorageHidlEnvironment::Instance()->getServiceName<IStorage>());
124         ASSERT_NE(fs, nullptr);
125         LOG(INFO) << "Service is remote " << fs->isRemote();
126     }
128     virtual void TearDown() override {
129         EXPECT_TRUE(ping(kRpcTime))
130             << "Service is not responsive; expect subsequent tests to fail.";
131     }
133     /**
134      * Ping the service and expect it to return after "timeout". Return true
135      * iff the service is responsive within "timeout".
136      */
137     template <typename R, typename P>
138     bool ping(std::chrono::duration<R, P> timeout) {
139         // Ensure the service is responsive after the test.
140         sp<IStorage> service = fs;
141         auto pingFlag = std::make_shared<Flag>();
142         std::thread([service, pingFlag] {
143             service->ping();
144             pingFlag->onFinish();
145         })
146             .detach();
147         return pingFlag->wait(timeout);
148     }
150     sp<IStorage> fs;
151 };
153 /**
154  * Ensure garbage collection works on null callback.
155  */
156 TEST_F(HealthStorageHidlTest, GcNullCallback) {
157     auto ret = fs->garbageCollect(kDevGcTimeoutSec, nullptr);
159     ASSERT_OK(ret);
161     // Hold test process because HAL can be single-threaded and doing GC.
162     ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime))
163         << "Service must be available after " << toString(kDevGcTimeout + kRpcTime);
166 /**
167  * Ensure garbage collection works on non-null callback.
168  */
169 TEST_F(HealthStorageHidlTest, GcNonNullCallback) {
170     sp<GcCallback> cb = new GcCallback();
171     auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb);
172     ASSERT_OK(ret);
173     cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS);
176 }  // namespace V1_0
177 }  // namespace storage
178 }  // namespace health
179 }  // namespace hardware
180 }  // namespace android
182 int main(int argc, char** argv) {
183     using ::android::hardware::configureRpcThreadpool;
184     using ::android::hardware::health::storage::V1_0::HealthStorageHidlEnvironment;
186     configureRpcThreadpool(1, false /* callerWillJoin*/);
187     ::testing::AddGlobalTestEnvironment(HealthStorageHidlEnvironment::Instance());
188     ::testing::InitGoogleTest(&argc, argv);
189     HealthStorageHidlEnvironment::Instance()->init(&argc, argv);
190     int status = RUN_ALL_TESTS();
191     LOG(INFO) << "Test result = " << status;
192     return status;