Move handling of -qmljsdebugger argument to QCoreApplication
[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         int argc = 2;
150         char *argv[] = { "tst_qcoreapplication", "-qmljsdebugger=port:3768,block" };
151         QCoreApplication app(argc, argv);
152         QCOMPARE(argc, 1);
153         QCOMPARE(app.argc(), 1);
154     }
155 }
156
157 class EventGenerator : public QObject
158 {
159     Q_OBJECT
160
161 public:
162     QObject *other;
163
164     bool event(QEvent *e)
165     {
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);
173         }
174
175         return QObject::event(e);
176     }
177 };
178
179 void tst_QCoreApplication::postEvent()
180 {
181     int argc = 1;
182     char *argv[] = { "tst_qcoreapplication" };
183     QCoreApplication app(argc, argv);
184
185     EventSpy spy;
186     EventGenerator odd, even;
187     odd.other = &even;
188     odd.installEventFilter(&spy);
189     even.other = &odd;
190     even.installEventFilter(&spy);
191
192     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 1)));
193     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 2)));
194
195     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 3)), 1);
196     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 4)), 2);
197
198     QCoreApplication::postEvent(&odd,  new QEvent(QEvent::Type(QEvent::User + 5)), -2);
199     QCoreApplication::postEvent(&even, new QEvent(QEvent::Type(QEvent::User + 6)), -1);
200
201     QList<int> expected;
202     expected << QEvent::User + 4
203              << QEvent::User + 3
204              << QEvent::User + 1
205              << QEvent::User + 2
206              << QEvent::User + 6
207              << QEvent::User + 5;
208
209     QCoreApplication::sendPostedEvents();
210     // live lock protection ensures that we only send the initial events
211     QCOMPARE(spy.recordedEvents, expected);
212
213     expected.clear();
214     expected << QEvent::User + 66
215              << QEvent::User + 55
216              << QEvent::User + 44
217              << QEvent::User + 33
218              << QEvent::User + 22
219              << QEvent::User + 11;
220
221     spy.recordedEvents.clear();
222     QCoreApplication::sendPostedEvents();
223     // expect next sequence events
224     QCOMPARE(spy.recordedEvents, expected);
225
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);
230
231     expected.clear();
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;
240
241     spy.recordedEvents.clear();
242     QCoreApplication::sendPostedEvents();
243     QCOMPARE(spy.recordedEvents, expected);
244
245     expected.clear();
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;
252
253     spy.recordedEvents.clear();
254     QCoreApplication::sendPostedEvents();
255     QCOMPARE(spy.recordedEvents, expected);
256
257     // no more events
258     expected.clear();
259     spy.recordedEvents.clear();
260     QCoreApplication::sendPostedEvents();
261     QCOMPARE(spy.recordedEvents, expected);
262 }
263
264 void tst_QCoreApplication::removePostedEvents()
265 {
266     int argc = 1;
267     char *argv[] = { "tst_qcoreapplication" };
268     QCoreApplication app(argc, argv);
269
270     EventSpy spy;
271     QObject one, two;
272     one.installEventFilter(&spy);
273     two.installEventFilter(&spy);
274
275     QList<int> expected;
276
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
286              << QEvent::User + 5
287              << QEvent::User + 6;
288     QCoreApplication::sendPostedEvents();
289     QCOMPARE(spy.recordedEvents, expected);
290     spy.recordedEvents.clear();
291     expected.clear();
292
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());
303
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
315              << QEvent::User + 15
316              << QEvent::User + 16
317              << QEvent::User + 17;
318     QCOMPARE(spy.recordedEvents, expected);
319     spy.recordedEvents.clear();
320     expected.clear();
321
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
332              << QEvent::User + 19
333              << QEvent::User + 21
334              << QEvent::User + 21;
335     QCOMPARE(spy.recordedEvents, expected);
336     spy.recordedEvents.clear();
337     expected.clear();
338 }
339
340 #ifndef QT_NO_THREAD
341 class DeliverInDefinedOrderThread : public QThread
342 {
343     Q_OBJECT
344
345 public:
346     DeliverInDefinedOrderThread()
347         : QThread()
348     { }
349
350 signals:
351     void progress(int);
352
353 protected:
354     void run()
355     {
356         emit progress(1);
357         emit progress(2);
358         emit progress(3);
359         emit progress(4);
360         emit progress(5);
361         emit progress(6);
362         emit progress(7);
363     }
364 };
365
366 class DeliverInDefinedOrderObject : public QObject
367 {
368     Q_OBJECT
369
370     QPointer<QThread> thread;
371     int count;
372     int startCount;
373     int loopLevel;
374
375 public:
376     DeliverInDefinedOrderObject(QObject *parent)
377         : QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
378     { }
379
380 signals:
381     void done();
382
383 public slots:
384     void startThread()
385     {
386         QVERIFY(!thread);
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()));
391         thread->start();
392
393         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
394     }
395
396     void threadProgress(int v)
397     {
398         ++count;
399         QVERIFY(v == count);
400
401         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
402     }
403
404     void threadFinished()
405     {
406         QVERIFY(count == 7);
407         count = 0;
408         thread->deleteLater();
409
410         QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
411     }
412
413     void threadDestroyed()
414     {
415         if (++startCount < 20)
416             startThread();
417         else
418             emit done();
419     }
420
421 public:
422     bool event(QEvent *event)
423     {
424         switch (event->type()) {
425         case QEvent::User:
426         {
427             ++loopLevel;
428             if (loopLevel == 2) {
429                 // Ready. Starts a thread that emits (queued) signals, which should be handled in order
430                 startThread();
431             }
432             QCoreApplication::postEvent(this, new QEvent(QEvent::MaxUser), -1);
433             (void) QEventLoop().exec();
434             break;
435         }
436         default:
437             break;
438         }
439         return QObject::event(event);
440     }
441 };
442
443 void tst_QCoreApplication::deliverInDefinedOrder()
444 {
445     int argc = 1;
446     char *argv[] = { "tst_qcoreapplication" };
447     QCoreApplication app(argc, argv);
448
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));
453
454     QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
455     app.exec();
456 }
457 #endif // QT_NO_QTHREAD
458
459 void tst_QCoreApplication::applicationPid()
460 {
461     QVERIFY(QCoreApplication::applicationPid() > 0);
462 }
463
464 QT_BEGIN_NAMESPACE
465 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
466 QT_END_NAMESPACE
467
468 class GlobalPostedEventsCountObject : public QObject
469 {
470     Q_OBJECT
471
472 public:
473     QList<int> globalPostedEventsCount;
474
475     bool event(QEvent *event)
476     {
477         if (event->type() == QEvent::User)
478             globalPostedEventsCount.append(qGlobalPostedEventsCount());
479         return QObject::event(event);
480     }
481 };
482
483 void tst_QCoreApplication::globalPostedEventsCount()
484 {
485     int argc = 1;
486     char *argv[] = { "tst_qcoreapplication" };
487     QCoreApplication app(argc, argv);
488
489     QCoreApplication::sendPostedEvents();
490     QCOMPARE(qGlobalPostedEventsCount(), 0u);
491
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);
499
500     QCoreApplication::sendPostedEvents();
501     QCOMPARE(qGlobalPostedEventsCount(), 0u);
502
503     QList<int> expected = QList<int>()
504                           << 4
505                           << 3
506                           << 2
507                           << 1
508                           << 0;
509     QCOMPARE(x.globalPostedEventsCount, expected);
510 }
511
512 class ProcessEventsAlwaysSendsPostedEventsObject : public QObject
513 {
514 public:
515     int counter;
516
517     inline ProcessEventsAlwaysSendsPostedEventsObject()
518         : counter(0)
519     { }
520
521     bool event(QEvent *event)
522     {
523         if (event->type() == QEvent::User)
524             ++counter;
525         return QObject::event(event);
526     }
527 };
528
529 void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
530 {
531     int argc = 1;
532     char *argv[] = { "tst_qcoreapplication" };
533     QCoreApplication app(argc, argv);
534
535     ProcessEventsAlwaysSendsPostedEventsObject object;
536     QTime t;
537     t.start();
538     int i = 1;
539     do {
540         QCoreApplication::postEvent(&object, new QEvent(QEvent::User));
541         QCoreApplication::processEvents();
542         QCOMPARE(object.counter, i);
543         ++i;
544     } while (t.elapsed() < 1000);
545 }
546
547 void tst_QCoreApplication::reexec()
548 {
549     int argc = 1;
550     char *argv[] = { "tst_qcoreapplication" };
551     QCoreApplication app(argc, argv);
552
553     // exec once
554     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
555     QCOMPARE(app.exec(), 0);
556
557     // and again
558     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
559     QCOMPARE(app.exec(), 0);
560 }
561
562 void tst_QCoreApplication::execAfterExit()
563 {
564     int argc = 1;
565     char *argv[] = { "tst_qcoreapplication" };
566     QCoreApplication app(argc, argv);
567
568     app.exit(1);
569     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
570     QCOMPARE(app.exec(), 0);
571 }
572
573 void tst_QCoreApplication::eventLoopExecAfterExit()
574 {
575     int argc = 1;
576     char *argv[] = { "tst_qcoreapplication" };
577     QCoreApplication app(argc, argv);
578
579     // exec once and exit
580     QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
581     QCOMPARE(app.exec(), 0);
582
583     // and again, but this time using a QEventLoop
584     QEventLoop loop;
585     QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection);
586     QCOMPARE(loop.exec(), 0);
587 }
588
589 QTEST_APPLESS_MAIN(tst_QCoreApplication)
590 #include "tst_qcoreapplication.moc"