99f0941ac2f802024ab7664f67a521defa48b2a1
[profile/ivi/qtbase.git] / tests / auto / corelib / kernel / qcoreapplication / tst_qcoreapplication.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtCore/QtCore>
44 #include <QtTest/QtTest>
45
46 class tst_QCoreApplication: public QObject
47 {
48     Q_OBJECT
49 private slots:
50     void sendEventsOnProcessEvents(); // this must be the first test
51     void getSetCheck();
52     void qAppName();
53     void argc();
54     void postEvent();
55     void removePostedEvents();
56 #ifndef QT_NO_THREAD
57     void deliverInDefinedOrder();
58 #endif
59     void applicationPid();
60     void globalPostedEventsCount();
61     void processEventsAlwaysSendsPostedEvents();
62     void reexec();
63     void execAfterExit();
64     void eventLoopExecAfterExit();
65 };
66
67 class EventSpy : public QObject
68 {
69    Q_OBJECT
70
71 public:
72     QList<int> recordedEvents;
73     bool eventFilter(QObject *, QEvent *event)
74     {
75         recordedEvents.append(event->type());
76         return false;
77     }
78 };
79
80 void tst_QCoreApplication::sendEventsOnProcessEvents()
81 {
82     int argc = 1;
83     char *argv[] = { "tst_qcoreapplication" };
84     QCoreApplication app(argc, argv);
85
86     EventSpy spy;
87     app.installEventFilter(&spy);
88
89     QCoreApplication::postEvent(&app,  new QEvent(QEvent::Type(QEvent::User + 1)));
90     QCoreApplication::processEvents();
91     QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
92 }
93
94 void tst_QCoreApplication::getSetCheck()
95 {
96     // do not crash
97     QString v = QCoreApplication::applicationVersion();
98     v = QLatin1String("3.0.0 prerelease 1");
99     QCoreApplication::setApplicationVersion(v);
100     QCOMPARE(QCoreApplication::applicationVersion(), v);
101
102     // Test the property
103     {
104         int argc = 1;
105         char *argv[] = { "tst_qcoreapplication" };
106         QCoreApplication app(argc, argv);
107         QCOMPARE(app.property("applicationVersion").toString(), v);
108     }
109     v = QString();
110     QCoreApplication::setApplicationVersion(v);
111     QCOMPARE(QCoreApplication::applicationVersion(), v);
112 }
113
114 void tst_QCoreApplication::qAppName()
115 {
116     int argc = 1;
117     char *argv[] = { "tst_qcoreapplication" };
118     QCoreApplication app(argc, argv);
119     QVERIFY(!::qAppName().isEmpty());
120 }
121
122 void tst_QCoreApplication::argc()
123 {
124     {
125         int argc = 1;
126         char *argv[] = { "tst_qcoreapplication" };
127         QCoreApplication app(argc, argv);
128         QCOMPARE(argc, 1);
129         QCOMPARE(app.argc(), 1);
130     }
131
132     {
133         int argc = 4;
134         char *argv[] = { "tst_qcoreapplication", "arg1", "arg2", "arg3" };
135         QCoreApplication app(argc, argv);
136         QCOMPARE(argc, 4);
137         QCOMPARE(app.argc(), 4);
138     }
139
140     {
141         int argc = 0;
142         char **argv = 0;
143         QCoreApplication app(argc, argv);
144         QCOMPARE(argc, 0);
145         QCOMPARE(app.argc(), 0);
146     }
147 }
148
149 class EventGenerator : public QObject
150 {
151     Q_OBJECT
152
153 public:
154     QObject *other;
155
156     bool event(QEvent *e)
157     {
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);
165         }
166
167         return QObject::event(e);
168     }
169 };
170
171 void tst_QCoreApplication::postEvent()
172 {
173     int argc = 1;
174     char *argv[] = { "tst_qcoreapplication" };
175     QCoreApplication app(argc, argv);
176
177     EventSpy spy;
178     EventGenerator odd, even;
179     odd.other = &even;
180     odd.installEventFilter(&spy);
181     even.other = &odd;
182     even.installEventFilter(&spy);
183
184     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 1)));
185     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 2)));
186
187     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 3)), 1);
188     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 4)), 2);
189
190     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 5)), -2);
191     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 6)), -1);
192
193     QList<int> expected;
194     expected << QEvent::User + 4
195              << QEvent::User + 3
196              << QEvent::User + 1
197              << QEvent::User + 2
198              << QEvent::User + 6
199              << QEvent::User + 5;
200
201     QCoreApplication::sendPostedEvents();
202     // live lock protection ensures that we only send the initial events
203     QCOMPARE(spy.recordedEvents, expected);
204
205     expected.clear();
206     expected << QEvent::User + 66
207              << QEvent::User + 55
208              << QEvent::User + 44
209              << QEvent::User + 33
210              << QEvent::User + 22
211              << QEvent::User + 11;
212
213     spy.recordedEvents.clear();
214     QCoreApplication::sendPostedEvents();
215     // expect next sequence events
216     QCOMPARE(spy.recordedEvents, expected);
217
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);
222
223     expected.clear();
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;
232
233     spy.recordedEvents.clear();
234     QCoreApplication::sendPostedEvents();
235     QCOMPARE(spy.recordedEvents, expected);
236
237     expected.clear();
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;
244
245     spy.recordedEvents.clear();
246     QCoreApplication::sendPostedEvents();
247     QCOMPARE(spy.recordedEvents, expected);
248
249     // no more events
250     expected.clear();
251     spy.recordedEvents.clear();
252     QCoreApplication::sendPostedEvents();
253     QCOMPARE(spy.recordedEvents, expected);
254 }
255
256 void tst_QCoreApplication::removePostedEvents()
257 {
258     int argc = 1;
259     char *argv[] = { "tst_qcoreapplication" };
260     QCoreApplication app(argc, argv);
261
262     EventSpy spy;
263     QObject one, two;
264     one.installEventFilter(&spy);
265     two.installEventFilter(&spy);
266
267     QList<int> expected;
268
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
278              << QEvent::User + 5
279              << QEvent::User + 6;
280     QCoreApplication::sendPostedEvents();
281     QCOMPARE(spy.recordedEvents, expected);
282     spy.recordedEvents.clear();
283     expected.clear();
284
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());
295
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
307              << QEvent::User + 15
308              << QEvent::User + 16
309              << QEvent::User + 17;
310     QCOMPARE(spy.recordedEvents, expected);
311     spy.recordedEvents.clear();
312     expected.clear();
313
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
324              << QEvent::User + 19
325              << QEvent::User + 21
326              << QEvent::User + 21;
327     QCOMPARE(spy.recordedEvents, expected);
328     spy.recordedEvents.clear();
329     expected.clear();
330 }
331
332 #ifndef QT_NO_THREAD
333 class DeliverInDefinedOrderThread : public QThread
334 {
335     Q_OBJECT
336
337 public:
338     DeliverInDefinedOrderThread()
339         : QThread()
340     { }
341
342 signals:
343     void progress(int);
344
345 protected:
346     void run()
347     {
348         emit progress(1);
349         emit progress(2);
350         emit progress(3);
351         emit progress(4);
352         emit progress(5);
353         emit progress(6);
354         emit progress(7);
355     }
356 };
357
358 class DeliverInDefinedOrderObject : public QObject
359 {
360     Q_OBJECT
361
362     QPointer<QThread> thread;
363     int count;
364     int startCount;
365     int loopLevel;
366
367 public:
368     DeliverInDefinedOrderObject(QObject *parent)
369         : QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
370     { }
371
372 signals:
373     void done();
374
375 public slots:
376     void startThread()
377     {
378         QVERIFY(!thread);
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()));
383         thread->start();
384
385         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
386     }
387
388     void threadProgress(int v)
389     {
390         ++count;
391         QVERIFY(v == count);
392
393         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
394     }
395
396     void threadFinished()
397     {
398         QVERIFY(count == 7);
399         count = 0;
400         thread->deleteLater();
401
402         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
403     }
404
405     void threadDestroyed()
406     {
407         if (++startCount < 20)
408             startThread();
409         else
410             emit done();
411     }
412
413 public:
414     bool event(QEvent *event)
415     {
416         switch (event->type()) {
417         case QEvent::User:
418         {
419             ++loopLevel;
420             if (loopLevel == 2) {
421                 // Ready. Starts a thread that emits (queued) signals, which should be handled in order
422                 startThread();
423             }
424             QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
425             (void) QEventLoop().exec();
426             break;
427         }
428         default:
429             break;
430         }
431         return QObject::event(event);
432     }
433 };
434
435 void tst_QCoreApplication::deliverInDefinedOrder()
436 {
437     int argc = 1;
438     char *argv[] = { "tst_qcoreapplication" };
439     QCoreApplication app(argc, argv);
440
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));
445
446     QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
447     app.exec();
448 }
449 #endif // QT_NO_QTHREAD
450
451 void tst_QCoreApplication::applicationPid()
452 {
453     QVERIFY(QCoreApplication::applicationPid() > 0);
454 }
455
456 QT_BEGIN_NAMESPACE
457 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
458 QT_END_NAMESPACE
459
460 class GlobalPostedEventsCountObject : public QObject
461 {
462     Q_OBJECT
463
464 public:
465     QList<int> globalPostedEventsCount;
466
467     bool event(QEvent *event)
468     {
469         if (event->type() == QEvent::User)
470             globalPostedEventsCount.append(qGlobalPostedEventsCount());
471         return QObject::event(event);
472     }
473 };
474
475 void tst_QCoreApplication::globalPostedEventsCount()
476 {
477     int argc = 1;
478     char *argv[] = { "tst_qcoreapplication" };
479     QCoreApplication app(argc, argv);
480
481     QCoreApplication::sendPostedEvents();
482     QCOMPARE(qGlobalPostedEventsCount(), 0u);
483
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);
491
492     QCoreApplication::sendPostedEvents();
493     QCOMPARE(qGlobalPostedEventsCount(), 0u);
494
495     QList<int> expected = QList<int>()
496                           << 4
497                           << 3
498                           << 2
499                           << 1
500                           << 0;
501     QCOMPARE(x.globalPostedEventsCount, expected);
502 }
503
504 class ProcessEventsAlwaysSendsPostedEventsObject : public QObject
505 {
506 public:
507     int counter;
508
509     inline ProcessEventsAlwaysSendsPostedEventsObject()
510         : counter(0)
511     { }
512
513     bool event(QEvent *event)
514     {
515         if (event->type() == QEvent::User)
516             ++counter;
517         return QObject::event(event);
518     }
519 };
520
521 void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
522 {
523     int argc = 1;
524     char *argv[] = { "tst_qcoreapplication" };
525     QCoreApplication app(argc, argv);
526
527     ProcessEventsAlwaysSendsPostedEventsObject object;
528     QTime t;
529     t.start();
530     int i = 1;
531     do {
532         QCoreApplication::postEvent(&object, new QEvent(QEvent::User));
533         QCoreApplication::processEvents();
534         QCOMPARE(object.counter, i);
535         ++i;
536     } while (t.elapsed() < 1000);
537 }
538
539 void tst_QCoreApplication::reexec()
540 {
541     int argc = 1;
542     char *argv[] = { "tst_qcoreapplication" };
543     QCoreApplication app(argc, argv);
544
545     // exec once
546     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
547     QCOMPARE(app.exec(), 0);
548
549     // and again
550     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
551     QCOMPARE(app.exec(), 0);
552 }
553
554 void tst_QCoreApplication::execAfterExit()
555 {
556     int argc = 1;
557     char *argv[] = { "tst_qcoreapplication" };
558     QCoreApplication app(argc, argv);
559
560     app.exit(1);
561     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
562     QCOMPARE(app.exec(), 0);
563 }
564
565 void tst_QCoreApplication::eventLoopExecAfterExit()
566 {
567     int argc = 1;
568     char *argv[] = { "tst_qcoreapplication" };
569     QCoreApplication app(argc, argv);
570
571     // exec once and exit
572     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
573     QCOMPARE(app.exec(), 0);
574
575     // and again, but this time using a QEventLoop
576     QEventLoop loop;
577     QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
578     QCOMPARE(loop.exec(), 0);
579 }
580
581 QTEST_APPLESS_MAIN(tst_QCoreApplication)
582 #include "tst_qcoreapplication.moc"