@@ -0,0 +1,323 @@
2+ * Copyright (C) 2015 Canonical, Ltd.
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.
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.
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/>.
17+#include "HomeKeyWatcher.h"
24+class FakeElapsedTimer : public AbstractElapsedTimer {
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; }
35+ qint64 m_msecsSinceReference;
37+qint64 FakeElapsedTimer::msecsSinceEpoch = 0;
39+class FakeTimer : public AbstractTimer
43+ FakeTimer(QObject *parent = nullptr);
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;
56+ qint64 m_nextTimeoutTime;
59+class FakeTimerFactory : public AbstractTimerFactory
63+ virtual ~FakeTimerFactory();
65+ void updateTime(qint64 targetTime);
67+ AbstractTimer *create(QObject *parent = nullptr) override;
68+ QList<QPointer<FakeTimer>> timers;
70+} // namespace UnityUtil
72+using namespace UnityUtil;
74+class HomeKeyWatcherTest : public QObject {
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();
86+ void passTime(qint64 timeSpanMs);
88+ FakeTimerFactory *m_fakeTimerFactory;
91+void HomeKeyWatcherTest::init()
93+ m_fakeTimerFactory = new FakeTimerFactory;
96+void HomeKeyWatcherTest::cleanup()
98+ delete m_fakeTimerFactory;
99+ m_fakeTimerFactory = nullptr;
103+void HomeKeyWatcherTest::passTime(qint64 timeSpanMs)
105+ qint64 finalTime = FakeElapsedTimer::msecsSinceEpoch + timeSpanMs;
106+ m_fakeTimerFactory->updateTime(finalTime);
109+void 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;
124+void 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, SIGNAL(activated()));
132+ QVERIFY(activatedSpy.isValid());
135+ QTouchEvent touchEvent(QEvent::TouchBegin);
136+ homeKeyWatcher.update(&touchEvent);
140+ QTouchEvent touchEvent(QEvent::TouchUpdate);
141+ homeKeyWatcher.update(&touchEvent);
145+ QTouchEvent touchEvent(QEvent::TouchEnd);
146+ homeKeyWatcher.update(&touchEvent);
149+ passTime(silenceBeforeTap);
152+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
153+ homeKeyWatcher.update(&keyEvent);
156+ while (tapTime < tapDuration) {
159+ if (tapTime + 10 >= tapDuration) {
160+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
161+ homeKeyWatcher.update(&keyEvent);
163+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier, QString(), true /*autorepeat*/);
164+ homeKeyWatcher.update(&keyEvent);
168+ passTime(silenceAfterTap);
171+ QTouchEvent touchEvent(QEvent::TouchBegin);
172+ homeKeyWatcher.update(&touchEvent);
176+ QTouchEvent touchEvent(QEvent::TouchUpdate);
177+ homeKeyWatcher.update(&touchEvent);
181+ QTouchEvent touchEvent(QEvent::TouchEnd);
182+ homeKeyWatcher.update(&touchEvent);
186+ QCOMPARE(activatedSpy.count(), expectedActivatedCount);
189+void HomeKeyWatcherTest::tapWhileTouching()
191+ HomeKeyWatcher homeKeyWatcher(m_fakeTimerFactory->create(), new FakeElapsedTimer);
192+ QSignalSpy activatedSpy(&homeKeyWatcher, SIGNAL(activated()));
193+ QVERIFY(activatedSpy.isValid());
196+ QTouchEvent touchEvent(QEvent::TouchBegin);
197+ homeKeyWatcher.update(&touchEvent);
201+ QKeyEvent keyEvent(QEvent::KeyPress, Qt::Key_Super_L, Qt::NoModifier);
202+ homeKeyWatcher.update(&keyEvent);
206+ QKeyEvent keyEvent(QEvent::KeyRelease, Qt::Key_Super_L, Qt::NoModifier);
207+ homeKeyWatcher.update(&keyEvent);
211+ QTouchEvent touchEvent(QEvent::TouchEnd);
212+ homeKeyWatcher.update(&touchEvent);
217+ QCOMPARE(activatedSpy.count(), 0);
220+/////////////////////////////////// FakeTimer //////////////////////////////////
222+FakeTimer::FakeTimer(QObject *parent)
223+ : UnityUtil::AbstractTimer(parent)
225+ , m_singleShot(true)
229+void FakeTimer::update()
235+ if (m_nextTimeoutTime <= FakeElapsedTimer::msecsSinceEpoch) {
236+ if (isSingleShot()) {
239+ m_nextTimeoutTime += interval();
245+void FakeTimer::start()
247+ AbstractTimer::start();
248+ m_nextTimeoutTime = FakeElapsedTimer::msecsSinceEpoch + (qint64)interval();
251+int FakeTimer::interval() const
256+void FakeTimer::setInterval(int msecs)
261+bool FakeTimer::isSingleShot() const
263+ return m_singleShot;
266+void FakeTimer::setSingleShot(bool value)
268+ m_singleShot = value;
271+/////////////////////////////////// FakeTimerFactory //////////////////////////////////
273+FakeTimerFactory::FakeTimerFactory()
277+FakeTimerFactory::~FakeTimerFactory()
279+ for (int i = 0; i < timers.count(); ++i) {
280+ FakeTimer *timer = timers[i].data();
287+void 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();
298+ FakeElapsedTimer::msecsSinceEpoch = minTimeoutTime;
300+ for (int i = 0; i < timers.count(); ++i) {
301+ FakeTimer *timer = timers[i].data();
307+ if (FakeElapsedTimer::msecsSinceEpoch < targetTime) {
308+ updateTime(targetTime);
312+AbstractTimer *FakeTimerFactory::create(QObject *parent)
314+ FakeTimer *fakeTimer = new FakeTimer(parent);
316+ timers.append(fakeTimer);
321+QTEST_GUILESS_MAIN(HomeKeyWatcherTest)
323+#include "homekeywatchertest.moc"