summaryrefslogtreecommitdiff
path: root/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp')
-rw-r--r--automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
new file mode 100644
index 0000000000..a033a248cd
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "RecurrentTimer.h"
+
+#include <android-base/thread_annotations.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+class RecurrentTimerTest : public testing::Test {
+ public:
+ std::shared_ptr<RecurrentTimer::Callback> getCallback(size_t token) {
+ return std::make_shared<RecurrentTimer::Callback>([this, token] {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+
+ mCallbacks.push_back(token);
+ });
+ }
+
+ std::vector<size_t> getCalledCallbacks() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return mCallbacks;
+ }
+
+ void clearCalledCallbacks() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mCallbacks.clear();
+ }
+
+ size_t countTimerCallbackQueue(RecurrentTimer* timer) {
+ std::scoped_lock<std::mutex> lockGuard(timer->mLock);
+ return timer->mCallbackQueue.size();
+ }
+
+ private:
+ std::mutex mLock;
+ std::vector<size_t> mCallbacks GUARDED_BY(mLock);
+};
+
+TEST_F(RecurrentTimerTest, testRegisterCallback) {
+ RecurrentTimer timer;
+ // 0.1s
+ int64_t interval = 100000000;
+
+ auto action = getCallback(0);
+ timer.registerTimerCallback(interval, action);
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+
+ timer.unregisterTimerCallback(action);
+
+ // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+ ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+}
+
+TEST_F(RecurrentTimerTest, testRegisterUnregisterRegister) {
+ RecurrentTimer timer;
+ // 0.1s
+ int64_t interval = 100000000;
+
+ auto action = getCallback(0);
+ timer.registerTimerCallback(interval, action);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ timer.unregisterTimerCallback(action);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ clearCalledCallbacks();
+
+ timer.registerTimerCallback(interval, action);
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+
+ // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+ ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+}
+
+TEST_F(RecurrentTimerTest, testDestroyTimerWithCallback) {
+ std::unique_ptr<RecurrentTimer> timer = std::make_unique<RecurrentTimer>();
+ // 0.1s
+ int64_t interval = 100000000;
+
+ auto action = getCallback(0);
+ timer->registerTimerCallback(interval, action);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ timer.reset();
+
+ clearCalledCallbacks();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+
+ ASSERT_TRUE(getCalledCallbacks().empty());
+}
+
+TEST_F(RecurrentTimerTest, testRegisterMultipleCallbacks) {
+ RecurrentTimer timer;
+ // 0.1s
+ int64_t interval1 = 100000000;
+ auto action1 = getCallback(1);
+ timer.registerTimerCallback(interval1, action1);
+ // 0.05s
+ int64_t interval2 = 50000000;
+ auto action2 = getCallback(2);
+ timer.registerTimerCallback(interval2, action2);
+ // 0.03s
+ int64_t interval3 = 30000000;
+ auto action3 = getCallback(3);
+ timer.registerTimerCallback(interval3, action3);
+
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+
+ timer.unregisterTimerCallback(action1);
+ timer.unregisterTimerCallback(action2);
+ timer.unregisterTimerCallback(action3);
+
+ size_t action1Count = 0;
+ size_t action2Count = 0;
+ size_t action3Count = 0;
+ for (size_t token : getCalledCallbacks()) {
+ if (token == 1) {
+ action1Count++;
+ }
+ if (token == 2) {
+ action2Count++;
+ }
+ if (token == 3) {
+ action3Count++;
+ }
+ }
+ // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+ ASSERT_GE(action1Count, static_cast<size_t>(9));
+ // Theoretically trigger 20 times, but check for at least 15 times to be stable.
+ ASSERT_GE(action2Count, static_cast<size_t>(15));
+ // Theoretically trigger 33 times, but check for at least 25 times to be stable.
+ ASSERT_GE(action3Count, static_cast<size_t>(25));
+}
+
+TEST_F(RecurrentTimerTest, testRegisterSameCallbackMultipleTimes) {
+ RecurrentTimer timer;
+ // 0.02s
+ int64_t interval1 = 20000000;
+ // 0.01s
+ int64_t interval2 = 10000000;
+
+ auto action = getCallback(0);
+ for (int i = 0; i < 10; i++) {
+ timer.registerTimerCallback(interval1, action);
+ timer.registerTimerCallback(interval2, action);
+ }
+
+ clearCalledCallbacks();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ // Theoretically trigger 10 times, but check for at least 9 times to be stable.
+ ASSERT_GE(getCalledCallbacks().size(), static_cast<size_t>(9));
+
+ timer.unregisterTimerCallback(action);
+
+ // Make sure there is no item in the callback queue.
+ ASSERT_EQ(countTimerCallbackQueue(&timer), static_cast<size_t>(0));
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android