blob: c809e8264a07c00180b8e62951d6dc61bd52121e [file] [log] [blame]
Ana Krulec0c8cd522018-08-31 12:27:28 -07001#undef LOG_TAG
2#define LOG_TAG "SchedulerUnittests"
3
4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
6
7#include <log/log.h>
8
9#include "AsyncCallRecorder.h"
10#include "Scheduler/DispSync.h"
11#include "Scheduler/EventThread.h"
12#include "Scheduler/Scheduler.h"
13#include "mock/MockDispSync.h"
14#include "mock/MockEventThread.h"
15
16using testing::_;
17using testing::Return;
18
19namespace android {
20
21class SchedulerTest : public testing::Test {
22protected:
23 class MockEventThreadConnection : public BnDisplayEventConnection {
24 public:
25 MockEventThreadConnection() = default;
26 ~MockEventThreadConnection() = default;
27
28 MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
29 MOCK_METHOD1(setVsyncRate, status_t(uint32_t count));
30 MOCK_METHOD0(requestNextVsync, void());
31 };
32
33 /**
34 * This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
35 * the same.
36 */
37 class MockScheduler : public android::Scheduler {
38 public:
39 MockScheduler(std::unique_ptr<EventThread> eventThread)
40 : mEventThread(std::move(eventThread)) {}
41
42 std::unique_ptr<EventThread> makeEventThread(
43 const char* /* connectionName */, DispSync* /* dispSync */,
44 nsecs_t /* phaseOffsetNs */,
45 impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
46 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
47 return std::move(mEventThread);
48 }
49
50 MockScheduler() = default;
51 ~MockScheduler() override = default;
52
53 std::unique_ptr<EventThread> mEventThread;
54 };
55
56 SchedulerTest();
57 ~SchedulerTest() override;
58
59 sp<Scheduler::ConnectionHandle> mConnectionHandle;
60 mock::DispSync* mPrimaryDispSync = new mock::DispSync();
61 mock::EventThread* mEventThread;
62 std::unique_ptr<MockScheduler> mScheduler;
63 sp<MockEventThreadConnection> mEventThreadConnection;
64
65 AsyncCallRecorder<void (*)()> mResyncCallRecorder;
66 AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
67};
68
69SchedulerTest::SchedulerTest() {
70 const ::testing::TestInfo* const test_info =
71 ::testing::UnitTest::GetInstance()->current_test_info();
72 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
73
74 std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
75 mEventThread = eventThread.get();
76 mScheduler = std::make_unique<MockScheduler>(std::move(eventThread));
77 mEventThreadConnection = new MockEventThreadConnection();
78
79 // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
80 // sure that call gets executed and returns an EventThread::Connection object.
81 EXPECT_CALL(*mEventThread, createEventConnection())
82 .WillRepeatedly(Return(mEventThreadConnection));
83
84 mConnectionHandle = mScheduler->createConnection("appConnection", mPrimaryDispSync, 16,
85 mResyncCallRecorder.getInvocable(),
86 mInterceptVSyncCallRecorder.getInvocable());
87}
88
89SchedulerTest::~SchedulerTest() {
90 const ::testing::TestInfo* const test_info =
91 ::testing::UnitTest::GetInstance()->current_test_info();
92 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
93}
94
95namespace {
96/* ------------------------------------------------------------------------
97 * Test cases
98 */
99TEST_F(SchedulerTest, canCreateAndDestroyTest) {
100 EXPECT_FALSE(mResyncCallRecorder.waitForCall().has_value());
101 EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall().has_value());
102 EXPECT_EQ(0, mConnectionHandle->id);
103}
104
105TEST_F(SchedulerTest, testNullPtr) {
106 // Passing a null pointer for ConnectionHandle is a valid argument. The code doesn't throw any
107 // exceptions, just gracefully continues.
108 sp<IDisplayEventConnection> returnedValue;
109 ASSERT_NO_FATAL_FAILURE(returnedValue = mScheduler->createDisplayEventConnection(nullptr));
110 EXPECT_TRUE(returnedValue == nullptr);
111 EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
112 EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
113 ASSERT_NO_FATAL_FAILURE(
114 mScheduler->hotplugReceived(nullptr, EventThread::DisplayType::Primary, false));
115 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(nullptr));
116 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(nullptr));
117 String8 testString;
118 ASSERT_NO_FATAL_FAILURE(mScheduler->dump(nullptr, testString));
119 EXPECT_TRUE(testString == "");
120 ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(nullptr, 10));
121}
122
123TEST_F(SchedulerTest, invalidConnectionHandle) {
124 // Passing an invalid ConnectionHandle is a valid argument. The code doesn't throw any
125 // exceptions, just gracefully continues.
126 sp<Scheduler::ConnectionHandle> connectionHandle = new Scheduler::ConnectionHandle(20);
127
128 sp<IDisplayEventConnection> returnedValue;
129 ASSERT_NO_FATAL_FAILURE(returnedValue =
130 mScheduler->createDisplayEventConnection(connectionHandle));
131 EXPECT_TRUE(returnedValue == nullptr);
132 EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
133 EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
134
135 // The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
136 EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
137 ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(connectionHandle,
138 EventThread::DisplayType::Primary, false));
139
140 EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
141 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(connectionHandle));
142
143 EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
144 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(connectionHandle));
145
146 String8 testString;
147 EXPECT_CALL(*mEventThread, dump(_)).Times(0);
148 ASSERT_NO_FATAL_FAILURE(mScheduler->dump(connectionHandle, testString));
149 EXPECT_TRUE(testString == "");
150
151 EXPECT_CALL(*mEventThread, setPhaseOffset(_)).Times(0);
152 ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(connectionHandle, 10));
153}
154
155TEST_F(SchedulerTest, validConnectionHandle) {
156 sp<IDisplayEventConnection> returnedValue;
157 ASSERT_NO_FATAL_FAILURE(returnedValue =
158 mScheduler->createDisplayEventConnection(mConnectionHandle));
159 EXPECT_TRUE(returnedValue != nullptr);
160 ASSERT_EQ(returnedValue, mEventThreadConnection);
161
162 EXPECT_TRUE(mScheduler->getEventThread(mConnectionHandle) != nullptr);
163 EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle) != nullptr);
164
165 EXPECT_CALL(*mEventThread, onHotplugReceived(EventThread::DisplayType::Primary, false))
166 .Times(1);
167 ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(mConnectionHandle,
168 EventThread::DisplayType::Primary, false));
169
170 EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
171 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(mConnectionHandle));
172
173 EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
174 ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(mConnectionHandle));
175
176 String8 testString("dump");
177 EXPECT_CALL(*mEventThread, dump(testString)).Times(1);
178 ASSERT_NO_FATAL_FAILURE(mScheduler->dump(mConnectionHandle, testString));
179 EXPECT_TRUE(testString != "");
180
181 EXPECT_CALL(*mEventThread, setPhaseOffset(10)).Times(1);
182 ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(mConnectionHandle, 10));
183}
184
185} // namespace
186} // namespace android