QtBase  v6.3.1
tst_qcoreapplication.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29 
30 #include "tst_qcoreapplication.h"
31 
32 #include <QtCore/QtCore>
33 #include <QTest>
34 
35 #include <private/qcoreapplication_p.h>
36 #include <private/qeventloop_p.h>
37 #include <private/qthread_p.h>
38 
39 #ifdef Q_OS_WIN
40 #include <QtCore/qt_windows.h>
41 #endif
42 
44 
45 class EventSpy : public QObject
46 {
47  Q_OBJECT
48 
49 public:
51  bool eventFilter(QObject *, QEvent *event) override
52  {
53  recordedEvents.append(event->type());
54  return false;
55  }
56 };
57 
59 {
60  Q_OBJECT
61 public:
63  bool event(QEvent *event) override
64  {
65  if (event->type() != QEvent::Type(QEvent::User + 1))
66  return QObject::event(event);
67  recordedEvents.append(event->type());
70  moveToThread(0);
71  return true;
72  }
73 };
74 
75 class Thread : public QDaemonThread
76 {
77  void run() override
78  {
80  QVERIFY(!data->requiresCoreApplication); // daemon thread
81  data->requiresCoreApplication = requiresCoreApplication;
82  QThread::run();
83  }
84 
85 public:
88 };
89 
90 void tst_QCoreApplication::sendEventsOnProcessEvents()
91 {
92  int argc = 1;
93  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
94  TestApplication app(argc, argv);
95 
96  EventSpy spy;
98 
101  QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
102 }
103 
104 void tst_QCoreApplication::getSetCheck()
105 {
106  // do not crash
108  v = QLatin1String("3.0.0 prerelease 1");
111 
112  // Test the property
113  {
114  int argc = 1;
115  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
116  TestApplication app(argc, argv);
117  QCOMPARE(app.property("applicationVersion").toString(), v);
118  }
119  v = QString();
122 }
123 
124 void tst_QCoreApplication::qAppName()
125 {
126 #ifdef QT_QGUIAPPLICATIONTEST
127  const char* appName = "tst_qguiapplication";
128 #else
129  const char* appName = "tst_qcoreapplication";
130 #endif
131 
132  {
133  int argc = 1;
134  char *argv[] = { const_cast<char*>(appName) };
135  TestApplication app(argc, argv);
136  QCOMPARE(::qAppName(), QString::fromLatin1(appName));
138  }
139  // The application name should still be available after destruction;
140  // global statics often rely on this.
142 
143  // Setting the appname before creating the application should work (QTBUG-45283)
144  const QString wantedAppName("my app name");
145  {
146  int argc = 1;
147  char *argv[] = { const_cast<char*>(appName) };
149  TestApplication app(argc, argv);
150  QCOMPARE(::qAppName(), QString::fromLatin1(appName));
152  }
154 
155  // Restore to initial value
158 }
159 
160 void tst_QCoreApplication::qAppVersion()
161 {
162 #if defined(Q_OS_WIN)
163  const char appVersion[] = "1.2.3.4";
164 #elif defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
165  const char appVersion[] = "1.2.3";
166 #else
167  const char appVersion[] = "";
168 #endif
169 
170  {
171  int argc = 0;
172  char *argv[] = { nullptr };
173  TestApplication app(argc, argv);
175  }
176  // The application version should still be available after destruction
178 
179  // Setting the appversion before creating the application should work
180  const QString wantedAppVersion("0.0.1");
181  {
182  int argc = 0;
183  char *argv[] = { nullptr };
184  QCoreApplication::setApplicationVersion(wantedAppVersion);
185  TestApplication app(argc, argv);
186  QCOMPARE(QCoreApplication::applicationVersion(), wantedAppVersion);
187  }
188  QCOMPARE(QCoreApplication::applicationVersion(), wantedAppVersion);
189 
190  // Restore to initial value
193 }
194 
195 void tst_QCoreApplication::argc()
196 {
197  {
198  int argc = 1;
199  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
200  TestApplication app(argc, argv);
201  QCOMPARE(argc, 1);
202  QCOMPARE(app.arguments().count(), 1);
203  }
204 
205  {
206  int argc = 4;
207  char *argv[] = { const_cast<char*>(QTest::currentAppName()),
208  const_cast<char*>("arg1"),
209  const_cast<char*>("arg2"),
210  const_cast<char*>("arg3") };
211  TestApplication app(argc, argv);
212  QCOMPARE(argc, 4);
213  QCOMPARE(app.arguments().count(), 4);
214  }
215 
216  {
217  int argc = 0;
218  char **argv = 0;
219  TestApplication app(argc, argv);
220  QCOMPARE(argc, 0);
221  QCOMPARE(app.arguments().count(), 0);
222  }
223 
224  {
225  int argc = 2;
226  char *argv[] = { const_cast<char*>(QTest::currentAppName()),
227  const_cast<char*>("-qmljsdebugger=port:3768,block") };
228  TestApplication app(argc, argv);
229  QCOMPARE(argc, 1);
230  QCOMPARE(app.arguments().count(), 1);
231  }
232 }
233 
234 class EventGenerator : public QObject
235 {
236  Q_OBJECT
237 
238 public:
240 
241  bool event(QEvent *e) override
242  {
243  if (e->type() == QEvent::MaxUser) {
245  } else if (e->type() <= QEvent::User + 999) {
246  // post a new event in response to this posted event
247  int offset = e->type() - QEvent::User;
248  offset = (offset * 10 + offset % 10);
250  }
251 
252  return QObject::event(e);
253  }
254 };
255 
256 void tst_QCoreApplication::postEvent()
257 {
258  int argc = 1;
259  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
260  TestApplication app(argc, argv);
261 
262  EventSpy spy;
263  EventGenerator odd, even;
264  odd.other = &even;
265  odd.installEventFilter(&spy);
266  even.other = &odd;
267  even.installEventFilter(&spy);
268 
271 
274 
277 
278  QList<int> expected;
279  expected << QEvent::User + 4
280  << QEvent::User + 3
281  << QEvent::User + 1
282  << QEvent::User + 2
283  << QEvent::User + 6
284  << QEvent::User + 5;
285 
287  // live lock protection ensures that we only send the initial events
288  QCOMPARE(spy.recordedEvents, expected);
289 
290  expected.clear();
291  expected << QEvent::User + 66
292  << QEvent::User + 55
293  << QEvent::User + 44
294  << QEvent::User + 33
295  << QEvent::User + 22
296  << QEvent::User + 11;
297 
298  spy.recordedEvents.clear();
300  // expect next sequence events
301  QCOMPARE(spy.recordedEvents, expected);
302 
303  // have the generators call sendPostedEvents() on each other in
304  // response to an event
306  QCoreApplication::postEvent(&even, new QEvent(QEvent::MaxUser), INT_MAX);
307 
308  expected.clear();
309  expected << int(QEvent::MaxUser)
310  << int(QEvent::MaxUser)
311  << QEvent::User + 555
312  << QEvent::User + 333
313  << QEvent::User + 111
314  << QEvent::User + 666
315  << QEvent::User + 444
316  << QEvent::User + 222;
317 
318  spy.recordedEvents.clear();
320  QCOMPARE(spy.recordedEvents, expected);
321 
322  expected.clear();
323  expected << QEvent::User + 6666
324  << QEvent::User + 5555
325  << QEvent::User + 4444
326  << QEvent::User + 3333
327  << QEvent::User + 2222
328  << QEvent::User + 1111;
329 
330  spy.recordedEvents.clear();
332  QCOMPARE(spy.recordedEvents, expected);
333 
334  // no more events
335  expected.clear();
336  spy.recordedEvents.clear();
338  QCOMPARE(spy.recordedEvents, expected);
339 }
340 
341 void tst_QCoreApplication::removePostedEvents()
342 {
343  int argc = 1;
344  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
345  TestApplication app(argc, argv);
346 
347  EventSpy spy;
348  QObject one, two;
349  one.installEventFilter(&spy);
350  two.installEventFilter(&spy);
351 
352  QList<int> expected;
353 
354  // remove all events for one object
362  expected << QEvent::User + 4
363  << QEvent::User + 5
364  << QEvent::User + 6;
366  QCOMPARE(spy.recordedEvents, expected);
367  spy.recordedEvents.clear();
368  expected.clear();
369 
370  // remove all events for all objects
379  QVERIFY(spy.recordedEvents.isEmpty());
380 
381  // remove a specific type of event for one object
391  expected << QEvent::User + 14
392  << QEvent::User + 15
393  << QEvent::User + 16
394  << QEvent::User + 17;
395  QCOMPARE(spy.recordedEvents, expected);
396  spy.recordedEvents.clear();
397  expected.clear();
398 
399  // remove a specific type of event for all objects
408  expected << QEvent::User + 19
409  << QEvent::User + 19
410  << QEvent::User + 21
411  << QEvent::User + 21;
412  QCOMPARE(spy.recordedEvents, expected);
413  spy.recordedEvents.clear();
414  expected.clear();
415 }
416 
417 #if QT_CONFIG(thread)
418 class DeliverInDefinedOrderThread : public QThread
419 {
420  Q_OBJECT
421 
422 public:
423  DeliverInDefinedOrderThread()
424  : QThread()
425  { }
426 
427 signals:
428  void progress(int);
429 
430 protected:
431  void run() override
432  {
433  emit progress(1);
434  emit progress(2);
435  emit progress(3);
436  emit progress(4);
437  emit progress(5);
438  emit progress(6);
439  emit progress(7);
440  }
441 };
442 
443 class DeliverInDefinedOrderObject : public QObject
444 {
445  Q_OBJECT
446 
448  int count;
449  int startCount;
450  int loopLevel;
451 
452 public:
453  DeliverInDefinedOrderObject(QObject *parent)
454  : QObject(parent), thread(0), count(0), startCount(0), loopLevel(0)
455  { }
456 
457 signals:
458  void done();
459 
460 public slots:
461  void startThread()
462  {
463  QVERIFY(!thread);
464  thread = new DeliverInDefinedOrderThread();
465  connect(thread, SIGNAL(progress(int)), this, SLOT(threadProgress(int)));
466  connect(thread, SIGNAL(finished()), this, SLOT(threadFinished()));
467  connect(thread, SIGNAL(destroyed()), this, SLOT(threadDestroyed()));
468  thread->start();
469 
471  }
472 
473  void threadProgress(int v)
474  {
475  ++count;
476  QCOMPARE(v, count);
477 
479  }
480 
481  void threadFinished()
482  {
483  QCOMPARE(count, 7);
484  count = 0;
485  thread->deleteLater();
486 
488  }
489 
490  void threadDestroyed()
491  {
492  if (++startCount < 20)
493  startThread();
494  else
495  emit done();
496  }
497 
498 public:
499  bool event(QEvent *event) override
500  {
501  switch (event->type()) {
502  case QEvent::User:
503  {
504  ++loopLevel;
505  if (loopLevel == 2) {
506  // Ready. Starts a thread that emits (queued) signals, which should be handled in order
507  startThread();
508  }
510  (void) QEventLoop().exec();
511  break;
512  }
513  default:
514  break;
515  }
516  return QObject::event(event);
517  }
518 };
519 
520 void tst_QCoreApplication::deliverInDefinedOrder()
521 {
522  int argc = 1;
523  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
524  TestApplication app(argc, argv);
525 
526  DeliverInDefinedOrderObject obj(&app);
527  // causes sendPostedEvents() to recurse twice
530 
531  QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit()));
532  app.exec();
533 }
534 #endif // QT_CONFIG(thread)
535 
536 void tst_QCoreApplication::applicationPid()
537 {
539 }
540 
542 Q_CORE_EXPORT uint qGlobalPostedEventsCount();
544 
546 {
547  Q_OBJECT
548 
549 public:
551 
552  bool event(QEvent *event) override
553  {
554  if (event->type() == QEvent::User)
556  return QObject::event(event);
557  }
558 };
559 
560 void tst_QCoreApplication::globalPostedEventsCount()
561 {
562  int argc = 1;
563  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
564  TestApplication app(argc, argv);
565 
568 
576 
579 
580  QList<int> expected = QList<int>()
581  << 4
582  << 3
583  << 2
584  << 1
585  << 0;
586  QCOMPARE(x.globalPostedEventsCount, expected);
587 }
588 
590 {
591 public:
592  int counter;
593 
595  : counter(0)
596  { }
597 
598  bool event(QEvent *event) override
599  {
600  if (event->type() == QEvent::User)
601  ++counter;
602  return QObject::event(event);
603  }
604 };
605 
606 void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents()
607 {
608  int argc = 1;
609  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
610  TestApplication app(argc, argv);
611 
614  t.start();
615  int i = 1;
616  do {
619  QCOMPARE(object.counter, i);
620  ++i;
621  } while (t.elapsed() < 1000);
622 }
623 
624 #ifdef Q_OS_WIN
625 void tst_QCoreApplication::sendPostedEventsInNativeLoop()
626 {
627  int argc = 1;
628  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
629  TestApplication app(argc, argv);
630 
631  bool signalReceived = false;
632 
633  // Post a message to the queue
634  QMetaObject::invokeMethod(this, [&signalReceived]() {
635  signalReceived = true;
637 
638  QElapsedTimer elapsedTimer;
639  elapsedTimer.start();
640 
641  // Exec own message loop
642  MSG msg;
643  forever {
644  if (elapsedTimer.hasExpired(3000) || signalReceived)
645  break;
646 
647  if (!::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
648  QThread::msleep(100);
649  continue;
650  }
651 
652  ::TranslateMessage(&msg);
653  ::DispatchMessage(&msg);
654  }
655 
656  QVERIFY(signalReceived);
657 }
658 #endif // Q_OS_WIN
659 
660 class QuitBlocker : public QObject
661 {
662  Q_OBJECT
663 
664 public:
665  bool eventFilter(QObject *, QEvent *event) override
666  {
667  if (event->type() == QEvent::Quit) {
668  event->ignore();
669  return true;
670  }
671 
672  return false;
673  }
674 };
675 
676 void tst_QCoreApplication::quit()
677 {
678  TestApplication::quit(); // Should not do anything
679 
680  {
681  int argc = 1;
682  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
683  TestApplication app(argc, argv);
684 
685  EventSpy spy;
687 
688  {
689  QTimer::singleShot(0, &app, SLOT(quit()));
690  app.exec();
691  QVERIFY(spy.recordedEvents.contains(QEvent::Quit));
692  }
693 
694  spy.recordedEvents.clear();
695 
696  {
697  QTimer::singleShot(0, qApp, SLOT(quit()));
698  app.exec();
699  QVERIFY(spy.recordedEvents.contains(QEvent::Quit));
700  }
701 
702  spy.recordedEvents.clear();
703 
704  {
706  app.exec();
707  QVERIFY(spy.recordedEvents.contains(QEvent::Quit));
708  }
709 
710  spy.recordedEvents.clear();
711 
712  {
713  QuitBlocker quitBlocker;
714  app.installEventFilter(&quitBlocker);
715 
718  app.exec();
719  QVERIFY(!spy.recordedEvents.contains(QEvent::Quit));
720  }
721  }
722 
723  TestApplication::quit(); // Should not do anything
724 }
725 
726 void tst_QCoreApplication::reexec()
727 {
728  int argc = 1;
729  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
730  TestApplication app(argc, argv);
731 
732  // exec once
734  QCOMPARE(app.exec(), 0);
735 
736  // and again
738  QCOMPARE(app.exec(), 0);
739 }
740 
741 void tst_QCoreApplication::execAfterExit()
742 {
743  int argc = 1;
744  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
745  TestApplication app(argc, argv);
746 
747  app.exit(1);
749  QCOMPARE(app.exec(), 0);
750 }
751 
752 void tst_QCoreApplication::eventLoopExecAfterExit()
753 {
754  int argc = 1;
755  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
756  TestApplication app(argc, argv);
757 
758  // exec once and exit
760  QCOMPARE(app.exec(), 0);
761 
762  // and again, but this time using a QEventLoop
763  QEventLoop loop;
765  QCOMPARE(loop.exec(), 0);
766 }
767 
769 public:
771  bool processEvents(QEventLoop::ProcessEventsFlags) override {
772  visited = true;
773  emit awake();
775  return false;
776  }
779  void registerTimer(int , qint64 , Qt::TimerType, QObject *) override {}
780  bool unregisterTimer(int ) override { return false; }
781  bool unregisterTimers(QObject *) override { return false; }
783  int remainingTime(int) override { return 0; }
784  void wakeUp() override {}
785  void interrupt() override {}
786 
787 #ifdef Q_OS_WIN
788  bool registerEventNotifier(QWinEventNotifier *) { return false; }
789  void unregisterEventNotifier(QWinEventNotifier *) { }
790 #endif
791 
792  bool visited;
793 };
794 
795 void tst_QCoreApplication::customEventDispatcher()
796 {
797  // there should be no ED yet
801  // the new ED should be set
803  // test the alternative API of QAbstractEventDispatcher
805  QPointer<DummyEventDispatcher> weak_ed(ed);
806  QVERIFY(!weak_ed.isNull());
807  {
808  int argc = 1;
809  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
810  TestApplication app(argc, argv);
811  // instantiating app should not overwrite the ED
814  app.exec();
815  // the custom ED has really been used?
816  QVERIFY(ed->visited);
817  }
818  // ED has been deleted?
819  QVERIFY(weak_ed.isNull());
820 }
821 
822 class JobObject : public QObject
823 {
824  Q_OBJECT
825 public:
826 
827  explicit JobObject(QEventLoop *loop, QObject *parent = nullptr)
828  : QObject(parent), locker(loop)
829  {
830  QTimer::singleShot(1000, this, SLOT(timeout()));
831  }
832 
833  explicit JobObject(QObject *parent = nullptr)
834  : QObject(parent)
835  {
836  QTimer::singleShot(1000, this, SLOT(timeout()));
837  }
838 
839 public slots:
841  {
842  new JobObject();
843  }
844 
845 private slots:
846  void timeout()
847  {
848  emit done();
849  deleteLater();
850  }
851 
852 signals:
853  void done();
854 
855 private:
856  QEventLoopLocker locker;
857 };
858 
859 class QuitTester : public QObject
860 {
861  Q_OBJECT
862 public:
864  : QObject(parent)
865  {
866  QTimer::singleShot(0, this, SLOT(doTest()));
867  }
868 
869 private slots:
870  void doTest()
871  {
873 
874  {
875  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
876  // Test with a lock active so that the refcount doesn't drop to zero during these tests, causing a quit.
877  // (until we exit the scope)
878  QEventLoopLocker locker;
879 
880  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
881 
882  JobObject *job1 = new JobObject(this);
883 
884  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
885 
886  delete job1;
887 
888  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
889 
890  job1 = new JobObject(this);
891 
892  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
893 
894  JobObject *job2 = new JobObject(this);
895 
896  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
897 
898  delete job1;
899 
900  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 2);
901 
902  JobObject *job3 = new JobObject(job2);
903  Q_UNUSED(job3);
904 
905  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 3);
906 
907  JobObject *job4 = new JobObject(job2);
908  Q_UNUSED(job4);
909 
910  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 4);
911 
912  delete job2;
913 
914  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 1);
915 
916  }
917  QCOMPARE(privateClass->quitLockRef.loadRelaxed(), 0);
918  }
919 };
920 
921 void tst_QCoreApplication::testQuitLock()
922 {
923  int argc = 1;
924  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
925  TestApplication app(argc, argv);
926 
927  QuitTester tester;
928  app.exec();
929 }
930 
931 
932 void tst_QCoreApplication::QTBUG31606_QEventDestructorDeadLock()
933 {
934  class MyEvent : public QEvent
935  { public:
936  MyEvent() : QEvent(QEvent::Type(QEvent::User + 1)) {}
937  ~MyEvent() {
939  }
940  };
941 
942  int argc = 1;
943  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
944  TestApplication app(argc, argv);
945 
946  EventSpy spy;
948 
949  QCoreApplication::postEvent(&app, new MyEvent);
951  QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
952  QVERIFY(!spy.recordedEvents.contains(QEvent::User + 2));
954  QVERIFY(spy.recordedEvents.contains(QEvent::User + 2));
955 }
956 
957 // this is almost identical to sendEventsOnProcessEvents
958 void tst_QCoreApplication::applicationEventFilters_mainThread()
959 {
960  int argc = 1;
961  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
962  TestApplication app(argc, argv);
963 
964  EventSpy spy;
966 
968  QTimer::singleShot(10, &app, SLOT(quit()));
969  app.exec();
970  QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
971 }
972 
973 void tst_QCoreApplication::applicationEventFilters_auxThread()
974 {
975  int argc = 1;
976  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
977  TestApplication app(argc, argv);
978  QThread thread;
979  ThreadedEventReceiver receiver;
980  receiver.moveToThread(&thread);
981 
982  EventSpy spy;
984 
985  // this is very similar to sendEventsOnProcessEvents
987  QTimer::singleShot(1000, &app, SLOT(quit()));
988  thread.start();
989  app.exec();
990  QVERIFY(thread.wait(1000));
992  QVERIFY(!spy.recordedEvents.contains(QEvent::User + 1));
993 }
994 
995 void tst_QCoreApplication::threadedEventDelivery_data()
996 {
997  QTest::addColumn<bool>("requiresCoreApplication");
998  QTest::addColumn<bool>("createCoreApplication");
999  QTest::addColumn<bool>("eventsReceived");
1000 
1001  // invalid combination:
1002  //QTest::newRow("default-without-coreapp") << true << false << false;
1003  QTest::newRow("default") << true << true << true;
1004  QTest::newRow("independent-without-coreapp") << false << false << true;
1005  QTest::newRow("independent-with-coreapp") << false << true << true;
1006 }
1007 
1008 // posts the event before the QCoreApplication is destroyed, starts thread after
1009 void tst_QCoreApplication::threadedEventDelivery()
1010 {
1011  QFETCH(bool, requiresCoreApplication);
1012  QFETCH(bool, createCoreApplication);
1013  QFETCH(bool, eventsReceived);
1014 
1015  int argc = 1;
1016  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
1017  QScopedPointer<TestApplication> app(createCoreApplication ? new TestApplication(argc, argv) : 0);
1018 
1019  Thread thread;
1020  thread.requiresCoreApplication = requiresCoreApplication;
1021  ThreadedEventReceiver receiver;
1022  receiver.moveToThread(&thread);
1024 
1025  thread.start();
1026  QVERIFY(thread.wait(1000));
1027  QCOMPARE(receiver.recordedEvents.contains(QEvent::User + 1), eventsReceived);
1028 
1029 }
1030 
1031 void tst_QCoreApplication::testTrWithPercantegeAtTheEnd()
1032 {
1033  QCoreApplication::translate("testcontext", "this will crash%", "testdisamb", 3);
1034 }
1035 
1036 #if QT_CONFIG(library)
1037 void tst_QCoreApplication::addRemoveLibPaths()
1038 {
1039  QStringList paths = QCoreApplication::libraryPaths();
1040  if (paths.isEmpty())
1041  QSKIP("Cannot add/remove library paths if there are none.");
1042 
1043  QString currentDir = QDir().absolutePath();
1044  QCoreApplication::addLibraryPath(currentDir);
1045  QVERIFY(QCoreApplication::libraryPaths().contains(currentDir));
1046 
1047  QCoreApplication::removeLibraryPath(paths[0]);
1048  QVERIFY(!QCoreApplication::libraryPaths().contains(paths[0]));
1049 
1050  int argc = 1;
1051  char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
1052  TestApplication app(argc, argv);
1053 
1054  // If libraryPaths only contains currentDir, neither will be in libraryPaths now.
1055  if (paths.length() != 1 && currentDir != paths[0]) {
1056  // Check that modifications stay alive across the creation of an application.
1057  QVERIFY(QCoreApplication::libraryPaths().contains(currentDir));
1058  QVERIFY(!QCoreApplication::libraryPaths().contains(paths[0]));
1059  }
1060 
1061  QStringList replace;
1062  replace << currentDir << paths[0];
1063  QCoreApplication::setLibraryPaths(replace);
1064  QCOMPARE(QCoreApplication::libraryPaths(), replace);
1065 }
1066 #endif
1067 
1068 static void createQObjectOnDestruction()
1069 {
1070  // Make sure that we can create a QObject after the last QObject has been
1071  // destroyed (especially after QCoreApplication has).
1072  //
1073  // Before the fixes, this would cause a dangling pointer dereference. If
1074  // the problem comes back, it's possible that the following causes no
1075  // effect.
1076  QObject obj;
1077  obj.thread()->setProperty("testing", 1);
1078 }
1079 Q_DESTRUCTOR_FUNCTION(createQObjectOnDestruction)
1080 
1081 #ifndef QT_QGUIAPPLICATIONTEST
1083 #endif
1084 
1085 #include "tst_qcoreapplication.moc"
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
const char msg[]
Definition: arch.cpp:46
int remainingTime(int) override
void registerTimer(int, qint64, Qt::TimerType, QObject *) override
QList< TimerInfo > registeredTimers(QObject *) const override
void registerSocketNotifier(QSocketNotifier *) override
void unregisterSocketNotifier(QSocketNotifier *) override
bool unregisterTimer(int) override
bool unregisterTimers(QObject *) override
bool processEvents(QEventLoop::ProcessEventsFlags) override
bool event(QEvent *e) override
QList< int > recordedEvents
bool eventFilter(QObject *, QEvent *event) override
bool event(QEvent *event) override
JobObject(QEventLoop *loop, QObject *parent=nullptr)
JobObject(QObject *parent=nullptr)
void done()
The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
static int exec()
T loadRelaxed() const noexcept
Definition: qbasicatomic.h:90
The QCoreApplication class provides an event loop for Qt applications without UI.
static QAbstractEventDispatcher * eventDispatcher()
static void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
static void removePostedEvents(QObject *receiver, int eventType=0)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
QString applicationVersion
the version of this application
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static void setApplicationName(const QString &application)
static qint64 applicationPid() Q_DECL_CONST_FUNCTION
static void setApplicationVersion(const QString &version)
static QStringList arguments()
QString applicationName
the name of this application
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
static void exit(int retcode=0)
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:55
QString absolutePath() const
Definition: qdir.cpp:660
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:49
void start() noexcept
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ MaxUser
Definition: qcoreevent.h:301
@ Quit
Definition: qcoreevent.h:92
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:50
int exec(ProcessEventsFlags flags=AllEvents)
Definition: qeventloop.cpp:162
The QEventLoopLocker class provides a means to quit an event loop when it is no longer needed.
Definition: qeventloop.h:91
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
bool isEmpty() const noexcept
Definition: qlist.h:418
void append(parameter_type t)
Definition: qlist.h:469
void clear()
Definition: qlist.h:445
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
void installEventFilter(QObject *filterObj)
Definition: qobject.cpp:2235
QObject * parent() const
Definition: qobject.h:409
void moveToThread(QThread *thread)
Definition: qobject.cpp:1572
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
QThread * thread() const
Definition: qobject.cpp:1527
QVariant property(const char *name) const
Definition: qobject.cpp:4118
void destroyed(QObject *=nullptr)
void deleteLater()
Definition: qobject.cpp:2319
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:368
The QPointer class is a template class that provides guarded pointers to QObject.
Definition: qpointer.h:54
bool isNull() const
Definition: qpointer.h:87
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
The QStringList class provides a list of strings.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition: qthread.cpp:908
void start(Priority=InheritPriority)
Definition: qthread.cpp:836
virtual void run()
Definition: qthread.cpp:826
static QThread * currentThread()
Definition: qthread.cpp:879
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition: qthread.cpp:863
static void msleep(unsigned long)
void quit()
Definition: qthread.cpp:848
bool singleShot
whether the timer is a single-shot timer
Definition: qtimer.h:60
QString toString() const
Definition: qvariant.cpp:1416
The QWinEventNotifier class provides support for the Windows Wait functions.
bool eventFilter(QObject *, QEvent *event) override
QuitTester(QObject *parent=nullptr)
bool requiresCoreApplication
bool event(QEvent *event) override
[user-class]
Definition: user.h:59
double e
set contains("Julia")
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QCOMPARE(spy.count(), 1)
#define NULL
Definition: ftobjs.h:61
#define true
Definition: ftrandom.c:51
#define forever
Definition: ftrandom.c:53
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT const char * currentAppName()
Definition: qtestcase.cpp:2737
TimerType
Definition: qnamespace.h:1689
@ QueuedConnection
Definition: qnamespace.h:1307
def startCount(c, text)
Definition: qlocalexml.py:65
#define QString()
Definition: parse-defines.h:51
void
Definition: png.h:1080
#define qApp
QT_BEGIN_NAMESPACE bool done
unsigned int uint
Definition: qglobal.h:334
long long qint64
Definition: qglobal.h:298
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLenum GLsizei count
GLuint object
[3]
GLbitfield GLuint64 timeout
[4]
GLsizei const GLuint * paths
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLuint counter
struct _cl_event * event
Definition: qopenglext.h:2998
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
#define QTEST_APPLESS_MAIN(TestObject)
Definition: qtest.h:632
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
#define signals
Definition: qtmetamacros.h:77
#define emit
Definition: qtmetamacros.h:85
struct tagMSG MSG
Q_UNUSED(salary)
[21]
QApplication app(argc, argv)
[0]
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Definition: moc.h:48
QT_BEGIN_NAMESPACE Q_CORE_EXPORT uint qGlobalPostedEventsCount()
QCoreApplication TestApplication
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent