1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 #include <QtCore/QtCore>
44 #include <QtTest/QtTest>
46 class tst_QCoreApplication: public QObject
50 void sendEventsOnProcessEvents(); // this must be the first test
55 void removePostedEvents();
57 void deliverInDefinedOrder();
59 void applicationPid();
60 void globalPostedEventsCount();
61 void processEventsAlwaysSendsPostedEvents();
64 void eventLoopExecAfterExit();
67 class EventSpy : public QObject
72 QList<int> recordedEvents;
73 bool eventFilter(QObject *, QEvent *event)
75 recordedEvents.append(event->type());
80 void tst_QCoreApplication::sendEventsOnProcessEvents()
83 char *argv[] = { "tst_qcoreapplication" };
84 QCoreApplication app(argc, argv);
87 app.installEventFilter(&spy);
89 QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
90 QCoreApplication::processEvents();
91 QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
94 void tst_QCoreApplication::getSetCheck()
97 QString v = QCoreApplication::applicationVersion();
98 v = QLatin1String("3.0.0 prerelease 1");
99 QCoreApplication::setApplicationVersion(v);
100 QCOMPARE(QCoreApplication::applicationVersion(), v);
105 char *argv[] = { "tst_qcoreapplication" };
106 QCoreApplication app(argc, argv);
107 QCOMPARE(app.property("applicationVersion").toString(), v);
110 QCoreApplication::setApplicationVersion(v);
111 QCOMPARE(QCoreApplication::applicationVersion(), v);
114 void tst_QCoreApplication::qAppName()
117 char *argv[] = { "tst_qcoreapplication" };
118 QCoreApplication app(argc, argv);
119 QVERIFY(!::qAppName().isEmpty());
122 void tst_QCoreApplication::argc()
126 char *argv[] = { "tst_qcoreapplication" };
127 QCoreApplication app(argc, argv);
129 QCOMPARE(app.argc(), 1);
134 char *argv[] = { "tst_qcoreapplication", "arg1", "arg2", "arg3" };
135 QCoreApplication app(argc, argv);
137 QCOMPARE(app.argc(), 4);
143 QCoreApplication app(argc, argv);
145 QCOMPARE(app.argc(), 0);
150 char *argv[] = { "tst_qcoreapplication", "-qmljsdebugger=port:3768,block" };
151 QCoreApplication app(argc, argv);
153 QCOMPARE(app.argc(), 1);
157 class EventGenerator : public QObject
164 bool event(QEvent *e)
166 if (e->type() == QEvent::MaxUser) {
167 QCoreApplication::sendPostedEvents(other, 0);
168 } else if (e->type() <= QEvent::User + 999) {
169 // post a new event in response to this posted event
170 int offset = e->type() - QEvent::User;
171 offset = (offset * 10 + offset % 10);
172 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(QEvent::User + offset)), offset);
175 return QObject::event(e);
179 void tst_QCoreApplication::postEvent()
182 char *argv[] = { "tst_qcoreapplication" };
183 QCoreApplication app(argc, argv);
186 EventGenerator odd, even;
188 odd.installEventFilter(&spy);
190 even.installEventFilter(&spy);
192 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 1)));
193 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 2)));
195 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 3)), 1);
196 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 4)), 2);
198 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 5)), -2);
199 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 6)), -1);
202 expected << QEvent::User + 4
209 QCoreApplication::sendPostedEvents();
210 // live lock protection ensures that we only send the initial events
211 QCOMPARE(spy.recordedEvents, expected);
214 expected << QEvent::User + 66
219 << QEvent::User + 11;
221 spy.recordedEvents.clear();
222 QCoreApplication::sendPostedEvents();
223 // expect next sequence events
224 QCOMPARE(spy.recordedEvents, expected);
226 // have the generators call sendPostedEvents() on each other in
227 // response to an event
228 QCoreApplication::postEvent(&odd, new QEvent(QEvent::MaxUser), INT_MAX);
229 QCoreApplication::postEvent(&even, new QEvent(QEvent::MaxUser), INT_MAX);
232 expected << int(QEvent::MaxUser)
233 << int(QEvent::MaxUser)
234 << QEvent::User + 555
235 << QEvent::User + 333
236 << QEvent::User + 111
237 << QEvent::User + 666
238 << QEvent::User + 444
239 << QEvent::User + 222;
241 spy.recordedEvents.clear();
242 QCoreApplication::sendPostedEvents();
243 QCOMPARE(spy.recordedEvents, expected);
246 expected << QEvent::User + 6666
247 << QEvent::User + 5555
248 << QEvent::User + 4444
249 << QEvent::User + 3333
250 << QEvent::User + 2222
251 << QEvent::User + 1111;
253 spy.recordedEvents.clear();
254 QCoreApplication::sendPostedEvents();
255 QCOMPARE(spy.recordedEvents, expected);
259 spy.recordedEvents.clear();
260 QCoreApplication::sendPostedEvents();
261 QCOMPARE(spy.recordedEvents, expected);
264 void tst_QCoreApplication::removePostedEvents()
267 char *argv[] = { "tst_qcoreapplication" };
268 QCoreApplication app(argc, argv);
272 one.installEventFilter(&spy);
273 two.installEventFilter(&spy);
277 // remove all events for one object
278 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 1)));
279 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 2)));
280 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 3)));
281 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 4)));
282 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 5)));
283 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 6)));
284 QCoreApplication::removePostedEvents(&one);
285 expected << QEvent::User + 4
288 QCoreApplication::sendPostedEvents();
289 QCOMPARE(spy.recordedEvents, expected);
290 spy.recordedEvents.clear();
293 // remove all events for all objects
294 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 7)));
295 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 8)));
296 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 9)));
297 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 10)));
298 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 11)));
299 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 12)));
300 QCoreApplication::removePostedEvents(0);
301 QCoreApplication::sendPostedEvents();
302 QVERIFY(spy.recordedEvents.isEmpty());
304 // remove a specific type of event for one object
305 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 13)));
306 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 14)));
307 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 15)));
308 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 16)));
309 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 17)));
310 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 18)));
311 QCoreApplication::removePostedEvents(&one, QEvent::User + 13);
312 QCoreApplication::removePostedEvents(&two, QEvent::User + 18);
313 QCoreApplication::sendPostedEvents();
314 expected << QEvent::User + 14
317 << QEvent::User + 17;
318 QCOMPARE(spy.recordedEvents, expected);
319 spy.recordedEvents.clear();
322 // remove a specific type of event for all objects
323 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 19)));
324 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 19)));
325 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 20)));
326 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 20)));
327 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 21)));
328 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 21)));
329 QCoreApplication::removePostedEvents(0, QEvent::User + 20);
330 QCoreApplication::sendPostedEvents();
331 expected << QEvent::User + 19
334 << QEvent::User + 21;
335 QCOMPARE(spy.recordedEvents, expected);
336 spy.recordedEvents.clear();
341 class DeliverInDefinedOrderThread : public QThread
346 DeliverInDefinedOrderThread()
366 class DeliverInDefinedOrderObject : public QObject
370 QPointer<QThread> thread;
376 DeliverInDefinedOrderObject(QObject *parent)
377 : QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
387 thread = new DeliverInDefinedOrderThread();
388 connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
389 connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
390 connect(thread, SIGNAL(destroyed()), this, SLOT(threadDestroyed()));
393 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
396 void threadProgress(int v)
401 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
404 void threadFinished()
408 thread->deleteLater();
410 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
413 void threadDestroyed()
415 if (++startCount < 20)
422 bool event(QEvent *event)
424 switch (event->type()) {
428 if (loopLevel == 2) {
429 // Ready. Starts a thread that emits (queued) signals, which should be handled in order
432 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
433 (void) QEventLoop().exec();
439 return QObject::event(event);
443 void tst_QCoreApplication::deliverInDefinedOrder()
446 char *argv[] = { "tst_qcoreapplication" };
447 QCoreApplication app(argc, argv);
449 DeliverInDefinedOrderObject obj(&app);
450 // causes sendPostedEvents() to recurse twice
451 QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
452 QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
454 QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
457 #endif // QT_NO_QTHREAD
459 void tst_QCoreApplication::applicationPid()
461 QVERIFY(QCoreApplication::applicationPid() > 0);
465 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
468 class GlobalPostedEventsCountObject : public QObject
473 QList<int> globalPostedEventsCount;
475 bool event(QEvent *event)
477 if (event->type() == QEvent::User)
478 globalPostedEventsCount.append(qGlobalPostedEventsCount());
479 return QObject::event(event);
483 void tst_QCoreApplication::globalPostedEventsCount()
486 char *argv[] = { "tst_qcoreapplication" };
487 QCoreApplication app(argc, argv);
489 QCoreApplication::sendPostedEvents();
490 QCOMPARE(qGlobalPostedEventsCount(), 0u);
492 GlobalPostedEventsCountObject x;
493 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
494 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
495 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
496 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
497 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
498 QCOMPARE(qGlobalPostedEventsCount(), 5u);
500 QCoreApplication::sendPostedEvents();
501 QCOMPARE(qGlobalPostedEventsCount(), 0u);
503 QList<int> expected = QList<int>()
509 QCOMPARE(x.globalPostedEventsCount, expected);
512 class ProcessEventsAlwaysSendsPostedEventsObject : public QObject
517 inline ProcessEventsAlwaysSendsPostedEventsObject()
521 bool event(QEvent *event)
523 if (event->type() == QEvent::User)
525 return QObject::event(event);
529 void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
532 char *argv[] = { "tst_qcoreapplication" };
533 QCoreApplication app(argc, argv);
535 ProcessEventsAlwaysSendsPostedEventsObject object;
540 QCoreApplication::postEvent(&object, new QEvent(QEvent::User));
541 QCoreApplication::processEvents();
542 QCOMPARE(object.counter, i);
544 } while (t.elapsed() < 1000);
547 void tst_QCoreApplication::reexec()
550 char *argv[] = { "tst_qcoreapplication" };
551 QCoreApplication app(argc, argv);
554 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
555 QCOMPARE(app.exec(), 0);
558 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
559 QCOMPARE(app.exec(), 0);
562 void tst_QCoreApplication::execAfterExit()
565 char *argv[] = { "tst_qcoreapplication" };
566 QCoreApplication app(argc, argv);
569 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
570 QCOMPARE(app.exec(), 0);
573 void tst_QCoreApplication::eventLoopExecAfterExit()
576 char *argv[] = { "tst_qcoreapplication" };
577 QCoreApplication app(argc, argv);
579 // exec once and exit
580 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
581 QCOMPARE(app.exec(), 0);
583 // and again, but this time using a QEventLoop
585 QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
586 QCOMPARE(loop.exec(), 0);
589 QTEST_APPLESS_MAIN(tst_QCoreApplication)
590 #include "tst_qcoreapplication.moc"