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);
149 class EventGenerator : public QObject
156 bool event(QEvent *e)
158 if (e->type() == QEvent::MaxUser) {
159 QCoreApplication::sendPostedEvents(other, 0);
160 } else if (e->type() <= QEvent::User + 999) {
161 // post a new event in response to this posted event
162 int offset = e->type() - QEvent::User;
163 offset = (offset * 10 + offset % 10);
164 QCoreApplication::postEvent(this, new QEvent(QEvent::Type(QEvent::User + offset)), offset);
167 return QObject::event(e);
171 void tst_QCoreApplication::postEvent()
174 char *argv[] = { "tst_qcoreapplication" };
175 QCoreApplication app(argc, argv);
178 EventGenerator odd, even;
180 odd.installEventFilter(&spy);
182 even.installEventFilter(&spy);
184 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 1)));
185 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 2)));
187 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 3)), 1);
188 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 4)), 2);
190 QCoreApplication::postEvent(&odd, new QEvent(QEvent::Type(QEvent::User + 5)), -2);
191 QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 6)), -1);
194 expected << QEvent::User + 4
201 QCoreApplication::sendPostedEvents();
202 // live lock protection ensures that we only send the initial events
203 QCOMPARE(spy.recordedEvents, expected);
206 expected << QEvent::User + 66
211 << QEvent::User + 11;
213 spy.recordedEvents.clear();
214 QCoreApplication::sendPostedEvents();
215 // expect next sequence events
216 QCOMPARE(spy.recordedEvents, expected);
218 // have the generators call sendPostedEvents() on each other in
219 // response to an event
220 QCoreApplication::postEvent(&odd, new QEvent(QEvent::MaxUser), INT_MAX);
221 QCoreApplication::postEvent(&even, new QEvent(QEvent::MaxUser), INT_MAX);
224 expected << int(QEvent::MaxUser)
225 << int(QEvent::MaxUser)
226 << QEvent::User + 555
227 << QEvent::User + 333
228 << QEvent::User + 111
229 << QEvent::User + 666
230 << QEvent::User + 444
231 << QEvent::User + 222;
233 spy.recordedEvents.clear();
234 QCoreApplication::sendPostedEvents();
235 QCOMPARE(spy.recordedEvents, expected);
238 expected << QEvent::User + 6666
239 << QEvent::User + 5555
240 << QEvent::User + 4444
241 << QEvent::User + 3333
242 << QEvent::User + 2222
243 << QEvent::User + 1111;
245 spy.recordedEvents.clear();
246 QCoreApplication::sendPostedEvents();
247 QCOMPARE(spy.recordedEvents, expected);
251 spy.recordedEvents.clear();
252 QCoreApplication::sendPostedEvents();
253 QCOMPARE(spy.recordedEvents, expected);
256 void tst_QCoreApplication::removePostedEvents()
259 char *argv[] = { "tst_qcoreapplication" };
260 QCoreApplication app(argc, argv);
264 one.installEventFilter(&spy);
265 two.installEventFilter(&spy);
269 // remove all events for one object
270 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 1)));
271 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 2)));
272 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 3)));
273 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 4)));
274 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 5)));
275 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 6)));
276 QCoreApplication::removePostedEvents(&one);
277 expected << QEvent::User + 4
280 QCoreApplication::sendPostedEvents();
281 QCOMPARE(spy.recordedEvents, expected);
282 spy.recordedEvents.clear();
285 // remove all events for all objects
286 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 7)));
287 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 8)));
288 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 9)));
289 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 10)));
290 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 11)));
291 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 12)));
292 QCoreApplication::removePostedEvents(0);
293 QCoreApplication::sendPostedEvents();
294 QVERIFY(spy.recordedEvents.isEmpty());
296 // remove a specific type of event for one object
297 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 13)));
298 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 14)));
299 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 15)));
300 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 16)));
301 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 17)));
302 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 18)));
303 QCoreApplication::removePostedEvents(&one, QEvent::User + 13);
304 QCoreApplication::removePostedEvents(&two, QEvent::User + 18);
305 QCoreApplication::sendPostedEvents();
306 expected << QEvent::User + 14
309 << QEvent::User + 17;
310 QCOMPARE(spy.recordedEvents, expected);
311 spy.recordedEvents.clear();
314 // remove a specific type of event for all objects
315 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 19)));
316 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 19)));
317 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 20)));
318 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 20)));
319 QCoreApplication::postEvent(&one, new QEvent(QEvent::Type(QEvent::User + 21)));
320 QCoreApplication::postEvent(&two, new QEvent(QEvent::Type(QEvent::User + 21)));
321 QCoreApplication::removePostedEvents(0, QEvent::User + 20);
322 QCoreApplication::sendPostedEvents();
323 expected << QEvent::User + 19
326 << QEvent::User + 21;
327 QCOMPARE(spy.recordedEvents, expected);
328 spy.recordedEvents.clear();
333 class DeliverInDefinedOrderThread : public QThread
338 DeliverInDefinedOrderThread()
358 class DeliverInDefinedOrderObject : public QObject
362 QPointer<QThread> thread;
368 DeliverInDefinedOrderObject(QObject *parent)
369 : QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
379 thread = new DeliverInDefinedOrderThread();
380 connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
381 connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
382 connect(thread, SIGNAL(destroyed()), this, SLOT(threadDestroyed()));
385 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
388 void threadProgress(int v)
393 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
396 void threadFinished()
400 thread->deleteLater();
402 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
405 void threadDestroyed()
407 if (++startCount < 20)
414 bool event(QEvent *event)
416 switch (event->type()) {
420 if (loopLevel == 2) {
421 // Ready. Starts a thread that emits (queued) signals, which should be handled in order
424 QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
425 (void) QEventLoop().exec();
431 return QObject::event(event);
435 void tst_QCoreApplication::deliverInDefinedOrder()
438 char *argv[] = { "tst_qcoreapplication" };
439 QCoreApplication app(argc, argv);
441 DeliverInDefinedOrderObject obj(&app);
442 // causes sendPostedEvents() to recurse twice
443 QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
444 QCoreApplication::postEvent(&obj, new QEvent(QEvent::User));
446 QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
449 #endif // QT_NO_QTHREAD
451 void tst_QCoreApplication::applicationPid()
453 QVERIFY(QCoreApplication::applicationPid() > 0);
457 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
460 class GlobalPostedEventsCountObject : public QObject
465 QList<int> globalPostedEventsCount;
467 bool event(QEvent *event)
469 if (event->type() == QEvent::User)
470 globalPostedEventsCount.append(qGlobalPostedEventsCount());
471 return QObject::event(event);
475 void tst_QCoreApplication::globalPostedEventsCount()
478 char *argv[] = { "tst_qcoreapplication" };
479 QCoreApplication app(argc, argv);
481 QCoreApplication::sendPostedEvents();
482 QCOMPARE(qGlobalPostedEventsCount(), 0u);
484 GlobalPostedEventsCountObject x;
485 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
486 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
487 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
488 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
489 QCoreApplication::postEvent(&x, new QEvent(QEvent::User));
490 QCOMPARE(qGlobalPostedEventsCount(), 5u);
492 QCoreApplication::sendPostedEvents();
493 QCOMPARE(qGlobalPostedEventsCount(), 0u);
495 QList<int> expected = QList<int>()
501 QCOMPARE(x.globalPostedEventsCount, expected);
504 class ProcessEventsAlwaysSendsPostedEventsObject : public QObject
509 inline ProcessEventsAlwaysSendsPostedEventsObject()
513 bool event(QEvent *event)
515 if (event->type() == QEvent::User)
517 return QObject::event(event);
521 void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
524 char *argv[] = { "tst_qcoreapplication" };
525 QCoreApplication app(argc, argv);
527 ProcessEventsAlwaysSendsPostedEventsObject object;
532 QCoreApplication::postEvent(&object, new QEvent(QEvent::User));
533 QCoreApplication::processEvents();
534 QCOMPARE(object.counter, i);
536 } while (t.elapsed() < 1000);
539 void tst_QCoreApplication::reexec()
542 char *argv[] = { "tst_qcoreapplication" };
543 QCoreApplication app(argc, argv);
546 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
547 QCOMPARE(app.exec(), 0);
550 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
551 QCOMPARE(app.exec(), 0);
554 void tst_QCoreApplication::execAfterExit()
557 char *argv[] = { "tst_qcoreapplication" };
558 QCoreApplication app(argc, argv);
561 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
562 QCOMPARE(app.exec(), 0);
565 void tst_QCoreApplication::eventLoopExecAfterExit()
568 char *argv[] = { "tst_qcoreapplication" };
569 QCoreApplication app(argc, argv);
571 // exec once and exit
572 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
573 QCOMPARE(app.exec(), 0);
575 // and again, but this time using a QEventLoop
577 QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
578 QCOMPARE(loop.exec(), 0);
581 QTEST_APPLESS_MAIN(tst_QCoreApplication)
582 #include "tst_qcoreapplication.moc"