source: trunk/src/testlib/qtestcase.cpp@ 353

Last change on this file since 353 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 62.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtTest module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "QtTest/qtestcase.h"
43#include "QtTest/qtestassert.h"
44
45#include <QtCore/qbytearray.h>
46#include <QtCore/qmetaobject.h>
47#include <QtCore/qobject.h>
48#include <QtCore/qstringlist.h>
49#include <QtCore/qvector.h>
50#include <QtCore/qvarlengtharray.h>
51#include <QtCore/qcoreapplication.h>
52#include <QtCore/qfile.h>
53#include <QtCore/qfileinfo.h>
54#include <QtCore/qdir.h>
55#include <QtCore/qprocess.h>
56#include <QtCore/qdebug.h>
57
58#include "QtTest/private/qtestlog_p.h"
59#include "QtTest/private/qtesttable_p.h"
60#include "QtTest/qtestdata.h"
61#include "QtTest/private/qtestresult_p.h"
62#include "QtTest/private/qsignaldumper_p.h"
63#include "QtTest/private/qbenchmark_p.h"
64#include "3rdparty/cycle_p.h"
65
66#include <stdarg.h>
67#include <stdio.h>
68#include <stdlib.h>
69
70#ifdef Q_OS_WIN
71#include <windows.h> // for Sleep
72#endif
73#ifdef Q_OS_UNIX
74#include <time.h>
75#endif
76
77#ifdef Q_WS_MAC
78#include <Carbon/Carbon.h> // for SetFrontProcess
79#ifdef QT_MAC_USE_COCOA
80#include <IOKit/pwr_mgt/IOPMLib.h>
81#else
82#include <Security/AuthSession.h>
83#endif
84#undef verify
85#endif
86
87QT_BEGIN_NAMESPACE
88
89/*!
90 \namespace QTest
91 \inmodule QtTest
92
93 \brief The QTest namespace contains all the functions and
94 declarations that are related to the QTestLib tool.
95
96 Please refer to the \l{QTestLib Manual} documentation for information on
97 how to write unit tests.
98*/
99
100/*! \macro QVERIFY(condition)
101
102 \relates QTest
103
104 The QVERIFY() macro checks whether the \a condition is true or not. If it is
105 true, execution continues. If not, a failure is recorded in the test log
106 and the test won't be executed further.
107
108 \bold {Note:} This macro can only be used in a test function that is invoked
109 by the test framework.
110
111 Example:
112 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 0
113
114 \sa QCOMPARE()
115*/
116
117/*! \macro QVERIFY2(condition, message)
118
119 \relates QTest
120
121 The QVERIFY2() macro behaves exactly like QVERIFY(), except that it outputs
122 a verbose \a message when \a condition is false. The \a message is a plain
123 C string.
124
125 Example:
126 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 1
127
128 \sa QVERIFY(), QCOMPARE()
129*/
130
131/*! \macro QCOMPARE(actual, expected)
132
133 \relates QTest
134
135 The QCOMPARE macro compares an \a actual value to an \a expected value using
136 the equals operator. If \a actual and \a expected are identical, execution
137 continues. If not, a failure is recorded in the test log and the test
138 won't be executed further.
139
140 In the case of comparing floats and doubles, qFuzzyCompare() is used for
141 comparing. This means that comparing to 0 will likely fail. One solution
142 to this is to compare to 1, and add 1 to the produced output.
143
144 QCOMPARE tries to output the contents of the values if the comparison fails,
145 so it is visible from the test log why the comparison failed.
146
147 QCOMPARE is very strict on the data types. Both \a actual and \a expected
148 have to be of the same type, otherwise the test won't compile. This prohibits
149 unspecified behavior from being introduced; that is behavior that usually
150 occurs when the compiler implicitly casts the argument.
151
152 If you use QCOMPARE() to compare two QStringList objects, it will start
153 comparing the objects from the end of the lists.
154
155 For your own classes, you can use \l QTest::toString() to format values for
156 outputting into the test log.
157
158 \note This macro can only be used in a test function that is invoked
159 by the test framework.
160
161 Example:
162 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 2
163
164 \sa QVERIFY(), QTest::toString()
165*/
166
167/*! \macro QFETCH(type, name)
168
169 \relates QTest
170
171 The fetch macro creates a local variable named \a name with the type \a type
172 on the stack. \a name has to match the element name from the test's data.
173 If no such element exists, the test will assert.
174
175 Assuming a test has the following data:
176
177 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 3
178
179 The test data has two elements, a QString called \c aString and an integer
180 called \c expected. To fetch these values in the actual test:
181
182 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 4
183
184 \c aString and \c expected are variables on the stack that are initialized with
185 the current test data.
186
187 \bold {Note:} This macro can only be used in a test function that is invoked
188 by the test framework. The test function must have a _data function.
189*/
190
191/*! \macro QWARN(message)
192
193 \relates QTest
194 \threadsafe
195
196 Appends \a message as a warning to the test log. This macro can be used anywhere
197 in your tests.
198*/
199
200/*! \macro QFAIL(message)
201
202 \relates QTest
203
204 This macro can be used to force a test failure. The test stops
205 executing and the failure \a message is appended to the test log.
206
207 \bold {Note:} This macro can only be used in a test function that is invoked
208 by the test framework.
209
210 Example:
211
212 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 5
213*/
214
215/*! \macro QTEST(actual, testElement)
216
217 \relates QTest
218
219 QTEST() is a convenience macro for \l QCOMPARE() that compares
220 the value \a actual with the element \a testElement from the test's data.
221 If there is no such element, the test asserts.
222
223 Apart from that, QTEST() behaves exactly as \l QCOMPARE().
224
225 Instead of writing:
226
227 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 6
228
229 you can write:
230
231 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 7
232
233 \sa QCOMPARE()
234*/
235
236/*! \macro QSKIP(description, mode)
237
238 \relates QTest
239
240 The QSKIP() macro stops execution of the test without adding a failure to the
241 test log. You can use it to skip tests that wouldn't make sense in the current
242 configuration. The text \a description is appended to the test log and should
243 contain an explanation why the test couldn't be executed. \a mode is a QTest::SkipMode
244 and describes whether to proceed with the rest of the test data or not.
245
246 \bold {Note:} This macro can only be used in a test function that is invoked
247 by the test framework.
248
249 Example:
250 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 8
251
252 \sa QTest::SkipMode
253*/
254
255/*! \macro QEXPECT_FAIL(dataIndex, comment, mode)
256
257 \relates QTest
258
259 The QEXPECT_FAIL() macro marks the next \l QCOMPARE() or \l QVERIFY() as an
260 expected failure. Instead of adding a failure to the test log, an expected
261 failure will be reported.
262
263 If a \l QVERIFY() or \l QCOMPARE() is marked as an expected failure,
264 but passes instead, an unexpected pass (XPASS) is written to the test log.
265
266 The parameter \a dataIndex describes for which entry in the test data the
267 failure is expected. Pass an empty string (\c{""}) if the failure
268 is expected for all entries or if no test data exists.
269
270 \a comment will be appended to the test log for the expected failure.
271
272 \a mode is a \l QTest::TestFailMode and sets whether the test should
273 continue to execute or not.
274
275 \bold {Note:} This macro can only be used in a test function that is invoked
276 by the test framework.
277
278 Example 1:
279 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 9
280
281 In the example above, an expected fail will be written into the test output
282 if the variable \c i is not 42. If the variable \c i is 42, an unexpected pass
283 is written instead. The QEXPECT_FAIL() has no influence on the second QCOMPARE()
284 statement in the example.
285
286 Example 2:
287 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 10
288
289 The above testfunction will not continue executing for the test data
290 entry \c{data27}.
291
292 \sa QTest::TestFailMode, QVERIFY(), QCOMPARE()
293*/
294
295/*! \macro QTEST_MAIN(TestClass)
296
297 \relates QTest
298
299 Implements a main() function that instantiates a QApplication object and
300 the \a TestClass, and executes all tests in the order they were defined.
301 Use this macro to build stand-alone executables.
302
303 Example:
304 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 11
305
306 \sa QTEST_APPLESS_MAIN(), QTest::qExec()
307*/
308
309/*! \macro QTEST_APPLESS_MAIN(TestClass)
310
311 \relates QTest
312
313 Implements a main() function that executes all tests in \a TestClass.
314
315 Behaves like \l QTEST_MAIN(), but doesn't instantiate a QApplication
316 object. Use this macro for really simple stand-alone non-GUI tests.
317
318 \sa QTEST_MAIN()
319*/
320
321/*! \macro QTEST_NOOP_MAIN()
322
323 \relates QTest
324
325 Implements a main() function with a test class that does absolutely nothing.
326 Use this macro to create a test that produces valid test output but just
327 doesn't execute any test, for example in conditional compilations:
328
329 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 12
330
331 \sa QTEST_MAIN()
332*/
333
334/*!
335 \macro QBENCHMARK
336
337 \relates QTest
338
339 This macro is used to measure the performance of code within a test.
340 The code to be benchmarked is contained within a code block following
341 this macro.
342
343 For example:
344
345 \snippet examples/qtestlib/tutorial5/benchmarking.cpp 0
346
347 \sa {QTestLib Manual#Creating a Benchmark}{Creating a Benchmark},
348 {Chapter 5: Writing a Benchmark}{Writing a Benchmark}
349*/
350
351/*! \enum QTest::SkipMode
352
353 This enum describes the modes for skipping tests during execution
354 of the test data.
355
356 \value SkipSingle Skips the current entry in the test table; continues
357 execution of all the other entries in the table.
358
359 \value SkipAll Skips all the entries in the test table; the test won't
360 be executed further.
361
362 \sa QSKIP()
363*/
364
365/*! \enum QTest::TestFailMode
366
367 This enum describes the modes for handling an expected failure of the
368 \l QVERIFY() or \l QCOMPARE() macros.
369
370 \value Abort Aborts the execution of the test. Use this mode when it
371 doesn't make sense to execute the test any further after the
372 expected failure.
373
374 \value Continue Continues execution of the test after the expected failure.
375
376 \sa QEXPECT_FAIL()
377*/
378
379/*! \enum QTest::KeyAction
380
381 This enum describes possible actions for key handling.
382
383 \value Press The key is pressed.
384 \value Release The key is released.
385 \value Click The key is clicked (pressed and released).
386*/
387
388/*! \enum QTest::MouseAction
389
390 This enum describes possible actions for mouse handling.
391
392 \value MousePress A mouse button is pressed.
393 \value MouseRelease A mouse button is released.
394 \value MouseClick A mouse button is clicked (pressed and released).
395 \value MouseDClick A mouse button is double clicked (pressed and released twice).
396 \value MouseMove The mouse pointer has moved.
397*/
398
399/*! \fn void QTest::keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
400
401 \overload
402
403 Simulates clicking of \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
404
405 Example:
406 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 13
407
408 The example above simulates clicking \c a on \c myWidget without
409 any keyboard modifiers and without delay of the test.
410
411 \sa QTest::keyClicks()
412*/
413
414/*! \fn void QTest::keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
415
416 Simulates clicking of \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
417
418 Examples:
419 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 14
420
421 The first example above simulates clicking the \c escape key on \c
422 myWidget without any keyboard modifiers and without delay. The
423 second example simulates clicking \c shift-escape on \c myWidget
424 with a following 200 ms delay of the test.
425
426 \sa QTest::keyClicks()
427*/
428
429/*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
430
431 Sends a Qt key event to \a widget with the given \a key and an associated \a action. Optionally, a keyboard \a modifier can be specified, as well as a \a delay (in milliseconds) of the test before sending the event.
432*/
433
434/*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, char ascii, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
435
436 \overload
437
438 Sends a Qt key event to \a widget with the given key \a ascii and an associated \a action. Optionally, a keyboard \a modifier can be specified, as well as a \a delay (in milliseconds) of the test before sending the event.
439
440*/
441
442/*! \fn void QTest::keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
443
444 Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
445
446 \bold {Note:} At some point you should release the key using \l keyRelease().
447
448 \sa QTest::keyRelease(), QTest::keyClick()
449*/
450
451/*! \fn void QTest::keyPress(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
452
453 \overload
454
455 Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
456
457 \bold {Note:} At some point you should release the key using \l keyRelease().
458
459 \sa QTest::keyRelease(), QTest::keyClick()
460*/
461
462/*! \fn void QTest::keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
463
464 Simulates releasing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
465
466 \sa QTest::keyPress(), QTest::keyClick()
467*/
468
469/*! \fn void QTest::keyRelease(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
470
471 \overload
472
473 Simulates releasing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds.
474
475 \sa QTest::keyClick()
476*/
477
478
479/*! \fn void QTest::keyClicks(QWidget *widget, const QString &sequence, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
480
481 Simulates clicking a \a sequence of keys on a \a
482 widget. Optionally, a keyboard \a modifier can be specified as
483 well as a \a delay (in milliseconds) of the test before each key
484 click.
485
486 Example:
487 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 15
488
489 The example above simulates clicking the sequence of keys
490 representing "hello world" on \c myWidget without any keyboard
491 modifiers and without delay of the test.
492
493 \sa QTest::keyClick()
494*/
495
496/*! \fn void QTest::mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1)
497
498 Simulates pressing a mouse \a button with an optional \a modifier
499 on a \a widget. The position is defined by \a pos; the default
500 position is the center of the widget. If \a delay is specified,
501 the test will wait for the specified amount of milliseconds before
502 the press.
503
504 \sa QTest::mouseRelease(), QTest::mouseClick()
505*/
506
507/*! \fn void QTest::mouseRelease(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1)
508
509 Simulates releasing a mouse \a button with an optional \a modifier
510 on a \a widget. The position of the release is defined by \a pos;
511 the default position is the center of the widget. If \a delay is
512 specified, the test will wait for the specified amount of
513 milliseconds before releasing the button.
514
515 \sa QTest::mousePress(), QTest::mouseClick()
516*/
517
518/*! \fn void QTest::mouseClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1)
519
520 Simulates clicking a mouse \a button with an optional \a modifier
521 on a \a widget. The position of the click is defined by \a pos;
522 the default position is the center of the widget. If \a delay is
523 specified, the test will wait for the specified amount of
524 milliseconds before pressing and before releasing the button.
525
526 \sa QTest::mousePress(), QTest::mouseRelease()
527*/
528
529/*! \fn void QTest::mouseDClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1)
530
531 Simulates double clicking a mouse \a button with an optional \a
532 modifier on a \a widget. The position of the click is defined by
533 \a pos; the default position is the center of the widget. If \a
534 delay is specified, the test will wait for the specified amount of
535 milliseconds before each press and release.
536
537 \sa QTest::mouseClick()
538*/
539
540/*! \fn void QTest::mouseMove(QWidget *widget, QPoint pos = QPoint(), int delay=-1)
541
542 Moves the mouse pointer to a \a widget. If \a pos is not
543 specified, the mouse pointer moves to the center of the widget. If
544 a \a delay (in milliseconds) is given, the test will wait before
545 moving the mouse pointer.
546*/
547
548/*!
549 \fn char *QTest::toString(const T &value)
550
551 Returns a textual representation of \a value. This function is used by
552 \l QCOMPARE() to output verbose information in case of a test failure.
553
554 You can add specializations of this function to your test to enable
555 verbose output.
556
557 \bold {Note:} The caller of toString() must delete the returned data
558 using \c{delete[]}. Your implementation should return a string
559 created with \c{new[]} or qstrdup().
560
561 Example:
562
563 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 16
564
565 The example above defines a toString() specialization for a class
566 called \c MyPoint. Whenever a comparison of two instances of \c
567 MyPoint fails, \l QCOMPARE() will call this function to output the
568 contents of \c MyPoint to the test log.
569
570 \sa QCOMPARE()
571*/
572
573/*!
574 \fn char *QTest::toString(const QLatin1String &string)
575 \overload
576
577 Returns a textual representation of the given \a string.
578*/
579
580/*!
581 \fn char *QTest::toString(const QString &string)
582 \overload
583
584 Returns a textual representation of the given \a string.
585*/
586
587/*!
588 \fn char *QTest::toString(const QByteArray &ba)
589 \overload
590
591 Returns a textual representation of the byte array \a ba.
592
593 \sa QTest::toHexRepresentation()
594*/
595
596/*!
597 \fn char *QTest::toString(const QTime &time)
598 \overload
599
600 Returns a textual representation of the given \a time.
601*/
602
603/*!
604 \fn char *QTest::toString(const QDate &date)
605 \overload
606
607 Returns a textual representation of the given \a date.
608*/
609
610/*!
611 \fn char *QTest::toString(const QDateTime &dateTime)
612 \overload
613
614 Returns a textual representation of the date and time specified by
615 \a dateTime.
616*/
617
618/*!
619 \fn char *QTest::toString(const QChar &character)
620 \overload
621
622 Returns a textual representation of the given \a character.
623*/
624
625/*!
626 \fn char *QTest::toString(const QPoint &point)
627 \overload
628
629 Returns a textual representation of the given \a point.
630*/
631
632/*!
633 \fn char *QTest::toString(const QSize &size)
634 \overload
635
636 Returns a textual representation of the given \a size.
637*/
638
639/*!
640 \fn char *QTest::toString(const QRect &rectangle)
641 \overload
642
643 Returns a textual representation of the given \a rectangle.
644*/
645
646/*!
647 \fn char *QTest::toString(const QUrl &url)
648 \since 4.4
649 \overload
650
651 Returns a textual representation of the given \a url.
652*/
653
654/*!
655 \fn char *QTest::toString(const QPointF &point)
656 \overload
657
658 Returns a textual representation of the given \a point.
659*/
660
661/*!
662 \fn char *QTest::toString(const QSizeF &size)
663 \overload
664
665 Returns a textual representation of the given \a size.
666*/
667
668/*!
669 \fn char *QTest::toString(const QRectF &rectangle)
670 \overload
671
672 Returns a textual representation of the given \a rectangle.
673*/
674
675/*! \fn void QTest::qWait(int ms)
676
677 Waits for \a ms milliseconds. While waiting, events will be processed and
678 your test will stay responsive to user interface events or network communication.
679
680 Example:
681 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 17
682
683 The code above will wait until the network server is responding for a
684 maximum of about 12.5 seconds.
685
686 \sa QTest::qSleep()
687*/
688
689namespace QTest
690{
691 static QObject *currentTestObject = 0;
692
693 struct TestFunction {
694 TestFunction():function(0), data(0) {}
695 ~TestFunction() { delete [] data; }
696 int function;
697 char *data;
698 } testFuncs[512];
699
700 /**
701 * Contains the count of test functions that was supplied
702 * on the command line, if any. Hence, if lastTestFuncIdx is
703 * more than zero, those functions should be run instead of
704 * all appearing in the test case.
705 */
706 static int lastTestFuncIdx = -1;
707
708 static int keyDelay = -1;
709 static int mouseDelay = -1;
710 static int eventDelay = -1;
711 static int keyVerbose = -1;
712
713/*! \internal
714 */
715int qt_snprintf(char *str, int size, const char *format, ...)
716{
717 va_list ap;
718 int res = 0;
719
720 va_start(ap, format);
721 qvsnprintf(str, size, format, ap);
722 va_end(ap);
723 str[size - 1] = '\0';
724
725 char *idx = str;
726 while (*idx) {
727 if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx > 0x7e))
728 *idx = '?';
729 ++idx;
730 }
731 return res;
732}
733
734bool Q_TESTLIB_EXPORT defaultKeyVerbose()
735{
736 if (keyVerbose == -1) {
737 keyVerbose = qgetenv("QTEST_KEYEVENT_VERBOSE").constData() ? 1 : 0;
738 }
739 return keyVerbose == 1;
740}
741
742int defaultEventDelay()
743{
744 if (eventDelay == -1) {
745 if (qgetenv("QTEST_EVENT_DELAY").constData())
746 eventDelay = atoi(qgetenv("QTEST_EVENT_DELAY"));
747 else
748 eventDelay = 0;
749 }
750 return eventDelay;
751}
752
753int Q_TESTLIB_EXPORT defaultMouseDelay()
754{
755 if (mouseDelay == -1) {
756 if (qgetenv("QTEST_MOUSEEVENT_DELAY").constData())
757 mouseDelay = atoi((qgetenv("QTEST_MOUSEEVENT_DELAY")));
758 else
759 mouseDelay = defaultEventDelay();
760 }
761 return mouseDelay;
762}
763
764int Q_TESTLIB_EXPORT defaultKeyDelay()
765{
766 if (keyDelay == -1) {
767 if (qgetenv("QTEST_KEYEVENT_DELAY").constData())
768 keyDelay = atoi(qgetenv("QTEST_KEYEVENT_DELAY").constData());
769 else
770 keyDelay = defaultEventDelay();
771 }
772 return keyDelay;
773}
774
775static bool isValidSlot(const QMetaMethod &sl)
776{
777 if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty()
778 || qstrlen(sl.typeName()) || sl.methodType() != QMetaMethod::Slot)
779 return false;
780 const char *sig = sl.signature();
781 int len = qstrlen(sig);
782 if (len < 2)
783 return false;
784 if (sig[len - 2] != '(' || sig[len - 1] != ')')
785 return false;
786 if (len > 7 && strcmp(sig + (len - 7), "_data()") == 0)
787 return false;
788 if (strcmp(sig, "initTestCase()") == 0 || strcmp(sig, "cleanupTestCase()") == 0
789 || strcmp(sig, "cleanup()") == 0 || strcmp(sig, "init()") == 0)
790 return false;
791 return true;
792}
793
794static void qPrintTestSlots()
795{
796 for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) {
797 QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i);
798 if (isValidSlot(sl))
799 printf("%s\n", sl.signature());
800 }
801}
802
803static int qToInt(char *str)
804{
805 char *pEnd;
806 int l = (int)strtol(str, &pEnd, 10);
807 if (*pEnd != 0) {
808 printf("Invalid numeric parameter: '%s'\n", str);
809 exit(1);
810 }
811 return l;
812}
813
814static void qParseArgs(int argc, char *argv[])
815{
816 lastTestFuncIdx = -1;
817
818 const char *testOptions =
819 " options:\n"
820 " -functions : Returns a list of current testfunctions\n"
821 " -xml : Outputs results as XML document\n"
822 " -lightxml : Outputs results as stream of XML tags\n"
823 " -o filename: Writes all output into a file\n"
824 " -silent : Only outputs warnings and failures\n"
825 " -v1 : Print enter messages for each testfunction\n"
826 " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n"
827 " -vs : Print every signal emitted\n"
828 " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
829 " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n"
830 " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n"
831 " -keyevent-verbose : Turn on verbose messages for keyboard simulation\n"
832 " -maxwarnings n : Sets the maximum amount of messages to output.\n"
833 " 0 means unlimited, default: 2000\n"
834 "\n"
835 " Benchmark related options:\n"
836#ifdef QTESTLIB_USE_VALGRIND
837 " -callgrind : Use callgrind to time benchmarks\n"
838#endif
839#ifdef HAVE_TICK_COUNTER
840 " -tickcounter : Use CPU tick counters to time benchmarks\n"
841#endif
842 " -eventcounter : Counts events received during benchmarks\n"
843 " -minimumvalue n : Sets the minimum acceptable measurement value\n"
844 " -iterations n : Sets the number of accumulation iterations.\n"
845 " -median n : Sets the number of median iterations.\n"
846 " -vb : Print out verbose benchmarking information.\n"
847#ifndef QT_NO_PROCESS
848// Will be enabled when tools are integrated.
849// " -chart : Runs the chart generator after the test. No output is printed to the console\n"
850#endif
851 "\n"
852 " -help : This help\n";
853
854 for (int i = 1; i < argc; ++i) {
855 if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "--help") == 0
856 || strcmp(argv[i], "/?") == 0) {
857 printf(" Usage: %s [options] [testfunction[:testdata]]...\n"
858 " By default, all testfunctions will be run.\n\n"
859 "%s", argv[0], testOptions);
860 exit(0);
861 } else if (strcmp(argv[i], "-functions") == 0) {
862 qPrintTestSlots();
863 exit(0);
864 } else if (strcmp(argv[i], "-xml") == 0) {
865 QTestLog::setLogMode(QTestLog::XML);
866 } else if (strcmp(argv[i], "-lightxml") == 0) {
867 QTestLog::setLogMode(QTestLog::LightXML);
868 } else if (strcmp(argv[i], "-silent") == 0) {
869 QTestLog::setVerboseLevel(-1);
870 } else if (strcmp(argv[i], "-v1") == 0) {
871 QTestLog::setVerboseLevel(1);
872 } else if (strcmp(argv[i], "-v2") == 0) {
873 QTestLog::setVerboseLevel(2);
874 } else if (strcmp(argv[i], "-vs") == 0) {
875 QSignalDumper::startDump();
876 } else if (strcmp(argv[i], "-o") == 0) {
877 if (i + 1 >= argc) {
878 printf("-o needs an extra parameter specifying the filename\n");
879 exit(1);
880 } else {
881 QTestLog::redirectOutput(argv[++i]);
882 }
883 } else if (strcmp(argv[i], "-eventdelay") == 0) {
884 if (i + 1 >= argc) {
885 printf("-eventdelay needs an extra parameter to indicate the delay(ms)\n");
886 exit(1);
887 } else {
888 QTest::eventDelay = qToInt(argv[++i]);
889 }
890 } else if (strcmp(argv[i], "-keydelay") == 0) {
891 if (i + 1 >= argc) {
892 printf("-keydelay needs an extra parameter to indicate the delay(ms)\n");
893 exit(1);
894 } else {
895 QTest::keyDelay = qToInt(argv[++i]);
896 }
897 } else if (strcmp(argv[i], "-mousedelay") == 0) {
898 if (i + 1 >= argc) {
899 printf("-mousedelay needs an extra parameter to indicate the delay(ms)\n");
900 exit(1);
901 } else {
902 QTest::mouseDelay = qToInt(argv[++i]);
903 }
904 } else if (strcmp(argv[i], "-maxwarnings") == 0) {
905 if (i + 1 >= argc) {
906 printf("-maxwarnings needs an extra parameter with the amount of warnings\n");
907 exit(1);
908 } else {
909 QTestLog::setMaxWarnings(qToInt(argv[++i]));
910 }
911 } else if (strcmp(argv[i], "-keyevent-verbose") == 0) {
912 QTest::keyVerbose = 1;
913#ifdef QTESTLIB_USE_VALGRIND
914 } else if (strcmp(argv[i], "-callgrind") == 0) {
915 if (QBenchmarkValgrindUtils::haveValgrind())
916 if (QFileInfo(QDir::currentPath()).isWritable()) {
917 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindParentProcess);
918 } else {
919 printf("WARNING: Current directory not writable. Using the walltime measurer.\n");
920 }
921 else {
922 printf("WARNING: Valgrind not found or too old. Make sure it is installed and in your path. "
923 "Using the walltime measurer.\n");
924 }
925 } else if (strcmp(argv[i], "-callgrindchild") == 0) { // "private" option
926 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess);
927 QBenchmarkGlobalData::current->callgrindOutFileBase =
928 QBenchmarkValgrindUtils::outFileBase();
929#endif
930#ifdef HAVE_TICK_COUNTER
931 } else if (strcmp(argv[i], "-tickcounter") == 0) {
932 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter);
933#endif
934 } else if (strcmp(argv[i], "-eventcounter") == 0) {
935 QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter);
936 } else if (strcmp(argv[i], "-minimumvalue") == 0) {
937 if (i + 1 >= argc) {
938 printf("-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n");
939 exit(1);
940 } else {
941 QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]);
942 }
943 } else if (strcmp(argv[i], "-iterations") == 0) {
944 if (i + 1 >= argc) {
945 printf("-iterations needs an extra parameter to indicate the number of iterations\n");
946 exit(1);
947 } else {
948 QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]);
949 }
950 } else if (strcmp(argv[i], "-median") == 0) {
951 if (i + 1 >= argc) {
952 printf("-median needs an extra parameter to indicate the number of median iterations\n");
953 exit(1);
954 } else {
955 QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]);
956 }
957
958 } else if (strcmp(argv[i], "-vb") == 0) {
959 QBenchmarkGlobalData::current->verboseOutput = true;
960#ifndef QT_NO_PROCESS
961 } else if (strcmp(argv[i], "-chart") == 0) {
962 QBenchmarkGlobalData::current->createChart = true;
963 QTestLog::setLogMode(QTestLog::XML);
964 QTestLog::redirectOutput("results.xml");
965#endif
966 } else if (strcmp(argv[i], "-qws") == 0) {
967 // do nothing
968 } else if (argv[i][0] == '-') {
969 printf("Unknown option: '%s'\n\n%s", argv[i], testOptions);
970 exit(1);
971 } else {
972 int colon = -1;
973 char buf[512], *data=0;
974 int off;
975 for(off = 0; *(argv[i]+off); ++off) {
976 if (*(argv[i]+off) == ':') {
977 colon = off;
978 break;
979 }
980 }
981 if(colon != -1) {
982 data = qstrdup(argv[i]+colon+1);
983 }
984 QTest::qt_snprintf(buf, qMin(512, off + 1), "%s", argv[i]); // copy text before the ':' into buf
985 QTest::qt_snprintf(buf + off, qMin(512 - off, 3), "()"); // append "()"
986 int idx = QTest::currentTestObject->metaObject()->indexOfMethod(buf);
987 if (idx < 0 || !isValidSlot(QTest::currentTestObject->metaObject()->method(idx))) {
988 printf("Unknown testfunction: '%s'\n", buf);
989 printf("Available testfunctions:\n");
990 qPrintTestSlots();
991 exit(1);
992 }
993 ++QTest::lastTestFuncIdx;
994 QTest::testFuncs[QTest::lastTestFuncIdx].function = idx;
995 QTest::testFuncs[QTest::lastTestFuncIdx].data = data;
996 QTEST_ASSERT(QTest::lastTestFuncIdx < 512);
997 }
998 }
999}
1000
1001QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container)
1002{
1003 const int count = container.count();
1004 if (count == 0)
1005 return QBenchmarkResult();
1006
1007 if (count == 1)
1008 return container.at(0);
1009
1010 QList<QBenchmarkResult> containerCopy = container;
1011 qSort(containerCopy);
1012
1013 const int middle = count / 2;
1014
1015 // ### handle even-sized containers here by doing an aritmetic mean of the two middle items.
1016 return containerCopy.at(middle);
1017}
1018
1019struct QTestDataSetter
1020{
1021 QTestDataSetter(QTestData *data)
1022 {
1023 QTestResult::setCurrentTestData(data);
1024 }
1025 ~QTestDataSetter()
1026 {
1027 QTestResult::setCurrentTestData(0);
1028 }
1029};
1030
1031static void qInvokeTestMethodDataEntry(char *slot)
1032{
1033 /* Benchmarking: for each median iteration*/
1034
1035 int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0;
1036
1037 QList<QBenchmarkResult> results;
1038 do {
1039 QBenchmarkTestMethodData::current->beginDataRun();
1040
1041 /* Benchmarking: for each accumulation iteration*/
1042 bool invokeOk;
1043 do {
1044 QTestResult::setCurrentTestLocation(QTestResult::InitFunc);
1045 QMetaObject::invokeMethod(QTest::currentTestObject, "init");
1046 if (QTestResult::skipCurrentTest())
1047 break;
1048
1049 QTestResult::setCurrentTestLocation(QTestResult::Func);
1050
1051 QBenchmarkTestMethodData::current->result = QBenchmarkResult();
1052 QBenchmarkTestMethodData::current->resultAccepted = false;
1053
1054 QBenchmarkGlobalData::current->context.tag =
1055 QLatin1String(
1056 QTestResult::currentDataTag()
1057 ? QTestResult::currentDataTag() : "");
1058
1059 invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot,
1060 Qt::DirectConnection);
1061 if (!invokeOk)
1062 QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__);
1063
1064 QTestResult::setCurrentTestLocation(QTestResult::CleanupFunc);
1065 QMetaObject::invokeMethod(QTest::currentTestObject, "cleanup");
1066 QTestResult::setCurrentTestLocation(QTestResult::NoWhere);
1067
1068 // If this test method has a benchmark, repeat until all measurements are
1069 // acceptable.
1070 // The QBENCHMARK macro increases the number of iterations for each run until
1071 // this happens.
1072 } while (invokeOk
1073 && QBenchmarkTestMethodData::current->isBenchmark()
1074 && QBenchmarkTestMethodData::current->resultsAccepted() == false);
1075
1076 QBenchmarkTestMethodData::current->endDataRun();
1077 if (i > -1) // iteration -1 is the warmup iteration.
1078 results.append(QBenchmarkTestMethodData::current->result);
1079
1080 if (QBenchmarkTestMethodData::current->isBenchmark() &&
1081 QBenchmarkGlobalData::current->verboseOutput) {
1082 if (i == -1) {
1083 qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value;
1084 } else {
1085 qDebug() << "accumulation stage result:" << QBenchmarkTestMethodData::current->result.value;
1086 }
1087 }
1088 } while (QBenchmarkTestMethodData::current->isBenchmark()
1089 && (++i < QBenchmarkGlobalData::current->adjustMedianIterationCount()));
1090
1091 if (QBenchmarkTestMethodData::current->isBenchmark()
1092 && QBenchmarkTestMethodData::current->resultsAccepted())
1093 QTestLog::addBenchmarkResult(qMedian(results));
1094}
1095
1096/*!
1097 \internal
1098
1099 Call init(), slot_data(), slot(), slot(), slot()..., cleanup()
1100 If data is set then it is the only test that is performed
1101
1102 If the function was successfully called, true is returned, otherwise
1103 false.
1104 */
1105static bool qInvokeTestMethod(const char *slotName, const char *data=0)
1106{
1107 QTEST_ASSERT(slotName);
1108
1109 QBenchmarkTestMethodData benchmarkData;
1110 QBenchmarkTestMethodData::current = &benchmarkData;
1111
1112 QBenchmarkGlobalData::current->context.slotName = QLatin1String(slotName);
1113
1114 char member[512];
1115 QTestTable table;
1116
1117 char *slot = qstrdup(slotName);
1118 slot[strlen(slot) - 2] = '\0';
1119 QTestResult::setCurrentTestFunction(slot);
1120
1121 const QTestTable *gTable = QTestTable::globalTestTable();
1122 const int globalDataCount = gTable->dataCount();
1123 int curGlobalDataIndex = 0;
1124
1125 /* For each test function that has a *_data() table/function, do: */
1126 do {
1127 if (!gTable->isEmpty())
1128 QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex));
1129
1130 if (curGlobalDataIndex == 0) {
1131 QTestResult::setCurrentTestLocation(QTestResult::DataFunc);
1132 QTest::qt_snprintf(member, 512, "%s_data", slot);
1133 QMetaObject::invokeMethod(QTest::currentTestObject, member, Qt::DirectConnection);
1134 // if we encounter a SkipAll in the _data slot, we skip the whole
1135 // testfunction, no matter how much global data exists
1136 if (QTestResult::skipCurrentTest()) {
1137 QTestResult::setCurrentGlobalTestData(0);
1138 break;
1139 }
1140 }
1141
1142 bool foundFunction = false;
1143 if (!QTestResult::skipCurrentTest()) {
1144 int curDataIndex = 0;
1145 const int dataCount = table.dataCount();
1146 QTestResult::setSkipCurrentTest(false);
1147
1148 /* For each entry in the data table, do: */
1149 do {
1150 if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
1151 foundFunction = true;
1152 QTestDataSetter s(table.isEmpty() ? static_cast<QTestData *>(0)
1153 : table.testData(curDataIndex));
1154
1155 qInvokeTestMethodDataEntry(slot);
1156
1157 if (QTestResult::skipCurrentTest())
1158 // check whether SkipAll was requested
1159 break;
1160 if (data)
1161 break;
1162 }
1163 ++curDataIndex;
1164 } while (curDataIndex < dataCount);
1165 }
1166
1167 if (data && !foundFunction) {
1168 printf("Unknown testdata for function %s: '%s'\n", slotName, data);
1169 printf("Available testdata:\n");
1170 for(int i = 0; i < table.dataCount(); ++i)
1171 printf("%s\n", table.testData(i)->dataTag());
1172 return false;
1173 }
1174
1175 QTestResult::setCurrentGlobalTestData(0);
1176 ++curGlobalDataIndex;
1177 } while (curGlobalDataIndex < globalDataCount);
1178
1179 QTestResult::finishedCurrentTestFunction();
1180 QTestResult::setSkipCurrentTest(false);
1181 QTestResult::setCurrentTestData(0);
1182 delete[] slot;
1183
1184 return true;
1185}
1186
1187void *fetchData(QTestData *data, const char *tagName, int typeId)
1188{
1189 QTEST_ASSERT(typeId);
1190 QTEST_ASSERT_X(data, "QTest::fetchData()", "Test data requested, but no testdata available.");
1191 QTEST_ASSERT(data->parent());
1192
1193 int idx = data->parent()->indexOf(tagName);
1194
1195 if (idx == -1 || idx >= data->dataCount()) {
1196 qFatal("QFETCH: Requested testdata '%s' not available, check your _data function.",
1197 tagName);
1198 }
1199
1200 if (typeId != data->parent()->elementTypeId(idx)) {
1201 qFatal("Requested type '%s' does not match available type '%s'.",
1202 QMetaType::typeName(typeId),
1203 QMetaType::typeName(data->parent()->elementTypeId(idx)));
1204 }
1205
1206 return data->data(idx);
1207}
1208
1209/*!
1210 \fn char* QTest::toHexRepresentation(const char *ba, int length)
1211
1212 Returns a pointer to a string that is the string \a ba represented
1213 as a space-separated sequence of hex characters. If the input is
1214 considered too long, it is truncated. A trucation is indicated in
1215 the returned string as an ellipsis at the end.
1216
1217 \a length is the length of the string \a ba.
1218 */
1219char *toHexRepresentation(const char *ba, int length)
1220{
1221 if(length == 0)
1222 return qstrdup("");
1223
1224 /* We output at maximum about maxLen characters in order to avoid
1225 * running out of memory and flooding things when the byte array
1226 * is large.
1227 *
1228 * maxLen can't be for example 200 because QTestLib is sprinkled with fixed
1229 * size char arrays.
1230 * */
1231 const int maxLen = 50;
1232 const int len = qMin(maxLen, length);
1233 char *result = 0;
1234
1235 if(length > maxLen) {
1236 const int size = len * 3 + 4;
1237 result = new char[size];
1238
1239 char *const forElipsis = result + size - 5;
1240 forElipsis[0] = ' ';
1241 forElipsis[1] = '.';
1242 forElipsis[2] = '.';
1243 forElipsis[3] = '.';
1244 result[size - 1] = '\0';
1245 }
1246 else {
1247 const int size = len * 3;
1248 result = new char[size];
1249 result[size - 1] = '\0';
1250 }
1251
1252 const char toHex[] = "0123456789ABCDEF";
1253 int i = 0;
1254 int o = 0;
1255
1256 while(true) {
1257 const char at = ba[i];
1258
1259 result[o] = toHex[(at >> 4) & 0x0F];
1260 ++o;
1261 result[o] = toHex[at & 0x0F];
1262
1263 ++i;
1264 ++o;
1265 if(i == len)
1266 break;
1267 else {
1268 result[o] = ' ';
1269 ++o;
1270 }
1271 }
1272
1273 return result;
1274}
1275
1276static void qInvokeTestMethods(QObject *testObject)
1277{
1278 const QMetaObject *metaObject = testObject->metaObject();
1279 QTEST_ASSERT(metaObject);
1280
1281 QTestLog::startLogging();
1282
1283 QTestResult::setCurrentTestFunction("initTestCase");
1284 QTestResult::setCurrentTestLocation(QTestResult::DataFunc);
1285 QTestTable::globalTestTable();
1286 QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection);
1287
1288 if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) {
1289 QTestResult::setCurrentTestLocation(QTestResult::InitFunc);
1290 QMetaObject::invokeMethod(testObject, "initTestCase");
1291
1292 // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy.
1293 const bool previousFailed = QTestResult::testFailed();
1294 QTestResult::finishedCurrentTestFunction();
1295
1296 if(!QTestResult::skipCurrentTest() && !previousFailed) {
1297
1298 if (lastTestFuncIdx >= 0) {
1299 for (int i = 0; i <= lastTestFuncIdx; ++i) {
1300 if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(),
1301 testFuncs[i].data))
1302 break;
1303 }
1304 } else {
1305 int methodCount = metaObject->methodCount();
1306 for (int i = 0; i < methodCount; ++i) {
1307 QMetaMethod slotMethod = metaObject->method(i);
1308 if (!isValidSlot(slotMethod))
1309 continue;
1310 if (!qInvokeTestMethod(slotMethod.signature()))
1311 break;
1312 }
1313 }
1314 }
1315
1316 QTestResult::setSkipCurrentTest(false);
1317 QTestResult::setCurrentTestFunction("cleanupTestCase");
1318 QMetaObject::invokeMethod(testObject, "cleanupTestCase");
1319 }
1320 QTestResult::finishedCurrentTestFunction();
1321 QTestResult::setCurrentTestFunction(0);
1322 QTestTable::clearGlobalTestTable();
1323
1324 QTestLog::stopLogging();
1325}
1326
1327} // namespace
1328
1329/*!
1330 Executes tests declared in \a testObject. In addition, the private slots
1331 \c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()}
1332 are executed if they exist. See \l{Creating a Test} for more details.
1333
1334 Optionally, the command line arguments \a argc and \a argv can be provided.
1335 For a list of recognized arguments, read \l {QTestLib Command Line Arguments}.
1336
1337 For stand-alone tests, the convenience macro \l QTEST_MAIN() can
1338 be used to declare a main method that parses the command line arguments
1339 and executes the tests.
1340
1341 Returns 0 if all tests passed. Returns a value other than 0 if tests failed
1342 or in case of unhandled exceptions. The return value from this function is
1343 also the exit code of the test application when the \l QTEST_MAIN() macro
1344 is used.
1345
1346 The following example will run all tests in \c MyFirstTestObject and
1347 \c{MySecondTestObject}:
1348
1349 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 18
1350
1351 Note: This function is not reentrant, only one test can run at a time. A
1352 test that was executed with qExec() can't run another test via qExec() and
1353 threads are not allowed to call qExec() simultaneously.
1354
1355 If you have programatically created the arguments, as opposed to getting them
1356 from the arguments in \c main(), it is likely of interest to use
1357 QTest::qExec(QObject *, const QStringList &) since it is Unicode safe.
1358
1359 \sa QTEST_MAIN()
1360*/
1361
1362int QTest::qExec(QObject *testObject, int argc, char **argv)
1363{
1364 QBenchmarkGlobalData benchmarkData;
1365 QBenchmarkGlobalData::current = &benchmarkData;
1366
1367#ifdef QTESTLIB_USE_VALGRIND
1368 int callgrindChildExitCode = 0;
1369#endif
1370
1371#ifdef Q_WS_MAC
1372 bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
1373#ifdef QT_MAC_USE_COCOA
1374 IOPMAssertionID powerID;
1375#endif
1376#endif
1377#ifndef QT_NO_EXCEPTIONS
1378 try {
1379#endif
1380
1381 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1382 SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
1383 #endif
1384
1385#ifdef Q_WS_MAC
1386 // Starting with Qt 4.4, applications launched from the command line
1387 // no longer get focus automatically. Since some tests might depend
1388 // on this, call SetFrontProcess here to get the pre 4.4 behavior.
1389 if (macNeedsActivate) {
1390 ProcessSerialNumber psn = { 0, kCurrentProcess };
1391 SetFrontProcess(&psn);
1392# ifdef QT_MAC_USE_COCOA
1393 IOReturn ok = IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, &powerID);
1394 if (ok != kIOReturnSuccess)
1395 macNeedsActivate = false; // no need to release the assertion on exit.
1396# else
1397 UpdateSystemActivity(1); // Wake the display.
1398# endif
1399 }
1400#endif
1401
1402 QTestResult::reset();
1403
1404 QTEST_ASSERT(testObject);
1405 QTEST_ASSERT(!currentTestObject);
1406 currentTestObject = testObject;
1407
1408 const QMetaObject *metaObject = testObject->metaObject();
1409 QTEST_ASSERT(metaObject);
1410
1411 QTestResult::setCurrentTestObject(metaObject->className());
1412 qParseArgs(argc, argv);
1413#ifdef QTESTLIB_USE_VALGRIND
1414 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
1415 const QStringList origAppArgs(QCoreApplication::arguments());
1416 if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode))
1417 return -1;
1418
1419 QBenchmarkValgrindUtils::cleanup();
1420
1421 } else {
1422#endif
1423
1424 qInvokeTestMethods(testObject);
1425
1426#ifdef QTESTLIB_USE_VALGRIND
1427 }
1428#endif
1429
1430 #ifndef QT_NO_EXCEPTIONS
1431 } catch (...) {
1432 QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__);
1433 if (QTestResult::currentTestFunction()) {
1434 QTestResult::finishedCurrentTestFunction();
1435 QTestResult::setCurrentTestFunction(0);
1436 }
1437
1438 QTestLog::stopLogging();
1439#ifdef QT_MAC_USE_COCOA
1440 if (macNeedsActivate) {
1441 IOPMAssertionRelease(powerID);
1442 }
1443#endif
1444 #ifdef Q_OS_WIN
1445 // rethrow exception to make debugging easier
1446 throw;
1447 #endif
1448 return -1;
1449 }
1450 #endif
1451
1452 currentTestObject = 0;
1453#ifdef QT_MAC_USE_COCOA
1454 if (macNeedsActivate) {
1455 IOPMAssertionRelease(powerID);
1456 }
1457#endif
1458
1459
1460#ifndef QT_NO_PROCESS
1461 if (QBenchmarkGlobalData::current->createChart) {
1462
1463#define XSTR(s) STR(s)
1464#define STR(s) #s
1465#ifdef Q_OS_WIN
1466 const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport.exe";
1467#else
1468 const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport";
1469#endif
1470#undef XSTR
1471#undef STR
1472
1473 if (QFile::exists(QLatin1String(path))) {
1474 QProcess p;
1475 p.setProcessChannelMode(QProcess::ForwardedChannels);
1476 p.start(QLatin1String(path), QStringList() << QLatin1String("results.xml"));
1477 p.waitForFinished(-1);
1478 } else {
1479 qWarning("Could not find %s, please make sure it is compiled.", path);
1480 }
1481 }
1482#endif
1483
1484#if defined(QTEST_NOEXITCODE) || (defined(QT_BUILD_INTERNAL) && !defined(QTEST_FORCE_EXITCODE))
1485 return 0;
1486#else
1487
1488#ifdef QTESTLIB_USE_VALGRIND
1489 if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
1490 return callgrindChildExitCode;
1491#endif
1492 // make sure our exit code is never going above 127
1493 // since that could wrap and indicate 0 test fails
1494 return qMin(QTestResult::failCount(), 127);
1495
1496#endif
1497}
1498
1499/*!
1500 \overload
1501 \since 4.4
1502
1503 Behaves identically to qExec(QObject *, int, char**) but takes a
1504 QStringList of \a arguments instead of a \c char** list.
1505 */
1506int QTest::qExec(QObject *testObject, const QStringList &arguments)
1507{
1508 const int argc = arguments.count();
1509 QVarLengthArray<char *> argv(argc);
1510
1511 QVector<QByteArray> args;
1512 args.reserve(argc);
1513
1514 for(int i = 0; i < argc; ++i)
1515 {
1516 args.append(arguments.at(i).toLocal8Bit().constData());
1517 argv[i] = args.last().data();
1518 }
1519
1520 return qExec(testObject, argc, argv.data());
1521}
1522
1523/*! \internal
1524 */
1525void QTest::qFail(const char *statementStr, const char *file, int line)
1526{
1527 QTestResult::addFailure(statementStr, file, line);
1528}
1529
1530/*! \internal
1531 */
1532bool QTest::qVerify(bool statement, const char *statementStr, const char *description,
1533 const char *file, int line)
1534{
1535 return QTestResult::verify(statement, statementStr, description, file, line);
1536}
1537
1538/*! \fn void QTest::qSkip(const char *message, SkipMode mode, const char *file, int line)
1539\internal
1540 */
1541void QTest::qSkip(const char *message, QTest::SkipMode mode,
1542 const char *file, int line)
1543{
1544 QTestResult::addSkip(message, mode, file, line);
1545 if (mode == QTest::SkipAll)
1546 QTestResult::setSkipCurrentTest(true);
1547}
1548
1549/*! \fn bool QTest::qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, const char *file, int line)
1550\internal
1551 */
1552bool QTest::qExpectFail(const char *dataIndex, const char *comment,
1553 QTest::TestFailMode mode, const char *file, int line)
1554{
1555 return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line);
1556}
1557
1558/*! \internal
1559 */
1560void QTest::qWarn(const char *message)
1561{
1562 QTestLog::warn(message);
1563}
1564
1565/*!
1566 Ignores messages created by qDebug() or qWarning(). If the \a message
1567 with the corresponding \a type is outputted, it will be removed from the
1568 test log. If the test finished and the \a message was not outputted,
1569 a test failure is appended to the test log.
1570
1571 \bold {Note:} Invoking this function will only ignore one message.
1572 If the message you want to ignore is outputted twice, you have to
1573 call ignoreMessage() twice, too.
1574
1575 Example:
1576 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 19
1577
1578 The example above tests that QDir::mkdir() outputs the right warning when invoked
1579 with an invalid file name.
1580*/
1581void QTest::ignoreMessage(QtMsgType type, const char *message)
1582{
1583 QTestResult::ignoreMessage(type, message);
1584}
1585
1586/*! \internal
1587 */
1588void *QTest::qData(const char *tagName, int typeId)
1589{
1590 return fetchData(QTestResult::currentTestData(), tagName, typeId);
1591}
1592
1593/*! \internal
1594 */
1595void *QTest::qGlobalData(const char *tagName, int typeId)
1596{
1597 return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId);
1598}
1599
1600/*! \internal
1601 */
1602void *QTest::qElementData(const char *tagName, int metaTypeId)
1603{
1604 QTEST_ASSERT(tagName);
1605 QTestData *data = QTestResult::currentTestData();
1606 QTEST_ASSERT(data);
1607 QTEST_ASSERT(data->parent());
1608
1609 int idx = data->parent()->indexOf(tagName);
1610 QTEST_ASSERT(idx != -1);
1611 QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId);
1612
1613 return data->data(data->parent()->indexOf(tagName));
1614}
1615
1616/*! \internal
1617 */
1618void QTest::addColumnInternal(int id, const char *name)
1619{
1620 QTestTable *tbl = QTestTable::currentTestTable();
1621 QTEST_ASSERT_X(tbl, "QTest::addColumn()", "Cannot add testdata outside of a _data slot.");
1622
1623 tbl->addColumn(id, name);
1624}
1625
1626/*!
1627 Appends a new row to the current test data. \a dataTag is the name of
1628 the testdata that will appear in the test output. Returns a QTestData reference
1629 that can be used to stream in data.
1630
1631 Example:
1632 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 20
1633
1634 \bold {Note:} This macro can only be used in a test's data function
1635 that is invoked by the test framework.
1636
1637 See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for
1638 a more extensive example.
1639
1640 \sa addColumn(), QFETCH()
1641*/
1642QTestData &QTest::newRow(const char *dataTag)
1643{
1644 QTestTable *tbl = QTestTable::currentTestTable();
1645 QTEST_ASSERT_X(tbl, "QTest::addColumn()", "Cannot add testdata outside of a _data slot.");
1646
1647 return *tbl->newData(dataTag);
1648}
1649
1650/*! \fn void QTest::addColumn(const char *name, T *dummy = 0)
1651
1652 Adds a column with type \c{T} to the current test data.
1653 \a name is the name of the column. \a dummy is a workaround
1654 for buggy compilers and can be ignored.
1655
1656 To populate the column with values, newRow() can be used. Use
1657 \l QFETCH() to fetch the data in the actual test.
1658
1659 Example:
1660 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 21
1661
1662 To add custom types to the testdata, the type must be registered with
1663 QMetaType via \l Q_DECLARE_METATYPE().
1664
1665 \bold {Note:} This macro can only be used in a test's data function
1666 that is invoked by the test framework.
1667
1668 See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for
1669 a more extensive example.
1670
1671 \sa QTest::newRow(), QFETCH(), QMetaType
1672*/
1673
1674/*!
1675 Returns the name of the test function that is currently executed.
1676
1677 Example:
1678
1679 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 22
1680*/
1681const char *QTest::currentTestFunction()
1682{
1683 return QTestResult::currentTestFunction();
1684}
1685
1686/*!
1687 Returns the name of the current test data. If the test doesn't
1688 have any assigned testdata, the function returns 0.
1689*/
1690const char *QTest::currentDataTag()
1691{
1692 return QTestResult::currentDataTag();
1693}
1694
1695/*!
1696 Returns true if the current test function failed, otherwise false.
1697*/
1698bool QTest::currentTestFailed()
1699{
1700 return QTestResult::currentTestFailed();
1701}
1702
1703/*!
1704 Sleeps for \a ms milliseconds, blocking execution of the
1705 test. qSleep() will not do any event processing and leave your test
1706 unresponsive. Network communication might time out while
1707 sleeping. Use \l qWait() to do non-blocking sleeping.
1708
1709 \a ms must be greater than 0.
1710
1711 \bold {Note:} The qSleep() function calls either \c nanosleep() on
1712 unix or \c Sleep() on windows, so the accuracy of time spent in
1713 qSleep() depends on the operating system.
1714
1715 Example:
1716 \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 23
1717
1718 \sa qWait()
1719*/
1720void QTest::qSleep(int ms)
1721{
1722 QTEST_ASSERT(ms > 0);
1723
1724#ifdef Q_OS_WIN
1725 Sleep(uint(ms));
1726#else
1727 struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
1728 nanosleep(&ts, NULL);
1729#endif
1730}
1731
1732/*! \internal
1733 */
1734QObject *QTest::testObject()
1735{
1736 return currentTestObject;
1737}
1738
1739/*! \internal
1740 */
1741bool QTest::compare_helper(bool success, const char *msg, const char *file, int line)
1742{
1743 return QTestResult::compare(success, msg, file, line);
1744}
1745
1746/*! \internal
1747 */
1748bool QTest::compare_helper(bool success, const char *msg, char *val1, char *val2,
1749 const char *actual, const char *expected, const char *file, int line)
1750{
1751 return QTestResult::compare(success, msg, val1, val2, actual, expected, file, line);
1752}
1753
1754/*! \fn bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line)
1755\internal
1756 */
1757template <>
1758bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected,
1759 const char *file, int line)
1760{
1761 return qFuzzyCompare(t1, t2)
1762 ? compare_helper(true, "COMPARE()", file, line)
1763 : compare_helper(false, "Compared floats are not the same (fuzzy compare)",
1764 toString(t1), toString(t2), actual, expected, file, line);
1765}
1766
1767/*! \fn bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line)
1768\internal
1769 */
1770template <>
1771bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected,
1772 const char *file, int line)
1773{
1774 return qFuzzyCompare(t1, t2)
1775 ? compare_helper(true, "COMPARE()", file, line)
1776 : compare_helper(false, "Compared doubles are not the same (fuzzy compare)",
1777 toString(t1), toString(t2), actual, expected, file, line);
1778}
1779
1780#define COMPARE_IMPL2(TYPE, FORMAT) \
1781template <> char *QTest::toString<TYPE >(const TYPE &t) \
1782{ \
1783 char *msg = new char[128]; \
1784 qt_snprintf(msg, 128, #FORMAT, t); \
1785 return msg; \
1786}
1787
1788COMPARE_IMPL2(short, %hd)
1789COMPARE_IMPL2(ushort, %hu)
1790COMPARE_IMPL2(int, %d)
1791COMPARE_IMPL2(uint, %u)
1792COMPARE_IMPL2(long, %ld)
1793COMPARE_IMPL2(ulong, %lu)
1794#if defined(Q_OS_WIN)
1795COMPARE_IMPL2(qint64, %I64d)
1796COMPARE_IMPL2(quint64, %I64u)
1797#else
1798COMPARE_IMPL2(qint64, %lld)
1799COMPARE_IMPL2(quint64, %llu)
1800#endif
1801COMPARE_IMPL2(bool, %d)
1802COMPARE_IMPL2(char, %c)
1803COMPARE_IMPL2(float, %g);
1804COMPARE_IMPL2(double, %lg);
1805
1806/*! \internal
1807 */
1808char *QTest::toString(const char *str)
1809{
1810 if (!str)
1811 return 0;
1812 char *msg = new char[strlen(str) + 1];
1813 return qstrcpy(msg, str);
1814}
1815
1816/*! \internal
1817 */
1818char *QTest::toString(const void *p)
1819{
1820 char *msg = new char[128];
1821 qt_snprintf(msg, 128, "%p", p);
1822 return msg;
1823}
1824
1825/*! \internal
1826 */
1827bool QTest::compare_string_helper(const char *t1, const char *t2, const char *actual,
1828 const char *expected, const char *file, int line)
1829{
1830 return (qstrcmp(t1, t2) == 0)
1831 ? compare_helper(true, "COMPARE()", file, line)
1832 : compare_helper(false, "Compared strings are not the same",
1833 toString(t1), toString(t2), actual, expected, file, line);
1834}
1835
1836/*! \fn bool QTest::compare_ptr_helper(const void *t1, const void *t2, const char *actual, const char *expected, const char *file, int line);
1837 \internal
1838*/
1839
1840/*! \fn bool QTest::qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
1841 \internal
1842*/
1843
1844
1845/*! \fn void QTest::mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1)
1846 \internal
1847*/
1848
1849/*! \fn bool QTest::qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected, const char *file, int line)
1850 \internal
1851*/
1852
1853/*! \fn bool QTest::qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, const char *expected, const char *file, int line)
1854 \internal
1855*/
1856
1857/*! \fn bool QTest::qCompare(T const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line)
1858 \internal
1859*/
1860
1861/*! \fn bool QTest::qCompare(const T *t1, const T *t2, const char *actual, const char *expected, const char *file, int line)
1862 \internal
1863*/
1864
1865/*! \fn bool QTest::qCompare(T *t1, T *t2, const char *actual, const char *expected, const char *file, int line)
1866 \internal
1867*/
1868
1869/*! \fn bool QTest::qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected, const char *file, int line)
1870 \internal
1871*/
1872
1873/*! \fn bool QTest::qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected, const char *file, int line)
1874 \internal
1875*/
1876
1877/*! \fn bool QTest::qCompare(const char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line)
1878 \internal
1879*/
1880
1881/*! \fn bool QTest::qCompare(char *t1, char *t2, const char *actual, const char *expected, const char *file, int line)
1882 \internal
1883*/
1884
1885/*! \fn bool QTest::qCompare(char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line)
1886 \internal
1887*/
1888
1889/*! \fn bool QTest::qCompare(const char *t1, char *t2, const char *actual, const char *expected, const char *file, int line)
1890 \internal
1891*/
1892
1893/*! \fn bool QTest::qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line)
1894 \internal
1895*/
1896
1897/*! \fn bool QTest::qCompare(QLatin1String const &t1, QString const &t2, const char *actual, const char *expected, const char *file, int line)
1898 \internal
1899*/
1900
1901/*! \fn bool QTest::qCompare(QStringList const &t1, QStringList const &t2, const char *actual, const char *expected, const char *file, int line)
1902 \internal
1903*/
1904
1905/*! \fn bool QTest::qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line)
1906 \internal
1907*/
1908
1909/*! \fn bool QTest::qCompare(QFlags<T> const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line)
1910 \internal
1911*/
1912
1913/*! \fn bool QTest::qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line)
1914 \internal
1915*/
1916
1917/*! \fn void QTest::sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, QString text, Qt::KeyboardModifiers modifier, int delay=-1)
1918 \internal
1919*/
1920
1921/*! \fn void QTest::sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, char ascii, Qt::KeyboardModifiers modifier, int delay=-1)
1922 \internal
1923*/
1924
1925/*! \fn void QTest::simulateEvent(QWidget *widget, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1)
1926 \internal
1927*/
1928
1929/*! \fn int QTest::qt_snprintf(char *str, int size, const char *format, ...)
1930 \internal
1931*/
1932
1933QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.