summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/tests/unittests/MessageQueueTest.cpp')
-rw-r--r--services/surfaceflinger/tests/unittests/MessageQueueTest.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
new file mode 100644
index 0000000000..dbd51fed78
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "FrameTimeline.h"
+#include "Scheduler/MessageQueue.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+using namespace std::chrono_literals;
+using namespace testing;
+
+using CallbackToken = scheduler::VSyncDispatch::CallbackToken;
+
+class TestableMessageQueue : public impl::MessageQueue {
+public:
+ class MockHandler : public MessageQueue::Handler {
+ public:
+ explicit MockHandler(MessageQueue& queue) : MessageQueue::Handler(queue) {}
+ ~MockHandler() override = default;
+ MOCK_METHOD2(dispatchInvalidate, void(int64_t vsyncId, nsecs_t expectedVSyncTimestamp));
+ };
+
+ TestableMessageQueue() = default;
+ ~TestableMessageQueue() override = default;
+
+ void initHandler(const sp<MockHandler>& handler) { mHandler = handler; }
+
+ void triggerVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
+ vsyncCallback(vsyncTime, targetWakeupTime, readyTime);
+ }
+};
+
+class MockVSyncDispatch : public scheduler::VSyncDispatch {
+public:
+ MockVSyncDispatch() = default;
+ ~MockVSyncDispatch() override = default;
+
+ MOCK_METHOD2(registerCallback,
+ CallbackToken(std::function<void(nsecs_t, nsecs_t, nsecs_t)> const&, std::string));
+ MOCK_METHOD1(unregisterCallback, void(CallbackToken));
+ MOCK_METHOD2(schedule, scheduler::ScheduleResult(CallbackToken, ScheduleTiming));
+ MOCK_METHOD1(cancel, scheduler::CancelResult(CallbackToken token));
+ MOCK_CONST_METHOD1(dump, void(std::string&));
+};
+
+class MockTokenManager : public frametimeline::TokenManager {
+public:
+ MockTokenManager() = default;
+ ~MockTokenManager() override = default;
+
+ MOCK_METHOD1(generateTokenForPredictions, int64_t(frametimeline::TimelineItem&& prediction));
+ MOCK_CONST_METHOD1(getPredictionsForToken, std::optional<frametimeline::TimelineItem>(int64_t));
+};
+
+class MessageQueueTest : public testing::Test {
+public:
+ MessageQueueTest() = default;
+ ~MessageQueueTest() override = default;
+
+ void SetUp() override {
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.initHandler(mHandler));
+
+ EXPECT_CALL(mVSyncDispatch, registerCallback(_, "sf")).WillOnce(Return(mCallbackToken));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.initVsync(mVSyncDispatch, mTokenManager, mDuration));
+ EXPECT_CALL(mVSyncDispatch, unregisterCallback(mCallbackToken)).Times(1);
+ }
+
+ sp<TestableMessageQueue::MockHandler> mHandler =
+ new TestableMessageQueue::MockHandler(mEventQueue);
+ MockVSyncDispatch mVSyncDispatch;
+ MockTokenManager mTokenManager;
+ TestableMessageQueue mEventQueue;
+
+ const CallbackToken mCallbackToken{5};
+ constexpr static auto mDuration = std::chrono::nanoseconds(100ms);
+ constexpr static auto mDifferentDuration = std::chrono::nanoseconds(250ms);
+};
+
+namespace {
+/* ------------------------------------------------------------------------
+ * Test cases
+ */
+TEST_F(MessageQueueTest, invalidate) {
+ const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(),
+ .readyDuration = 0,
+ .earliestVsync = 0};
+ EXPECT_FALSE(mEventQueue.nextExpectedInvalidate().has_value());
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+ EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value());
+ EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count());
+}
+
+TEST_F(MessageQueueTest, invalidateTwice) {
+ InSequence s;
+ const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(),
+ .readyDuration = 0,
+ .earliestVsync = 0};
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+ EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value());
+ EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count());
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(4567));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+ EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value());
+ EXPECT_EQ(4567, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count());
+}
+
+TEST_F(MessageQueueTest, invalidateTwiceWithCallback) {
+ InSequence s;
+ const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(),
+ .readyDuration = 0,
+ .earliestVsync = 0};
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+ EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value());
+ EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count());
+
+ const auto startTime = 100;
+ const auto endTime = startTime + mDuration.count();
+ const auto presentTime = 500;
+ const auto vsyncId = 42;
+ EXPECT_CALL(mTokenManager,
+ generateTokenForPredictions(
+ frametimeline::TimelineItem(startTime, endTime, presentTime)))
+ .WillOnce(Return(vsyncId));
+ EXPECT_CALL(*mHandler, dispatchInvalidate(vsyncId, presentTime)).Times(1);
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.triggerVsyncCallback(presentTime, startTime, endTime));
+
+ EXPECT_FALSE(mEventQueue.nextExpectedInvalidate().has_value());
+
+ const auto timingAfterCallback =
+ scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(),
+ .readyDuration = 0,
+ .earliestVsync = presentTime};
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+}
+
+TEST_F(MessageQueueTest, invalidateWithDurationChange) {
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.setDuration(mDifferentDuration));
+
+ const auto timing =
+ scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDifferentDuration.count(),
+ .readyDuration = 0,
+ .earliestVsync = 0};
+
+ EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0));
+ EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate());
+}
+
+} // namespace
+} // namespace android