on ded455e help sign in
unity8/tests/plugins/Utils/HomeKeyWatcherTest.cpp
323 lines 8.3 kB history raw
1/*
2 * Copyright (C) 2015 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "HomeKeyWatcher.h"
19#include <QTest>
20#include <QSignalSpy>
23namespace UnityUtil {
24class FakeElapsedTimer : public AbstractElapsedTimer {
25public:
26 static qint64 msecsSinceEpoch;
28 FakeElapsedTimer() { start(); }
30 void start() override { m_msecsSinceReference = msecsSinceEpoch; }
31 qint64 msecsSinceReference() const override { return m_msecsSinceReference; }
32 qint64 elapsed() const override { return msecsSinceEpoch - m_msecsSinceReference; }
34private:
35 qint64 m_msecsSinceReference;
36};
37qint64 FakeElapsedTimer::msecsSinceEpoch = 0;
39class FakeTimer : public AbstractTimer
41 Q_OBJECT
42public:
43 FakeTimer(QObject *parent = nullptr);
45 void update();
46 qint64 nextTimeoutTime() const { return m_nextTimeoutTime; }
48 int interval() const override;
49 void setInterval(int msecs) override;
50 void start() override;
51 bool isSingleShot() const override;
52 void setSingleShot(bool value) override;
53private:
54 int m_interval;
55 bool m_singleShot;
56 qint64 m_nextTimeoutTime;
57};
59class FakeTimerFactory : public AbstractTimerFactory
61public:
62 FakeTimerFactory();
63 virtual ~FakeTimerFactory();
65 void updateTime(qint64 targetTime);
67 AbstractTimer *create(QObject *parent = nullptr) override;
68 QList<QPointer<FakeTimer>> timers;
69};
70} // namespace UnityUtil
72using namespace UnityUtil;
74class HomeKeyWatcherTest : public QObject {
75 Q_OBJECT
76private Q_SLOTS:
77 void init(); // called right before each and every test function is executed
78 void cleanup(); // called right after each and every test function is executed
80 void touchTapTouch_data();
81 void touchTapTouch();
83 void tapWhileTouching();
85private:
86 void passTime(qint64 timeSpanMs);
88 FakeTimerFactory *m_fakeTimerFactory;
89};
91void HomeKeyWatcherTest::init()
93 m_fakeTimerFactory = new FakeTimerFactory;
96void HomeKeyWatcherTest::cleanup()
98 delete m_fakeTimerFactory;
99 m_fakeTimerFactory = nullptr;
103void HomeKeyWatcherTest::passTime(qint64 timeSpanMs)
105 qint64 finalTime = FakeElapsedTimer::msecsSinceEpoch + timeSpanMs;
106 m_fakeTimerFactory->updateTime(finalTime);
109void HomeKeyWatcherTest::touchTapTouch_data()
111 QTest::addColumn<int>("silenceBeforeTap");
112 QTest::addColumn<int>("tapDuration");
113 QTest::addColumn<int>("silenceAfterTap");
114 QTest::addColumn<int>("expectedActivatedCount");
116 QTest::newRow("tap followed by touch") << 2000 << 50 << 10 << 0;
117 QTest::newRow("touch, tap and touch") << 10 << 50 << 10 << 0;
118 QTest::newRow("touch followed by tap") << 10 << 50 << 2000 << 0;
119 QTest::newRow("touch followed by long tap") << 10 << 500 << 2000 << 0;
120 QTest::newRow("isolated tap") << 1000 << 50 << 1000 << 1;
121 QTest::newRow("isolated long press") << 1000 << 200 << 1000 << 0;
124void HomeKeyWatcherTest::touchTapTouch()
126 QFETCH(int, silenceBeforeTap);
127 QFETCH(int, tapDuration);
128 QFETCH(int, silenceAfterTap);
129 QFETCH(int, expectedActivatedCount);
130 HomeKeyWatcher homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
131 QSignalSpy activatedSpy(&homeKeyWatcher, &HomeKeyWatcher::activated);
132 QVERIFY(activatedSpy.isValid());
134 {
135 QTouchEvent touchEvent(QEvent::TouchBegin);
136 homeKeyWatcher.update(&touchEvent);
137 }
138 passTime(100);
139 {
140 QTouchEvent touchEvent(QEvent::TouchUpdate);
141 homeKeyWatcher.update(&touchEvent);
142 }
143 passTime(100);
144 {
145 QTouchEvent touchEvent(QEvent::TouchEnd);
146 homeKeyWatcher.update(&touchEvent);
147 }
149 passTime(silenceBeforeTap);
151 {
152 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
153 homeKeyWatcher.update(&keyEvent);
154 }
155 int tapTime = 0;
156 while (tapTime < tapDuration) {
157 passTime(10);
158 tapTime += 10;
159 if (tapTime + 10 >= tapDuration) {
160 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
161 homeKeyWatcher.update(&keyEvent);
162 } else {
163 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier, QString(), true /*autorepeat*/);
164 homeKeyWatcher.update(&keyEvent);
165 }
166 }
168 passTime(silenceAfterTap);
170 {
171 QTouchEvent touchEvent(QEvent::TouchBegin);
172 homeKeyWatcher.update(&touchEvent);
173 }
174 passTime(100);
175 {
176 QTouchEvent touchEvent(QEvent::TouchUpdate);
177 homeKeyWatcher.update(&touchEvent);
178 }
179 passTime(100);
180 {
181 QTouchEvent touchEvent(QEvent::TouchEnd);
182 homeKeyWatcher.update(&touchEvent);
183 }
184 passTime(1000);
186 QCOMPARE(activatedSpy.count(), expectedActivatedCount);
189void HomeKeyWatcherTest::tapWhileTouching()
191 HomeKeyWatcher homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
192 QSignalSpy activatedSpy(&homeKeyWatcher, &HomeKeyWatcher::activated);
193 QVERIFY(activatedSpy.isValid());
195 {
196 QTouchEvent touchEvent(QEvent::TouchBegin);
197 homeKeyWatcher.update(&touchEvent);
198 }
199 passTime(1000);
200 {
201 QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
202 homeKeyWatcher.update(&keyEvent);
203 }
204 passTime(100);
205 {
206 QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
207 homeKeyWatcher.update(&keyEvent);
208 }
209 passTime(1000);
210 {
211 QTouchEvent touchEvent(QEvent::TouchEnd);
212 homeKeyWatcher.update(&touchEvent);
213 }
214 passTime(1000);
217 QCOMPARE(activatedSpy.count(), 0);
220/////////////////////////////////// FakeTimer //////////////////////////////////
222FakeTimer::FakeTimer(QObject *parent)
223 : UnityUtil::AbstractTimer(parent)
224 , m_interval(0)
225 , m_singleShot(true)
229void FakeTimer::update()
231 if (!isRunning()) {
232 return;
233 }
235 if (m_nextTimeoutTime <= FakeElapsedTimer::msecsSinceEpoch) {
236 if (isSingleShot()) {
237 stop();
238 } else {
239 m_nextTimeoutTime += interval();
240 }
241 Q_EMIT timeout();
242 }
245void FakeTimer::start()
247 AbstractTimer::start();
248 m_nextTimeoutTime = FakeElapsedTimer::msecsSinceEpoch + (qint64)interval();
251int FakeTimer::interval() const
253 return m_interval;
256void FakeTimer::setInterval(int msecs)
258 m_interval = msecs;
261bool FakeTimer::isSingleShot() const
263 return m_singleShot;
266void FakeTimer::setSingleShot(bool value)
268 m_singleShot = value;
271/////////////////////////////////// FakeTimerFactory //////////////////////////////////
273FakeTimerFactory::FakeTimerFactory()
277FakeTimerFactory::~FakeTimerFactory()
279 for (int i = 0; i < timers.count(); ++i) {
280 FakeTimer *timer = timers[i].data();
281 if (timer) {
282 delete timer;
283 }
284 }
287void FakeTimerFactory::updateTime(qint64 targetTime)
289 qint64 minTimeoutTime = targetTime;
291 for (int i = 0; i < timers.count(); ++i) {
292 FakeTimer *timer = timers[i].data();
293 if (timer && timer->isRunning() && timer->nextTimeoutTime() < minTimeoutTime) {
294 minTimeoutTime = timer->nextTimeoutTime();
295 }
296 }
298 FakeElapsedTimer::msecsSinceEpoch = minTimeoutTime;
300 for (int i = 0; i < timers.count(); ++i) {
301 FakeTimer *timer = timers[i].data();
302 if (timer) {
303 timer->update();
304 }
305 }
307 if (FakeElapsedTimer::msecsSinceEpoch < targetTime) {
308 updateTime(targetTime);
309 }
312AbstractTimer *FakeTimerFactory::create(QObject *parent)
314 FakeTimer *fakeTimer = new FakeTimer(parent);
316 timers.append(fakeTimer);
318 return fakeTimer;
321QTEST_GUILESS_MAIN(HomeKeyWatcherTest)
323#include "HomeKeyWatcherTest.moc"