1 /*
2  * Copyright 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  */
16 #undef LOG_TAG
17 #define LOG_TAG "SchedulerUnittests"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <utils/Log.h>
22 
23 #include "AsyncCallRecorder.h"
24 #include "Scheduler/IdleTimer.h"
25 
26 using namespace std::chrono_literals;
27 
28 namespace android {
29 namespace scheduler {
30 
31 class IdleTimerTest : public testing::Test {
32 protected:
33     IdleTimerTest() = default;
34     ~IdleTimerTest() override = default;
35 
36     // This timeout should be used when a 3ms callback is expected.
37     // While the tests typically request a callback after 3ms, the scheduler
38     // does not always cooperate, at it can take significantly longer (observed
39     // 30ms).
40     static constexpr auto waitTimeForExpected3msCallback = 100ms;
41 
42     // This timeout should be used when an 3ms callback is not expected.
43     // Note that there can be false-negatives if the callback happens later.
44     static constexpr auto waitTimeForUnexpected3msCallback = 6ms;
45 
46     AsyncCallRecorder<void (*)()> mResetTimerCallback;
47     AsyncCallRecorder<void (*)()> mExpiredTimerCallback;
48 
49     std::unique_ptr<IdleTimer> mIdleTimer;
50 
clearPendingCallbacks()51     void clearPendingCallbacks() {
52         while (mExpiredTimerCallback.waitForCall(0us).has_value()) {
53         }
54     }
55 };
56 
57 namespace {
TEST_F(IdleTimerTest,createAndDestroyTest)58 TEST_F(IdleTimerTest, createAndDestroyTest) {
59     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, [] {}, [] {});
60 }
61 
TEST_F(IdleTimerTest,startStopTest)62 TEST_F(IdleTimerTest, startStopTest) {
63     mIdleTimer = std::make_unique<scheduler::IdleTimer>(30ms, mResetTimerCallback.getInvocable(),
64                                                         mExpiredTimerCallback.getInvocable());
65     auto startTime = std::chrono::steady_clock::now();
66     mIdleTimer->start();
67     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
68     // The idle timer fires after 30ms, so there should be no callback within
69     // 25ms (waiting for a callback for the full 30ms would be problematic).
70     bool callbackCalled = mExpiredTimerCallback.waitForCall(25ms).has_value();
71     // Under ideal conditions there should be no event. But occasionally
72     // it is possible that the wait just prior takes more than 30ms, and
73     // a callback is observed. We check the elapsed time since before the IdleTimer
74     // thread was started as a sanity check to not have a flakey test.
75     EXPECT_FALSE(callbackCalled && std::chrono::steady_clock::now() - startTime < 30ms);
76 
77     std::this_thread::sleep_for(std::chrono::milliseconds(25));
78     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
79     mIdleTimer->stop();
80 }
81 
TEST_F(IdleTimerTest,resetTest)82 TEST_F(IdleTimerTest, resetTest) {
83     mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
84                                                         mExpiredTimerCallback.getInvocable());
85     mIdleTimer->start();
86     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
87     // Observe any event that happens in about 25ms. We don't care if one was
88     // observed or not.
89     mExpiredTimerCallback.waitForCall(25ms).has_value();
90     mIdleTimer->reset();
91     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
92     // There may have been a race with the reset. Clear any callbacks we
93     // received right afterwards.
94     clearPendingCallbacks();
95     // A single callback should be generated after 30ms
96     EXPECT_TRUE(
97             mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback + 30ms).has_value());
98     // After one event, it should be idle, and not generate another.
99     EXPECT_FALSE(
100             mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback * 10).has_value());
101     mIdleTimer->stop();
102     // Final quick check that no more callback were observed.
103     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(0ms).has_value());
104     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
105 }
106 
TEST_F(IdleTimerTest,resetBackToBackTest)107 TEST_F(IdleTimerTest, resetBackToBackTest) {
108     mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(),
109                                                         mExpiredTimerCallback.getInvocable());
110     mIdleTimer->start();
111     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
112 
113     mIdleTimer->reset();
114     EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
115     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
116 
117     mIdleTimer->reset();
118     EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
119     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
120 
121     mIdleTimer->reset();
122     EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
123     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
124 
125     mIdleTimer->reset();
126     EXPECT_FALSE(mResetTimerCallback.waitForCall(1ms).has_value());
127     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
128 
129     // A single callback should be generated after 30ms
130     EXPECT_TRUE(
131             mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback + 30ms).has_value());
132     mIdleTimer->stop();
133     // Final quick check that no more callback were observed.
134     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(0ms).has_value());
135     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
136 }
137 
TEST_F(IdleTimerTest,startNotCalledTest)138 TEST_F(IdleTimerTest, startNotCalledTest) {
139     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
140                                                         mExpiredTimerCallback.getInvocable());
141     // The start hasn't happened, so the callback does not happen.
142     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
143     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
144     mIdleTimer->stop();
145     // Final quick check that no more callback were observed.
146     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(0ms).has_value());
147     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
148 }
149 
TEST_F(IdleTimerTest,idleTimerIdlesTest)150 TEST_F(IdleTimerTest, idleTimerIdlesTest) {
151     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
152                                                         mExpiredTimerCallback.getInvocable());
153     mIdleTimer->start();
154     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
155 
156     // A callback should be generated after 3ms
157     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
158     // After one event, it should be idle, and not generate another.
159     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
160     // Once reset, it should generate another
161     mIdleTimer->reset();
162     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
163     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
164     mIdleTimer->stop();
165     // Final quick check that no more callback were observed.
166     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(0ms).has_value());
167     EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value());
168 }
169 
TEST_F(IdleTimerTest,timeoutCallbackExecutionTest)170 TEST_F(IdleTimerTest, timeoutCallbackExecutionTest) {
171     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
172                                                         mExpiredTimerCallback.getInvocable());
173     mIdleTimer->start();
174     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
175     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
176     mIdleTimer->stop();
177 }
178 
TEST_F(IdleTimerTest,noCallbacksAfterStopAndResetTest)179 TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) {
180     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
181                                                         mExpiredTimerCallback.getInvocable());
182     mIdleTimer->start();
183     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
184     EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value());
185 
186     mIdleTimer->stop();
187     clearPendingCallbacks();
188     mIdleTimer->reset();
189     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
190     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
191 }
192 
TEST_F(IdleTimerTest,noCallbacksAfterStopTest)193 TEST_F(IdleTimerTest, noCallbacksAfterStopTest) {
194     mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(),
195                                                         mExpiredTimerCallback.getInvocable());
196     mIdleTimer->start();
197     EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
198 
199     mIdleTimer->stop();
200     clearPendingCallbacks();
201     mIdleTimer->reset();
202 
203     // No more idle events should be observed
204     EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
205     EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value());
206 }
207 
208 } // namespace
209 } // namespace scheduler
210 } // namespace android
211