1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtTest module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
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 <errno.h> |
75 | #include <signal.h> |
76 | #include <time.h> |
77 | #endif |
78 | |
79 | #ifdef Q_WS_MAC |
80 | #include <Carbon/Carbon.h> // for SetFrontProcess |
81 | #ifdef QT_MAC_USE_COCOA |
82 | #include <IOKit/pwr_mgt/IOPMLib.h> |
83 | #else |
84 | #include <Security/AuthSession.h> |
85 | #endif |
86 | #undef verify |
87 | #endif |
88 | |
89 | QT_BEGIN_NAMESPACE |
90 | |
91 | /*! |
92 | \namespace QTest |
93 | \inmodule QtTest |
94 | |
95 | \brief The QTest namespace contains all the functions and |
96 | declarations that are related to the QTestLib tool. |
97 | |
98 | Please refer to the \l{QTestLib Manual} documentation for information on |
99 | how to write unit tests. |
100 | */ |
101 | |
102 | /*! \macro QVERIFY(condition) |
103 | |
104 | \relates QTest |
105 | |
106 | The QVERIFY() macro checks whether the \a condition is true or not. If it is |
107 | true, execution continues. If not, a failure is recorded in the test log |
108 | and the test won't be executed further. |
109 | |
110 | \bold {Note:} This macro can only be used in a test function that is invoked |
111 | by the test framework. |
112 | |
113 | Example: |
114 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 0 |
115 | |
116 | \sa QCOMPARE() |
117 | */ |
118 | |
119 | /*! \macro QVERIFY2(condition, message) |
120 | |
121 | \relates QTest |
122 | |
123 | The QVERIFY2() macro behaves exactly like QVERIFY(), except that it outputs |
124 | a verbose \a message when \a condition is false. The \a message is a plain |
125 | C string. |
126 | |
127 | Example: |
128 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 1 |
129 | |
130 | \sa QVERIFY(), QCOMPARE() |
131 | */ |
132 | |
133 | /*! \macro QCOMPARE(actual, expected) |
134 | |
135 | \relates QTest |
136 | |
137 | The QCOMPARE macro compares an \a actual value to an \a expected value using |
138 | the equals operator. If \a actual and \a expected are identical, execution |
139 | continues. If not, a failure is recorded in the test log and the test |
140 | won't be executed further. |
141 | |
142 | In the case of comparing floats and doubles, qFuzzyCompare() is used for |
143 | comparing. This means that comparing to 0 will likely fail. One solution |
144 | to this is to compare to 1, and add 1 to the produced output. |
145 | |
146 | QCOMPARE tries to output the contents of the values if the comparison fails, |
147 | so it is visible from the test log why the comparison failed. |
148 | |
149 | QCOMPARE is very strict on the data types. Both \a actual and \a expected |
150 | have to be of the same type, otherwise the test won't compile. This prohibits |
151 | unspecified behavior from being introduced; that is behavior that usually |
152 | occurs when the compiler implicitly casts the argument. |
153 | |
154 | If you use QCOMPARE() to compare two QStringList objects, it will start |
155 | comparing the objects from the end of the lists. |
156 | |
157 | For your own classes, you can use \l QTest::toString() to format values for |
158 | outputting into the test log. |
159 | |
160 | \note This macro can only be used in a test function that is invoked |
161 | by the test framework. |
162 | |
163 | Example: |
164 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 2 |
165 | |
166 | \sa QVERIFY(), QTest::toString() |
167 | */ |
168 | |
169 | /*! \macro QFETCH(type, name) |
170 | |
171 | \relates QTest |
172 | |
173 | The fetch macro creates a local variable named \a name with the type \a type |
174 | on the stack. \a name has to match the element name from the test's data. |
175 | If no such element exists, the test will assert. |
176 | |
177 | Assuming a test has the following data: |
178 | |
179 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 3 |
180 | |
181 | The test data has two elements, a QString called \c aString and an integer |
182 | called \c expected. To fetch these values in the actual test: |
183 | |
184 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 4 |
185 | |
186 | \c aString and \c expected are variables on the stack that are initialized with |
187 | the current test data. |
188 | |
189 | \bold {Note:} This macro can only be used in a test function that is invoked |
190 | by the test framework. The test function must have a _data function. |
191 | */ |
192 | |
193 | /*! \macro QWARN(message) |
194 | |
195 | \relates QTest |
196 | \threadsafe |
197 | |
198 | Appends \a message as a warning to the test log. This macro can be used anywhere |
199 | in your tests. |
200 | */ |
201 | |
202 | /*! \macro QFAIL(message) |
203 | |
204 | \relates QTest |
205 | |
206 | This macro can be used to force a test failure. The test stops |
207 | executing and the failure \a message is appended to the test log. |
208 | |
209 | \bold {Note:} This macro can only be used in a test function that is invoked |
210 | by the test framework. |
211 | |
212 | Example: |
213 | |
214 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 5 |
215 | */ |
216 | |
217 | /*! \macro QTEST(actual, testElement) |
218 | |
219 | \relates QTest |
220 | |
221 | QTEST() is a convenience macro for \l QCOMPARE() that compares |
222 | the value \a actual with the element \a testElement from the test's data. |
223 | If there is no such element, the test asserts. |
224 | |
225 | Apart from that, QTEST() behaves exactly as \l QCOMPARE(). |
226 | |
227 | Instead of writing: |
228 | |
229 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 6 |
230 | |
231 | you can write: |
232 | |
233 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 7 |
234 | |
235 | \sa QCOMPARE() |
236 | */ |
237 | |
238 | /*! \macro QSKIP(description, mode) |
239 | |
240 | \relates QTest |
241 | |
242 | The QSKIP() macro stops execution of the test without adding a failure to the |
243 | test log. You can use it to skip tests that wouldn't make sense in the current |
244 | configuration. The text \a description is appended to the test log and should |
245 | contain an explanation why the test couldn't be executed. \a mode is a QTest::SkipMode |
246 | and describes whether to proceed with the rest of the test data or not. |
247 | |
248 | \bold {Note:} This macro can only be used in a test function that is invoked |
249 | by the test framework. |
250 | |
251 | Example: |
252 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 8 |
253 | |
254 | \sa QTest::SkipMode |
255 | */ |
256 | |
257 | /*! \macro QEXPECT_FAIL(dataIndex, comment, mode) |
258 | |
259 | \relates QTest |
260 | |
261 | The QEXPECT_FAIL() macro marks the next \l QCOMPARE() or \l QVERIFY() as an |
262 | expected failure. Instead of adding a failure to the test log, an expected |
263 | failure will be reported. |
264 | |
265 | If a \l QVERIFY() or \l QCOMPARE() is marked as an expected failure, |
266 | but passes instead, an unexpected pass (XPASS) is written to the test log. |
267 | |
268 | The parameter \a dataIndex describes for which entry in the test data the |
269 | failure is expected. Pass an empty string (\c{""}) if the failure |
270 | is expected for all entries or if no test data exists. |
271 | |
272 | \a comment will be appended to the test log for the expected failure. |
273 | |
274 | \a mode is a \l QTest::TestFailMode and sets whether the test should |
275 | continue to execute or not. |
276 | |
277 | \bold {Note:} This macro can only be used in a test function that is invoked |
278 | by the test framework. |
279 | |
280 | Example 1: |
281 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 9 |
282 | |
283 | In the example above, an expected fail will be written into the test output |
284 | if the variable \c i is not 42. If the variable \c i is 42, an unexpected pass |
285 | is written instead. The QEXPECT_FAIL() has no influence on the second QCOMPARE() |
286 | statement in the example. |
287 | |
288 | Example 2: |
289 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 10 |
290 | |
291 | The above testfunction will not continue executing for the test data |
292 | entry \c{data27}. |
293 | |
294 | \sa QTest::TestFailMode, QVERIFY(), QCOMPARE() |
295 | */ |
296 | |
297 | /*! \macro QTEST_MAIN(TestClass) |
298 | |
299 | \relates QTest |
300 | |
301 | Implements a main() function that instantiates an application object and |
302 | the \a TestClass, and executes all tests in the order they were defined. |
303 | Use this macro to build stand-alone executables. |
304 | |
305 | If \c QT_GUI_LIB is defined, the application object will be a QApplication, |
306 | otherwise it will be a QCoreApplication. If qmake is used and the configuration |
307 | includes \c{QT += gui}, then \c QT_GUI_LIB will be defined automatically. |
308 | |
309 | \bold {Note:} On platforms that have keypad navigation enabled by default (eg: Symbian), |
310 | this macro will forcfully disable it to simplify the usage of key events when writing |
311 | autotests. If you wish to write a test case that uses keypad navigation, you should |
312 | enable it either in the \c {initTestCase()} or \c {init()} functions of your test case. |
313 | |
314 | Example: |
315 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 11 |
316 | |
317 | \sa QTEST_APPLESS_MAIN(), QTest::qExec(), QApplication::setNavigationMode() |
318 | */ |
319 | |
320 | /*! \macro QTEST_APPLESS_MAIN(TestClass) |
321 | |
322 | \relates QTest |
323 | |
324 | Implements a main() function that executes all tests in \a TestClass. |
325 | |
326 | Behaves like \l QTEST_MAIN(), but doesn't instantiate a QApplication |
327 | object. Use this macro for really simple stand-alone non-GUI tests. |
328 | |
329 | \sa QTEST_MAIN() |
330 | */ |
331 | |
332 | /*! \macro QTEST_NOOP_MAIN() |
333 | |
334 | \relates QTest |
335 | |
336 | Implements a main() function with a test class that does absolutely nothing. |
337 | Use this macro to create a test that produces valid test output but just |
338 | doesn't execute any test, for example in conditional compilations: |
339 | |
340 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 12 |
341 | |
342 | \sa QTEST_MAIN() |
343 | */ |
344 | |
345 | /*! |
346 | \macro QBENCHMARK |
347 | |
348 | \relates QTest |
349 | |
350 | This macro is used to measure the performance of code within a test. |
351 | The code to be benchmarked is contained within a code block following |
352 | this macro. |
353 | |
354 | For example: |
355 | |
356 | \snippet examples/qtestlib/tutorial5/benchmarking.cpp 0 |
357 | |
358 | \sa {QTestLib Manual#Creating a Benchmark}{Creating a Benchmark}, |
359 | {Chapter 5: Writing a Benchmark}{Writing a Benchmark} |
360 | */ |
361 | |
362 | /*! |
363 | \macro QBENCHMARK_ONCE |
364 | \since 4.6 |
365 | |
366 | \relates QTest |
367 | |
368 | \brief The QBENCHMARK_ONCE macro is for measuring performance of a |
369 | code block by running it once. |
370 | |
371 | This macro is used to measure the performance of code within a test. |
372 | The code to be benchmarked is contained within a code block following |
373 | this macro. |
374 | |
375 | Unlike QBENCHMARK, the contents of the contained code block is only run |
376 | once. The elapsed time will be reported as "0" if it's to short to |
377 | be measured by the selected backend. (Use) |
378 | |
379 | \sa {QTestLib Manual#Creating a Benchmark}{Creating a Benchmark}, |
380 | {Chapter 5: Writing a Benchmark}{Writing a Benchmark} |
381 | */ |
382 | |
383 | |
384 | |
385 | /*! \enum QTest::SkipMode |
386 | |
387 | This enum describes the modes for skipping tests during execution |
388 | of the test data. |
389 | |
390 | \value SkipSingle Skips the current entry in the test table; continues |
391 | execution of all the other entries in the table. |
392 | |
393 | \value SkipAll Skips all the entries in the test table; the test won't |
394 | be executed further. |
395 | |
396 | \sa QSKIP() |
397 | */ |
398 | |
399 | /*! \enum QTest::TestFailMode |
400 | |
401 | This enum describes the modes for handling an expected failure of the |
402 | \l QVERIFY() or \l QCOMPARE() macros. |
403 | |
404 | \value Abort Aborts the execution of the test. Use this mode when it |
405 | doesn't make sense to execute the test any further after the |
406 | expected failure. |
407 | |
408 | \value Continue Continues execution of the test after the expected failure. |
409 | |
410 | \sa QEXPECT_FAIL() |
411 | */ |
412 | |
413 | /*! \enum QTest::KeyAction |
414 | |
415 | This enum describes possible actions for key handling. |
416 | |
417 | \value Press The key is pressed. |
418 | \value Release The key is released. |
419 | \value Click The key is clicked (pressed and released). |
420 | */ |
421 | |
422 | /*! \enum QTest::MouseAction |
423 | |
424 | This enum describes possible actions for mouse handling. |
425 | |
426 | \value MousePress A mouse button is pressed. |
427 | \value MouseRelease A mouse button is released. |
428 | \value MouseClick A mouse button is clicked (pressed and released). |
429 | \value MouseDClick A mouse button is double clicked (pressed and released twice). |
430 | \value MouseMove The mouse pointer has moved. |
431 | */ |
432 | |
433 | /*! \fn void QTest::keyClick(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
434 | |
435 | \overload |
436 | |
437 | Simulates clicking of \a key with an optional \a modifier on a \a widget. |
438 | If \a delay is larger than 0, the test will wait for \a delay milliseconds. |
439 | |
440 | Example: |
441 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 13 |
442 | |
443 | The example above simulates clicking \c a on \c myWidget without |
444 | any keyboard modifiers and without delay of the test. |
445 | |
446 | \sa QTest::keyClicks() |
447 | */ |
448 | |
449 | /*! \fn void QTest::keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
450 | |
451 | Simulates clicking of \a key with an optional \a modifier on a \a widget. |
452 | If \a delay is larger than 0, the test will wait for \a delay milliseconds. |
453 | |
454 | Examples: |
455 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 14 |
456 | |
457 | The first example above simulates clicking the \c escape key on \c |
458 | myWidget without any keyboard modifiers and without delay. The |
459 | second example simulates clicking \c shift-escape on \c myWidget |
460 | with a following 200 ms delay of the test. |
461 | |
462 | \sa QTest::keyClicks() |
463 | */ |
464 | |
465 | /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
466 | |
467 | Sends a Qt key event to \a widget with the given \a key and an associated \a action. |
468 | Optionally, a keyboard \a modifier can be specified, as well as a \a delay |
469 | (in milliseconds) of the test before sending the event. |
470 | */ |
471 | |
472 | /*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, char ascii, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
473 | |
474 | \overload |
475 | |
476 | Sends a Qt key event to \a widget with the given key \a ascii and an associated \a action. |
477 | Optionally, a keyboard \a modifier can be specified, as well as a \a delay |
478 | (in milliseconds) of the test before sending the event. |
479 | |
480 | */ |
481 | |
482 | /*! \fn void QTest::keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
483 | |
484 | Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay |
485 | is larger than 0, the test will wait for \a delay milliseconds. |
486 | |
487 | \bold {Note:} At some point you should release the key using \l keyRelease(). |
488 | |
489 | \sa QTest::keyRelease(), QTest::keyClick() |
490 | */ |
491 | |
492 | /*! \fn void QTest::keyPress(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
493 | |
494 | \overload |
495 | |
496 | Simulates pressing a \a key with an optional \a modifier on a \a widget. |
497 | If \a delay is larger than 0, the test will wait for \a delay milliseconds. |
498 | |
499 | \bold {Note:} At some point you should release the key using \l keyRelease(). |
500 | |
501 | \sa QTest::keyRelease(), QTest::keyClick() |
502 | */ |
503 | |
504 | /*! \fn void QTest::keyRelease(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
505 | |
506 | Simulates releasing a \a key with an optional \a modifier on a \a widget. |
507 | If \a delay is larger than 0, the test will wait for \a delay milliseconds. |
508 | |
509 | \sa QTest::keyPress(), QTest::keyClick() |
510 | */ |
511 | |
512 | /*! \fn void QTest::keyRelease(QWidget *widget, char key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
513 | |
514 | \overload |
515 | |
516 | Simulates releasing a \a key with an optional \a modifier on a \a widget. |
517 | If \a delay is larger than 0, the test will wait for \a delay milliseconds. |
518 | |
519 | \sa QTest::keyClick() |
520 | */ |
521 | |
522 | |
523 | /*! \fn void QTest::keyClicks(QWidget *widget, const QString &sequence, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1) |
524 | |
525 | Simulates clicking a \a sequence of keys on a \a |
526 | widget. Optionally, a keyboard \a modifier can be specified as |
527 | well as a \a delay (in milliseconds) of the test before each key |
528 | click. |
529 | |
530 | Example: |
531 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 15 |
532 | |
533 | The example above simulates clicking the sequence of keys |
534 | representing "hello world" on \c myWidget without any keyboard |
535 | modifiers and without delay of the test. |
536 | |
537 | \sa QTest::keyClick() |
538 | */ |
539 | |
540 | /*! \fn void QTest::mousePress(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) |
541 | |
542 | Simulates pressing a mouse \a button with an optional \a modifier |
543 | on a \a widget. The position is defined by \a pos; the default |
544 | position is the center of the widget. If \a delay is specified, |
545 | the test will wait for the specified amount of milliseconds before |
546 | the press. |
547 | |
548 | \sa QTest::mouseRelease(), QTest::mouseClick() |
549 | */ |
550 | |
551 | /*! \fn void QTest::mouseRelease(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) |
552 | |
553 | Simulates releasing a mouse \a button with an optional \a modifier |
554 | on a \a widget. The position of the release is defined by \a pos; |
555 | the default position is the center of the widget. If \a delay is |
556 | specified, the test will wait for the specified amount of |
557 | milliseconds before releasing the button. |
558 | |
559 | \sa QTest::mousePress(), QTest::mouseClick() |
560 | */ |
561 | |
562 | /*! \fn void QTest::mouseClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) |
563 | |
564 | Simulates clicking a mouse \a button with an optional \a modifier |
565 | on a \a widget. The position of the click is defined by \a pos; |
566 | the default position is the center of the widget. If \a delay is |
567 | specified, the test will wait for the specified amount of |
568 | milliseconds before pressing and before releasing the button. |
569 | |
570 | \sa QTest::mousePress(), QTest::mouseRelease() |
571 | */ |
572 | |
573 | /*! \fn void QTest::mouseDClick(QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers modifier = 0, QPoint pos = QPoint(), int delay=-1) |
574 | |
575 | Simulates double clicking a mouse \a button with an optional \a |
576 | modifier on a \a widget. The position of the click is defined by |
577 | \a pos; the default position is the center of the widget. If \a |
578 | delay is specified, the test will wait for the specified amount of |
579 | milliseconds before each press and release. |
580 | |
581 | \sa QTest::mouseClick() |
582 | */ |
583 | |
584 | /*! \fn void QTest::mouseMove(QWidget *widget, QPoint pos = QPoint(), int delay=-1) |
585 | |
586 | Moves the mouse pointer to a \a widget. If \a pos is not |
587 | specified, the mouse pointer moves to the center of the widget. If |
588 | a \a delay (in milliseconds) is given, the test will wait before |
589 | moving the mouse pointer. |
590 | */ |
591 | |
592 | /*! |
593 | \fn char *QTest::toString(const T &value) |
594 | |
595 | Returns a textual representation of \a value. This function is used by |
596 | \l QCOMPARE() to output verbose information in case of a test failure. |
597 | |
598 | You can add specializations of this function to your test to enable |
599 | verbose output. |
600 | |
601 | \bold {Note:} The caller of toString() must delete the returned data |
602 | using \c{delete[]}. Your implementation should return a string |
603 | created with \c{new[]} or qstrdup(). |
604 | |
605 | Example: |
606 | |
607 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 16 |
608 | |
609 | The example above defines a toString() specialization for a class |
610 | called \c MyPoint. Whenever a comparison of two instances of \c |
611 | MyPoint fails, \l QCOMPARE() will call this function to output the |
612 | contents of \c MyPoint to the test log. |
613 | |
614 | \sa QCOMPARE() |
615 | */ |
616 | |
617 | /*! |
618 | \fn char *QTest::toString(const QLatin1String &string) |
619 | \overload |
620 | |
621 | Returns a textual representation of the given \a string. |
622 | */ |
623 | |
624 | /*! |
625 | \fn char *QTest::toString(const QString &string) |
626 | \overload |
627 | |
628 | Returns a textual representation of the given \a string. |
629 | */ |
630 | |
631 | /*! |
632 | \fn char *QTest::toString(const QByteArray &ba) |
633 | \overload |
634 | |
635 | Returns a textual representation of the byte array \a ba. |
636 | |
637 | \sa QTest::toHexRepresentation() |
638 | */ |
639 | |
640 | /*! |
641 | \fn char *QTest::toString(const QTime &time) |
642 | \overload |
643 | |
644 | Returns a textual representation of the given \a time. |
645 | */ |
646 | |
647 | /*! |
648 | \fn char *QTest::toString(const QDate &date) |
649 | \overload |
650 | |
651 | Returns a textual representation of the given \a date. |
652 | */ |
653 | |
654 | /*! |
655 | \fn char *QTest::toString(const QDateTime &dateTime) |
656 | \overload |
657 | |
658 | Returns a textual representation of the date and time specified by |
659 | \a dateTime. |
660 | */ |
661 | |
662 | /*! |
663 | \fn char *QTest::toString(const QChar &character) |
664 | \overload |
665 | |
666 | Returns a textual representation of the given \a character. |
667 | */ |
668 | |
669 | /*! |
670 | \fn char *QTest::toString(const QPoint &point) |
671 | \overload |
672 | |
673 | Returns a textual representation of the given \a point. |
674 | */ |
675 | |
676 | /*! |
677 | \fn char *QTest::toString(const QSize &size) |
678 | \overload |
679 | |
680 | Returns a textual representation of the given \a size. |
681 | */ |
682 | |
683 | /*! |
684 | \fn char *QTest::toString(const QRect &rectangle) |
685 | \overload |
686 | |
687 | Returns a textual representation of the given \a rectangle. |
688 | */ |
689 | |
690 | /*! |
691 | \fn char *QTest::toString(const QUrl &url) |
692 | \since 4.4 |
693 | \overload |
694 | |
695 | Returns a textual representation of the given \a url. |
696 | */ |
697 | |
698 | /*! |
699 | \fn char *QTest::toString(const QPointF &point) |
700 | \overload |
701 | |
702 | Returns a textual representation of the given \a point. |
703 | */ |
704 | |
705 | /*! |
706 | \fn char *QTest::toString(const QSizeF &size) |
707 | \overload |
708 | |
709 | Returns a textual representation of the given \a size. |
710 | */ |
711 | |
712 | /*! |
713 | \fn char *QTest::toString(const QRectF &rectangle) |
714 | \overload |
715 | |
716 | Returns a textual representation of the given \a rectangle. |
717 | */ |
718 | |
719 | /*! |
720 | \fn char *QTest::toString(const QVariant &variant) |
721 | \overload |
722 | |
723 | Returns a textual representation of the given \a variant. |
724 | */ |
725 | |
726 | /*! \fn void QTest::qWait(int ms) |
727 | |
728 | Waits for \a ms milliseconds. While waiting, events will be processed and |
729 | your test will stay responsive to user interface events or network communication. |
730 | |
731 | Example: |
732 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 17 |
733 | |
734 | The code above will wait until the network server is responding for a |
735 | maximum of about 12.5 seconds. |
736 | |
737 | \sa QTest::qSleep() |
738 | */ |
739 | |
740 | /*! \fn bool QTest::qWaitForWindowShown(QWidget *window) |
741 | \since 4.6 |
742 | |
743 | Waits until the \a window is shown in the screen. This is mainly useful for |
744 | asynchronous systems like X11, where a window will be mapped to screen some |
745 | time after being asked to show itself on the screen. Returns true. |
746 | |
747 | Example: |
748 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 24 |
749 | */ |
750 | |
751 | /*! |
752 | \class QTest::QTouchEventSequence |
753 | \inmodule QtTest |
754 | \since 4.6 |
755 | |
756 | \brief The QTouchEventSequence class is used to simulate a sequence of touch events. |
757 | |
758 | To simulate a sequence of touch events on a specific device for a widget, call |
759 | QTest::touchEvent to create a QTouchEventSequence instance. Add touch events to |
760 | the sequence by calling press(), move(), release() and stationary(), and let the |
761 | instance run out of scope to commit the sequence to the event system. |
762 | |
763 | Example: |
764 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 25 |
765 | */ |
766 | |
767 | /*! |
768 | \fn QTest::QTouchEventSequence::~QTouchEventSequence() |
769 | |
770 | Commits this sequence of touch events and frees allocated resources. |
771 | */ |
772 | |
773 | /*! |
774 | \fn QTouchEventSequence &QTest::QTouchEventSequence::press(int touchId, const QPoint &pt, QWidget *widget) |
775 | |
776 | Adds a press event for touchpoint \a touchId at position \a pt to this sequence and returns |
777 | a reference to this QTouchEventSequence. |
778 | |
779 | The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then |
780 | \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. |
781 | |
782 | Simulates that the user pressed the touch screen or pad with the finger identified by \a touchId. |
783 | */ |
784 | |
785 | /*! |
786 | \fn QTouchEventSequence &QTest::QTouchEventSequence::move(int touchId, const QPoint &pt, QWidget *widget) |
787 | |
788 | Adds a move event for touchpoint \a touchId at position \a pt to this sequence and returns |
789 | a reference to this QTouchEventSequence. |
790 | |
791 | The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then |
792 | \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. |
793 | |
794 | Simulates that the user moved the finger identified by \a touchId. |
795 | */ |
796 | |
797 | /*! |
798 | \fn QTouchEventSequence &QTest::QTouchEventSequence::release(int touchId, const QPoint &pt, QWidget *widget) |
799 | |
800 | Adds a release event for touchpoint \a touchId at position \a pt to this sequence and returns |
801 | a reference to this QTouchEventSequence. |
802 | |
803 | The position \a pt is interpreted as relative to \a widget. If \a widget is the null pointer, then |
804 | \a pt is interpreted as relative to the widget provided when instantiating this QTouchEventSequence. |
805 | |
806 | Simulates that the user lifted the finger identified by \a touchId. |
807 | */ |
808 | |
809 | /*! |
810 | \fn QTouchEventSequence &QTest::QTouchEventSequence::stationary(int touchId) |
811 | |
812 | Adds a stationary event for touchpoint \a touchId to this sequence and returns |
813 | a reference to this QTouchEventSequence. |
814 | |
815 | Simulates that the user did not move the finger identified by \a touchId. |
816 | */ |
817 | |
818 | /*! |
819 | \fn QTouchEventSequence QTest::touchEvent(QWidget *widget, QTouchEvent::DeviceType deviceType) |
820 | |
821 | Creates and returns a QTouchEventSequence for the device \a deviceType to |
822 | simulate events for \a widget. |
823 | |
824 | When adding touch events to the sequence, \a widget will also be used to translate |
825 | the position provided to screen coordinates, unless another widget is provided in the |
826 | respective calls to press(), move() etc. |
827 | |
828 | The touch events are committed to the event system when the destructor of the |
829 | QTouchEventSequence is called (ie when the object returned runs out of scope). |
830 | */ |
831 | |
832 | namespace QTest |
833 | { |
834 | static QObject *currentTestObject = 0; |
835 | |
836 | class TestFunction { |
837 | public: |
838 | TestFunction() : function_(-1), data_(0) {} |
839 | void set(int function, char *data) { function_ = function; data_ = data; } |
840 | char *data() const { return data_; } |
841 | int function() const { return function_; } |
842 | ~TestFunction() { delete[] data_; } |
843 | private: |
844 | int function_; |
845 | char *data_; |
846 | }; |
847 | /** |
848 | * Contains the list of test functions that was supplied |
849 | * on the command line, if any. Hence, if not empty, |
850 | * those functions should be run instead of |
851 | * all appearing in the test case. |
852 | */ |
853 | static TestFunction * testFuncs = 0; |
854 | static int testFuncCount = 0; |
855 | |
856 | /** Don't leak testFuncs on exit even on error */ |
857 | static struct TestFuncCleanup |
858 | { |
859 | void cleanup() |
860 | { |
861 | delete[] testFuncs; |
862 | testFuncCount = 0; |
863 | testFuncs = 0; |
864 | } |
865 | |
866 | ~TestFuncCleanup() { cleanup(); } |
867 | } testFuncCleaner; |
868 | |
869 | static int keyDelay = -1; |
870 | static int mouseDelay = -1; |
871 | static int eventDelay = -1; |
872 | static bool randomOrder = false; |
873 | static int keyVerbose = -1; |
874 | static unsigned int seed = 0; |
875 | static bool seedSet = false; |
876 | #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) |
877 | static bool noCrashHandler = false; |
878 | #endif |
879 | |
880 | void filter_unprintable(char *str) |
881 | { |
882 | char *idx = str; |
883 | while (*idx) { |
884 | if (((*idx < 0x20 && *idx != '\n' && *idx != '\t') || *idx > 0x7e)) |
885 | *idx = '?'; |
886 | ++idx; |
887 | } |
888 | } |
889 | |
890 | /*! \internal |
891 | */ |
892 | int qt_snprintf(char *str, int size, const char *format, ...) |
893 | { |
894 | va_list ap; |
895 | int res = 0; |
896 | |
897 | va_start(ap, format); |
898 | qvsnprintf(str, size, format, ap); |
899 | va_end(ap); |
900 | str[size - 1] = '\0'; |
901 | |
902 | filter_unprintable(str); |
903 | |
904 | return res; |
905 | } |
906 | |
907 | /*! \internal |
908 | Invoke a method of the object without generating warning if the method does not exist |
909 | */ |
910 | static void invokeMethod(QObject *obj, const char *methodName) |
911 | { |
912 | const QMetaObject *metaObject = obj->metaObject(); |
913 | int funcIndex = metaObject->indexOfMethod(methodName); |
914 | if (funcIndex >= 0) { |
915 | QMetaMethod method = metaObject->method(funcIndex); |
916 | method.invoke(obj, Qt::DirectConnection); |
917 | } |
918 | } |
919 | |
920 | bool Q_TESTLIB_EXPORT defaultKeyVerbose() |
921 | { |
922 | if (keyVerbose == -1) { |
923 | keyVerbose = qgetenv("QTEST_KEYEVENT_VERBOSE" ).constData() ? 1 : 0; |
924 | } |
925 | return keyVerbose == 1; |
926 | } |
927 | |
928 | int defaultEventDelay() |
929 | { |
930 | if (eventDelay == -1) { |
931 | if (qgetenv("QTEST_EVENT_DELAY" ).constData()) |
932 | eventDelay = atoi(qgetenv("QTEST_EVENT_DELAY" )); |
933 | else |
934 | eventDelay = 0; |
935 | } |
936 | return eventDelay; |
937 | } |
938 | |
939 | int Q_TESTLIB_EXPORT defaultMouseDelay() |
940 | { |
941 | if (mouseDelay == -1) { |
942 | if (qgetenv("QTEST_MOUSEEVENT_DELAY" ).constData()) |
943 | mouseDelay = atoi((qgetenv("QTEST_MOUSEEVENT_DELAY" ))); |
944 | else |
945 | mouseDelay = defaultEventDelay(); |
946 | } |
947 | return mouseDelay; |
948 | } |
949 | |
950 | int Q_TESTLIB_EXPORT defaultKeyDelay() |
951 | { |
952 | if (keyDelay == -1) { |
953 | if (qgetenv("QTEST_KEYEVENT_DELAY" ).constData()) |
954 | keyDelay = atoi(qgetenv("QTEST_KEYEVENT_DELAY" ).constData()); |
955 | else |
956 | keyDelay = defaultEventDelay(); |
957 | } |
958 | return keyDelay; |
959 | } |
960 | |
961 | void seedRandom() |
962 | { |
963 | static bool randomSeeded = false; |
964 | if (!randomSeeded) { |
965 | if (!QTest::seedSet) { |
966 | QElapsedTimer timer; |
967 | timer.start(); |
968 | QTest::seed = timer.msecsSinceReference(); |
969 | } |
970 | qsrand(QTest::seed); |
971 | randomSeeded = true; |
972 | } |
973 | } |
974 | |
975 | int qTestRandomSeed() |
976 | { |
977 | Q_ASSERT(QTest::seedSet); |
978 | return QTest::seed; |
979 | } |
980 | |
981 | template<typename T> |
982 | void swap(T * array, int pos, int otherPos) |
983 | { |
984 | T tmp = array[pos]; |
985 | array[pos] = array[otherPos]; |
986 | array[otherPos] = tmp; |
987 | } |
988 | |
989 | template<typename T> |
990 | static void randomizeList(T * array, int size) |
991 | { |
992 | for (int i = 0; i != size; i++) { |
993 | int pos = qrand() % size; |
994 | swap(array, pos, i); |
995 | } |
996 | } |
997 | |
998 | static bool isValidSlot(const QMetaMethod &sl) |
999 | { |
1000 | if (sl.access() != QMetaMethod::Private || !sl.parameterTypes().isEmpty() |
1001 | || qstrlen(sl.typeName()) || sl.methodType() != QMetaMethod::Slot) |
1002 | return false; |
1003 | const char *sig = sl.signature(); |
1004 | int len = qstrlen(sig); |
1005 | if (len < 2) |
1006 | return false; |
1007 | if (sig[len - 2] != '(' || sig[len - 1] != ')') |
1008 | return false; |
1009 | if (len > 7 && strcmp(sig + (len - 7), "_data()" ) == 0) |
1010 | return false; |
1011 | if (strcmp(sig, "initTestCase()" ) == 0 || strcmp(sig, "cleanupTestCase()" ) == 0 |
1012 | || strcmp(sig, "cleanup()" ) == 0 || strcmp(sig, "init()" ) == 0) |
1013 | return false; |
1014 | return true; |
1015 | } |
1016 | |
1017 | Q_TESTLIB_EXPORT bool printAvailableFunctions = false; |
1018 | Q_TESTLIB_EXPORT bool printAvailableTags = false; |
1019 | Q_TESTLIB_EXPORT QStringList testFunctions; |
1020 | Q_TESTLIB_EXPORT QStringList testTags; |
1021 | |
1022 | static void qPrintTestSlots() |
1023 | { |
1024 | for (int i = 0; i < QTest::currentTestObject->metaObject()->methodCount(); ++i) { |
1025 | QMetaMethod sl = QTest::currentTestObject->metaObject()->method(i); |
1026 | if (isValidSlot(sl)) |
1027 | printf("%s\n" , sl.signature()); |
1028 | } |
1029 | } |
1030 | |
1031 | static void qPrintDataTags() |
1032 | { |
1033 | // Get global data tags: |
1034 | QTestTable::globalTestTable(); |
1035 | invokeMethod(QTest::currentTestObject, "initTestCase_data()" ); |
1036 | const QTestTable *gTable = QTestTable::globalTestTable(); |
1037 | |
1038 | const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject(); |
1039 | |
1040 | // Process test functions: |
1041 | for (int i = 0; i < currTestMetaObj->methodCount(); ++i) { |
1042 | QMetaMethod tf = currTestMetaObj->method(i); |
1043 | if (isValidSlot(tf)) { |
1044 | // Retrieve local tags: |
1045 | QStringList localTags; |
1046 | QTestTable table; |
1047 | char member[512]; |
1048 | char *slot = qstrdup(tf.signature()); |
1049 | slot[strlen(slot) - 2] = '\0'; |
1050 | QTest::qt_snprintf(member, 512, "%s_data()" , slot); |
1051 | invokeMethod(QTest::currentTestObject, member); |
1052 | for (int j = 0; j < table.dataCount(); ++j) |
1053 | localTags << QLatin1String(table.testData(j)->dataTag()); |
1054 | |
1055 | // Print all tag combinations: |
1056 | if (gTable->dataCount() == 0) { |
1057 | if (localTags.count() == 0) { |
1058 | // No tags at all, so just print the test function: |
1059 | printf("%s %s\n" , currTestMetaObj->className(), slot); |
1060 | } else { |
1061 | // Only local tags, so print each of them: |
1062 | for (int k = 0; k < localTags.size(); ++k) |
1063 | printf( |
1064 | "%s %s %s\n" , |
1065 | currTestMetaObj->className(), slot, localTags.at(k).toLatin1().data()); |
1066 | } |
1067 | } else { |
1068 | for (int j = 0; j < gTable->dataCount(); ++j) { |
1069 | if (localTags.count() == 0) { |
1070 | // Only global tags, so print the current one: |
1071 | printf( |
1072 | "%s %s __global__ %s\n" , |
1073 | currTestMetaObj->className(), slot, gTable->testData(j)->dataTag()); |
1074 | } else { |
1075 | // Local and global tags, so print each of the local ones and |
1076 | // the current global one: |
1077 | for (int k = 0; k < localTags.size(); ++k) |
1078 | printf( |
1079 | "%s %s %s __global__ %s\n" , currTestMetaObj->className(), slot, |
1080 | localTags.at(k).toLatin1().data(), gTable->testData(j)->dataTag()); |
1081 | } |
1082 | } |
1083 | } |
1084 | |
1085 | delete[] slot; |
1086 | } |
1087 | } |
1088 | } |
1089 | |
1090 | static int qToInt(char *str) |
1091 | { |
1092 | char *pEnd; |
1093 | int l = (int)strtol(str, &pEnd, 10); |
1094 | if (*pEnd != 0) { |
1095 | printf("Invalid numeric parameter: '%s'\n" , str); |
1096 | exit(1); |
1097 | } |
1098 | return l; |
1099 | } |
1100 | |
1101 | Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) |
1102 | { |
1103 | const char *testOptions = |
1104 | " options:\n" |
1105 | " -functions : Returns a list of current testfunctions\n" |
1106 | " -datatags : Returns a list of current data tags.\n" |
1107 | " A global data tag is preceded by ' __global__ '.\n" |
1108 | " -xunitxml : Outputs results as XML XUnit document\n" |
1109 | " -xml : Outputs results as XML document\n" |
1110 | " -lightxml : Outputs results as stream of XML tags\n" |
1111 | " -flush : Flushes the results\n" |
1112 | " -o filename: Writes all output into a file\n" |
1113 | " -silent : Only outputs warnings and failures\n" |
1114 | " -v1 : Print enter messages for each testfunction\n" |
1115 | " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n" |
1116 | " -vs : Print every signal emitted\n" |
1117 | " -random : Run testcases within each test in random order\n" |
1118 | " -seed n : Positive integer to be used as seed for -random. If not specified,\n" |
1119 | " the current time will be used as seed.\n" |
1120 | " -eventdelay ms : Set default delay for mouse and keyboard simulation to ms milliseconds\n" |
1121 | " -keydelay ms : Set default delay for keyboard simulation to ms milliseconds\n" |
1122 | " -mousedelay ms : Set default delay for mouse simulation to ms milliseconds\n" |
1123 | " -keyevent-verbose : Turn on verbose messages for keyboard simulation\n" |
1124 | " -maxwarnings n : Sets the maximum amount of messages to output.\n" |
1125 | " 0 means unlimited, default: 2000\n" |
1126 | #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) |
1127 | " -nocrashhandler : Disables the crash handler\n" |
1128 | #endif |
1129 | "\n" |
1130 | " Benchmark related options:\n" |
1131 | #ifdef QTESTLIB_USE_VALGRIND |
1132 | " -callgrind : Use callgrind to time benchmarks\n" |
1133 | #endif |
1134 | #ifdef HAVE_TICK_COUNTER |
1135 | " -tickcounter : Use CPU tick counters to time benchmarks\n" |
1136 | #endif |
1137 | " -eventcounter : Counts events received during benchmarks\n" |
1138 | " -minimumvalue n : Sets the minimum acceptable measurement value\n" |
1139 | " -iterations n : Sets the number of accumulation iterations.\n" |
1140 | " -median n : Sets the number of median iterations.\n" |
1141 | " -vb : Print out verbose benchmarking information.\n" |
1142 | "\n" |
1143 | " -help : This help\n" ; |
1144 | |
1145 | for (int i = 1; i < argc; ++i) { |
1146 | if (strcmp(argv[i], "-help" ) == 0 || strcmp(argv[i], "--help" ) == 0 |
1147 | || strcmp(argv[i], "/?" ) == 0) { |
1148 | printf(" Usage: %s [options] [testfunction[:testdata]]...\n" |
1149 | " By default, all testfunctions will be run.\n\n" |
1150 | "%s" , argv[0], testOptions); |
1151 | exit(0); |
1152 | } else if (strcmp(argv[i], "-functions" ) == 0) { |
1153 | if (qml) { |
1154 | QTest::printAvailableFunctions = true; |
1155 | } else { |
1156 | qPrintTestSlots(); |
1157 | exit(0); |
1158 | } |
1159 | } else if (strcmp(argv[i], "-datatags" ) == 0) { |
1160 | QTest::printAvailableTags = true; |
1161 | if (!qml) { |
1162 | qPrintDataTags(); |
1163 | exit(0); |
1164 | } |
1165 | } else if(strcmp(argv[i], "-xunitxml" ) == 0){ |
1166 | QTestLog::setLogMode(QTestLog::XunitXML); |
1167 | } else if (strcmp(argv[i], "-xml" ) == 0) { |
1168 | QTestLog::setLogMode(QTestLog::XML); |
1169 | } else if (strcmp(argv[i], "-lightxml" ) == 0) { |
1170 | QTestLog::setLogMode(QTestLog::LightXML); |
1171 | }else if(strcmp(argv[i], "-flush" ) == 0){ |
1172 | QTestLog::setFlushMode(QTestLog::FLushOn); |
1173 | } else if (strcmp(argv[i], "-silent" ) == 0) { |
1174 | QTestLog::setVerboseLevel(-1); |
1175 | } else if (strcmp(argv[i], "-v1" ) == 0) { |
1176 | QTestLog::setVerboseLevel(1); |
1177 | } else if (strcmp(argv[i], "-v2" ) == 0) { |
1178 | QTestLog::setVerboseLevel(2); |
1179 | } else if (strcmp(argv[i], "-vs" ) == 0) { |
1180 | QSignalDumper::startDump(); |
1181 | } else if (strcmp(argv[i], "-o" ) == 0) { |
1182 | if (i + 1 >= argc) { |
1183 | printf("-o needs an extra parameter specifying the filename\n" ); |
1184 | exit(1); |
1185 | } else { |
1186 | QTestLog::redirectOutput(argv[++i]); |
1187 | } |
1188 | } else if (strcmp(argv[i], "-eventdelay" ) == 0) { |
1189 | if (i + 1 >= argc) { |
1190 | printf("-eventdelay needs an extra parameter to indicate the delay(ms)\n" ); |
1191 | exit(1); |
1192 | } else { |
1193 | QTest::eventDelay = qToInt(argv[++i]); |
1194 | } |
1195 | } else if (strcmp(argv[i], "-keydelay" ) == 0) { |
1196 | if (i + 1 >= argc) { |
1197 | printf("-keydelay needs an extra parameter to indicate the delay(ms)\n" ); |
1198 | exit(1); |
1199 | } else { |
1200 | QTest::keyDelay = qToInt(argv[++i]); |
1201 | } |
1202 | } else if (strcmp(argv[i], "-mousedelay" ) == 0) { |
1203 | if (i + 1 >= argc) { |
1204 | printf("-mousedelay needs an extra parameter to indicate the delay(ms)\n" ); |
1205 | exit(1); |
1206 | } else { |
1207 | QTest::mouseDelay = qToInt(argv[++i]); |
1208 | } |
1209 | } else if (strcmp(argv[i], "-maxwarnings" ) == 0) { |
1210 | if (i + 1 >= argc) { |
1211 | printf("-maxwarnings needs an extra parameter with the amount of warnings\n" ); |
1212 | exit(1); |
1213 | } else { |
1214 | QTestLog::setMaxWarnings(qToInt(argv[++i])); |
1215 | } |
1216 | #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) |
1217 | } else if (strcmp(argv[i], "-nocrashhandler" ) == 0) { |
1218 | QTest::noCrashHandler = true; |
1219 | #endif |
1220 | } else if (strcmp(argv[i], "-keyevent-verbose" ) == 0) { |
1221 | QTest::keyVerbose = 1; |
1222 | #ifdef QTESTLIB_USE_VALGRIND |
1223 | } else if (strcmp(argv[i], "-callgrind" ) == 0) { |
1224 | if (QBenchmarkValgrindUtils::haveValgrind()) |
1225 | if (QFileInfo(QDir::currentPath()).isWritable()) { |
1226 | QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindParentProcess); |
1227 | } else { |
1228 | printf("WARNING: Current directory not writable. Using the walltime measurer.\n" ); |
1229 | } |
1230 | else { |
1231 | printf("WARNING: Valgrind not found or too old. Make sure it is installed and in your path. " |
1232 | "Using the walltime measurer.\n" ); |
1233 | } |
1234 | } else if (strcmp(argv[i], "-callgrindchild" ) == 0) { // "private" option |
1235 | QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::CallgrindChildProcess); |
1236 | QBenchmarkGlobalData::current->callgrindOutFileBase = |
1237 | QBenchmarkValgrindUtils::outFileBase(); |
1238 | #endif |
1239 | #ifdef HAVE_TICK_COUNTER |
1240 | } else if (strcmp(argv[i], "-tickcounter" ) == 0) { |
1241 | QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::TickCounter); |
1242 | #endif |
1243 | } else if (strcmp(argv[i], "-eventcounter" ) == 0) { |
1244 | QBenchmarkGlobalData::current->setMode(QBenchmarkGlobalData::EventCounter); |
1245 | } else if (strcmp(argv[i], "-random" ) == 0) { |
1246 | QTest::randomOrder = true; |
1247 | } else if (strcmp(argv[i], "-seed" ) == 0) { |
1248 | bool argumentOk = false; |
1249 | if (i + 1 < argc) { |
1250 | char * endpt = 0; |
1251 | long longSeed = strtol(argv[++i], &endpt, 10); |
1252 | argumentOk = (*endpt == '\0' && longSeed >= 0); |
1253 | QTest::seed = longSeed; |
1254 | } |
1255 | if (!argumentOk) { |
1256 | printf("-seed needs an extra positive integer parameter to specify the seed\n" ); |
1257 | exit(1); |
1258 | } else { |
1259 | QTest::seedSet = true; |
1260 | } |
1261 | } else if (strcmp(argv[i], "-minimumvalue" ) == 0) { |
1262 | if (i + 1 >= argc) { |
1263 | printf("-minimumvalue needs an extra parameter to indicate the minimum time(ms)\n" ); |
1264 | exit(1); |
1265 | } else { |
1266 | QBenchmarkGlobalData::current->walltimeMinimum = qToInt(argv[++i]); |
1267 | } |
1268 | } else if (strcmp(argv[i], "-iterations" ) == 0) { |
1269 | if (i + 1 >= argc) { |
1270 | printf("-iterations needs an extra parameter to indicate the number of iterations\n" ); |
1271 | exit(1); |
1272 | } else { |
1273 | QBenchmarkGlobalData::current->iterationCount = qToInt(argv[++i]); |
1274 | } |
1275 | } else if (strcmp(argv[i], "-median" ) == 0) { |
1276 | if (i + 1 >= argc) { |
1277 | printf("-median needs an extra parameter to indicate the number of median iterations\n" ); |
1278 | exit(1); |
1279 | } else { |
1280 | QBenchmarkGlobalData::current->medianIterationCount = qToInt(argv[++i]); |
1281 | } |
1282 | |
1283 | } else if (strcmp(argv[i], "-vb" ) == 0) { |
1284 | QBenchmarkGlobalData::current->verboseOutput = true; |
1285 | } else if (strcmp(argv[i], "-chart" ) == 0) { |
1286 | fprintf(stderr, "Warning: `-chart' option is not available\n" ); |
1287 | } else if (strcmp(argv[i], "-qws" ) == 0) { |
1288 | // do nothing |
1289 | } else if (strcmp(argv[i], "-graphicssystem" ) == 0) { |
1290 | // do nothing |
1291 | if (i + 1 >= argc) { |
1292 | printf("-graphicssystem needs an extra parameter specifying the graphics system\n" ); |
1293 | exit(1); |
1294 | } else { |
1295 | ++i; |
1296 | } |
1297 | } else if (argv[i][0] == '-') { |
1298 | printf("Unknown option: '%s'\n\n%s" , argv[i], testOptions); |
1299 | exit(1); |
1300 | } else if (qml) { |
1301 | // We can't check the availability of test functions until |
1302 | // we load the QML files. So just store the data for now. |
1303 | int colon = -1; |
1304 | int offset; |
1305 | for(offset = 0; *(argv[i]+offset); ++offset) { |
1306 | if (*(argv[i]+offset) == ':') { |
1307 | if (*(argv[i]+offset+1) == ':') { |
1308 | // "::" is used as a test name separator. |
1309 | // e.g. "ClickTests::test_click:row1". |
1310 | ++offset; |
1311 | } else { |
1312 | colon = offset; |
1313 | break; |
1314 | } |
1315 | } |
1316 | } |
1317 | if (colon == -1) { |
1318 | QTest::testFunctions += QString::fromLatin1(argv[i]); |
1319 | QTest::testTags += QString(); |
1320 | } else { |
1321 | QTest::testFunctions += |
1322 | QString::fromLatin1(argv[i], colon); |
1323 | QTest::testTags += |
1324 | QString::fromLatin1(argv[i] + colon + 1); |
1325 | } |
1326 | } else { |
1327 | if (!QTest::testFuncs) { |
1328 | QTest::testFuncs = new QTest::TestFunction[512]; |
1329 | } |
1330 | |
1331 | int colon = -1; |
1332 | char buf[512], *data=0; |
1333 | int off; |
1334 | for(off = 0; *(argv[i]+off); ++off) { |
1335 | if (*(argv[i]+off) == ':') { |
1336 | colon = off; |
1337 | break; |
1338 | } |
1339 | } |
1340 | if(colon != -1) { |
1341 | data = qstrdup(argv[i]+colon+1); |
1342 | } |
1343 | QTest::qt_snprintf(buf, qMin(512, off + 1), "%s" , argv[i]); // copy text before the ':' into buf |
1344 | QTest::qt_snprintf(buf + off, qMin(512 - off, 3), "()" ); // append "()" |
1345 | int idx = QTest::currentTestObject->metaObject()->indexOfMethod(buf); |
1346 | if (idx < 0 || !isValidSlot(QTest::currentTestObject->metaObject()->method(idx))) { |
1347 | printf("Unknown testfunction: '%s'\n" , buf); |
1348 | printf("Available testfunctions:\n" ); |
1349 | qPrintTestSlots(); |
1350 | exit(1); |
1351 | } |
1352 | testFuncs[testFuncCount].set(idx, data); |
1353 | testFuncCount++; |
1354 | QTEST_ASSERT(QTest::testFuncCount < 512); |
1355 | } |
1356 | } |
1357 | |
1358 | if (QTest::seedSet && !QTest::randomOrder) { |
1359 | printf("-seed requires -random\n" ); |
1360 | exit(1); |
1361 | } |
1362 | } |
1363 | |
1364 | QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container) |
1365 | { |
1366 | const int count = container.count(); |
1367 | if (count == 0) |
1368 | return QBenchmarkResult(); |
1369 | |
1370 | if (count == 1) |
1371 | return container.at(0); |
1372 | |
1373 | QList<QBenchmarkResult> containerCopy = container; |
1374 | qSort(containerCopy); |
1375 | |
1376 | const int middle = count / 2; |
1377 | |
1378 | // ### handle even-sized containers here by doing an aritmetic mean of the two middle items. |
1379 | return containerCopy.at(middle); |
1380 | } |
1381 | |
1382 | struct QTestDataSetter |
1383 | { |
1384 | QTestDataSetter(QTestData *data) |
1385 | { |
1386 | QTestResult::setCurrentTestData(data); |
1387 | } |
1388 | ~QTestDataSetter() |
1389 | { |
1390 | QTestResult::setCurrentTestData(0); |
1391 | } |
1392 | }; |
1393 | |
1394 | static void qInvokeTestMethodDataEntry(char *slot) |
1395 | { |
1396 | /* Benchmarking: for each median iteration*/ |
1397 | |
1398 | int i = (QBenchmarkGlobalData::current->measurer->needsWarmupIteration()) ? -1 : 0; |
1399 | |
1400 | QList<QBenchmarkResult> results; |
1401 | do { |
1402 | QBenchmarkTestMethodData::current->beginDataRun(); |
1403 | |
1404 | /* Benchmarking: for each accumulation iteration*/ |
1405 | bool invokeOk; |
1406 | do { |
1407 | QTestResult::setCurrentTestLocation(QTestResult::InitFunc); |
1408 | invokeMethod(QTest::currentTestObject, "init()" ); |
1409 | if (QTestResult::skipCurrentTest()) |
1410 | break; |
1411 | |
1412 | QTestResult::setCurrentTestLocation(QTestResult::Func); |
1413 | |
1414 | QBenchmarkTestMethodData::current->result = QBenchmarkResult(); |
1415 | QBenchmarkTestMethodData::current->resultAccepted = false; |
1416 | |
1417 | QBenchmarkGlobalData::current->context.tag = |
1418 | QLatin1String( |
1419 | QTestResult::currentDataTag() |
1420 | ? QTestResult::currentDataTag() : "" ); |
1421 | |
1422 | invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot, |
1423 | Qt::DirectConnection); |
1424 | if (!invokeOk) |
1425 | QTestResult::addFailure("Unable to execute slot" , __FILE__, __LINE__); |
1426 | |
1427 | QTestResult::setCurrentTestLocation(QTestResult::CleanupFunc); |
1428 | invokeMethod(QTest::currentTestObject, "cleanup()" ); |
1429 | QTestResult::setCurrentTestLocation(QTestResult::NoWhere); |
1430 | |
1431 | // If this test method has a benchmark, repeat until all measurements are |
1432 | // acceptable. |
1433 | // The QBENCHMARK macro increases the number of iterations for each run until |
1434 | // this happens. |
1435 | } while (invokeOk |
1436 | && QBenchmarkTestMethodData::current->isBenchmark() |
1437 | && QBenchmarkTestMethodData::current->resultsAccepted() == false); |
1438 | |
1439 | QBenchmarkTestMethodData::current->endDataRun(); |
1440 | if (i > -1) // iteration -1 is the warmup iteration. |
1441 | results.append(QBenchmarkTestMethodData::current->result); |
1442 | |
1443 | if (QBenchmarkTestMethodData::current->isBenchmark() && |
1444 | QBenchmarkGlobalData::current->verboseOutput) { |
1445 | if (i == -1) { |
1446 | qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value; |
1447 | } else { |
1448 | qDebug() << "accumulation stage result:" << QBenchmarkTestMethodData::current->result.value; |
1449 | } |
1450 | } |
1451 | } while (QBenchmarkTestMethodData::current->isBenchmark() |
1452 | && (++i < QBenchmarkGlobalData::current->adjustMedianIterationCount())); |
1453 | |
1454 | if (QBenchmarkTestMethodData::current->isBenchmark() |
1455 | && QBenchmarkTestMethodData::current->resultsAccepted()) |
1456 | QTestLog::addBenchmarkResult(qMedian(results)); |
1457 | } |
1458 | |
1459 | /*! |
1460 | \internal |
1461 | |
1462 | Call init(), slot_data(), slot(), slot(), slot()..., cleanup() |
1463 | If data is set then it is the only test that is performed |
1464 | |
1465 | If the function was successfully called, true is returned, otherwise |
1466 | false. |
1467 | */ |
1468 | static bool qInvokeTestMethod(const char *slotName, const char *data=0) |
1469 | { |
1470 | QTEST_ASSERT(slotName); |
1471 | |
1472 | QBenchmarkTestMethodData benchmarkData; |
1473 | QBenchmarkTestMethodData::current = &benchmarkData; |
1474 | |
1475 | QBenchmarkGlobalData::current->context.slotName = QLatin1String(slotName); |
1476 | |
1477 | char member[512]; |
1478 | QTestTable table; |
1479 | |
1480 | char *slot = qstrdup(slotName); |
1481 | slot[strlen(slot) - 2] = '\0'; |
1482 | QTestResult::setCurrentTestFunction(slot); |
1483 | |
1484 | const QTestTable *gTable = QTestTable::globalTestTable(); |
1485 | const int globalDataCount = gTable->dataCount(); |
1486 | int curGlobalDataIndex = 0; |
1487 | |
1488 | /* For each test function that has a *_data() table/function, do: */ |
1489 | do { |
1490 | if (!gTable->isEmpty()) |
1491 | QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex)); |
1492 | |
1493 | if (curGlobalDataIndex == 0) { |
1494 | QTestResult::setCurrentTestLocation(QTestResult::DataFunc); |
1495 | QTest::qt_snprintf(member, 512, "%s_data()" , slot); |
1496 | invokeMethod(QTest::currentTestObject, member); |
1497 | |
1498 | // if we encounter a SkipAll in the _data slot, we skip the whole |
1499 | // testfunction, no matter how much global data exists |
1500 | if (QTestResult::skipCurrentTest()) { |
1501 | QTestResult::setCurrentGlobalTestData(0); |
1502 | break; |
1503 | } |
1504 | } |
1505 | |
1506 | bool foundFunction = false; |
1507 | if (!QTestResult::skipCurrentTest()) { |
1508 | int curDataIndex = 0; |
1509 | const int dataCount = table.dataCount(); |
1510 | QTestResult::setSkipCurrentTest(false); |
1511 | |
1512 | // Data tag requested but none available? |
1513 | if (data && !dataCount) { |
1514 | // Let empty data tag through. |
1515 | if (!*data) |
1516 | data = 0; |
1517 | else { |
1518 | printf("Unknown testdata for function %s: '%s'\n" , slotName, data); |
1519 | printf("Function has no testdata.\n" ); |
1520 | return false; |
1521 | } |
1522 | } |
1523 | |
1524 | /* For each entry in the data table, do: */ |
1525 | do { |
1526 | if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) { |
1527 | foundFunction = true; |
1528 | QTestDataSetter s(curDataIndex >= dataCount ? static_cast<QTestData *>(0) |
1529 | : table.testData(curDataIndex)); |
1530 | |
1531 | qInvokeTestMethodDataEntry(slot); |
1532 | |
1533 | if (QTestResult::skipCurrentTest()) |
1534 | // check whether SkipAll was requested |
1535 | break; |
1536 | if (data) |
1537 | break; |
1538 | } |
1539 | ++curDataIndex; |
1540 | } while (curDataIndex < dataCount); |
1541 | } |
1542 | |
1543 | if (data && !foundFunction) { |
1544 | printf("Unknown testdata for function %s: '%s'\n" , slotName, data); |
1545 | printf("Available testdata:\n" ); |
1546 | for(int i = 0; i < table.dataCount(); ++i) |
1547 | printf("%s\n" , table.testData(i)->dataTag()); |
1548 | return false; |
1549 | } |
1550 | |
1551 | QTestResult::setCurrentGlobalTestData(0); |
1552 | ++curGlobalDataIndex; |
1553 | } while (curGlobalDataIndex < globalDataCount); |
1554 | |
1555 | QTestResult::finishedCurrentTestFunction(); |
1556 | QTestResult::setSkipCurrentTest(false); |
1557 | QTestResult::setCurrentTestData(0); |
1558 | delete[] slot; |
1559 | |
1560 | return true; |
1561 | } |
1562 | |
1563 | void *fetchData(QTestData *data, const char *tagName, int typeId) |
1564 | { |
1565 | QTEST_ASSERT(typeId); |
1566 | QTEST_ASSERT_X(data, "QTest::fetchData()" , "Test data requested, but no testdata available." ); |
1567 | QTEST_ASSERT(data->parent()); |
1568 | |
1569 | int idx = data->parent()->indexOf(tagName); |
1570 | |
1571 | if (idx == -1 || idx >= data->dataCount()) { |
1572 | qFatal("QFETCH: Requested testdata '%s' not available, check your _data function." , |
1573 | tagName); |
1574 | } |
1575 | |
1576 | if (typeId != data->parent()->elementTypeId(idx)) { |
1577 | qFatal("Requested type '%s' does not match available type '%s'." , |
1578 | QMetaType::typeName(typeId), |
1579 | QMetaType::typeName(data->parent()->elementTypeId(idx))); |
1580 | } |
1581 | |
1582 | return data->data(idx); |
1583 | } |
1584 | |
1585 | /*! |
1586 | \fn char* QTest::toHexRepresentation(const char *ba, int length) |
1587 | |
1588 | Returns a pointer to a string that is the string \a ba represented |
1589 | as a space-separated sequence of hex characters. If the input is |
1590 | considered too long, it is truncated. A trucation is indicated in |
1591 | the returned string as an ellipsis at the end. |
1592 | |
1593 | \a length is the length of the string \a ba. |
1594 | */ |
1595 | char *toHexRepresentation(const char *ba, int length) |
1596 | { |
1597 | if(length == 0) |
1598 | return qstrdup("" ); |
1599 | |
1600 | /* We output at maximum about maxLen characters in order to avoid |
1601 | * running out of memory and flooding things when the byte array |
1602 | * is large. |
1603 | * |
1604 | * maxLen can't be for example 200 because QTestLib is sprinkled with fixed |
1605 | * size char arrays. |
1606 | * */ |
1607 | const int maxLen = 50; |
1608 | const int len = qMin(maxLen, length); |
1609 | char *result = 0; |
1610 | |
1611 | if(length > maxLen) { |
1612 | const int size = len * 3 + 4; |
1613 | result = new char[size]; |
1614 | |
1615 | char *const forElipsis = result + size - 5; |
1616 | forElipsis[0] = ' '; |
1617 | forElipsis[1] = '.'; |
1618 | forElipsis[2] = '.'; |
1619 | forElipsis[3] = '.'; |
1620 | result[size - 1] = '\0'; |
1621 | } |
1622 | else { |
1623 | const int size = len * 3; |
1624 | result = new char[size]; |
1625 | result[size - 1] = '\0'; |
1626 | } |
1627 | |
1628 | const char toHex[] = "0123456789ABCDEF" ; |
1629 | int i = 0; |
1630 | int o = 0; |
1631 | |
1632 | while(true) { |
1633 | const char at = ba[i]; |
1634 | |
1635 | result[o] = toHex[(at >> 4) & 0x0F]; |
1636 | ++o; |
1637 | result[o] = toHex[at & 0x0F]; |
1638 | |
1639 | ++i; |
1640 | ++o; |
1641 | if(i == len) |
1642 | break; |
1643 | else { |
1644 | result[o] = ' '; |
1645 | ++o; |
1646 | } |
1647 | } |
1648 | |
1649 | return result; |
1650 | } |
1651 | |
1652 | static void qInvokeTestMethods(QObject *testObject) |
1653 | { |
1654 | const QMetaObject *metaObject = testObject->metaObject(); |
1655 | QTEST_ASSERT(metaObject); |
1656 | if (QTest::randomOrder) { |
1657 | QTestLog::startLogging(QTest::seed); |
1658 | } else { |
1659 | QTestLog::startLogging(); |
1660 | } |
1661 | QTestResult::setCurrentTestFunction("initTestCase" ); |
1662 | QTestResult::setCurrentTestLocation(QTestResult::DataFunc); |
1663 | QTestTable::globalTestTable(); |
1664 | invokeMethod(testObject, "initTestCase_data()" ); |
1665 | |
1666 | if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { |
1667 | QTestResult::setCurrentTestLocation(QTestResult::InitFunc); |
1668 | invokeMethod(testObject, "initTestCase()" ); |
1669 | |
1670 | // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy. |
1671 | const bool previousFailed = QTestResult::testFailed(); |
1672 | QTestResult::finishedCurrentTestFunction(); |
1673 | |
1674 | if(!QTestResult::skipCurrentTest() && !previousFailed) { |
1675 | |
1676 | if (QTest::testFuncs) { |
1677 | if (QTest::randomOrder) |
1678 | randomizeList(QTest::testFuncs, QTest::testFuncCount); |
1679 | for (int i = 0; i != QTest::testFuncCount; i++) { |
1680 | if (!qInvokeTestMethod(metaObject->method(QTest::testFuncs[i].function()).signature(), |
1681 | QTest::testFuncs[i].data())) { |
1682 | break; |
1683 | } |
1684 | } |
1685 | testFuncCleaner.cleanup(); |
1686 | } else { |
1687 | int methodCount = metaObject->methodCount(); |
1688 | QMetaMethod *testMethods = new QMetaMethod[methodCount]; |
1689 | for (int i = 0; i != methodCount; i++) |
1690 | testMethods[i] = metaObject->method(i); |
1691 | if (QTest::randomOrder) |
1692 | randomizeList(testMethods, methodCount); |
1693 | for (int i = 0; i != methodCount; i++) { |
1694 | if (!isValidSlot(testMethods[i])) |
1695 | continue; |
1696 | if (!qInvokeTestMethod(testMethods[i].signature())) |
1697 | break; |
1698 | } |
1699 | delete[] testMethods; |
1700 | testMethods = 0; |
1701 | } |
1702 | } |
1703 | |
1704 | QTestResult::setSkipCurrentTest(false); |
1705 | QTestResult::setCurrentTestFunction("cleanupTestCase" ); |
1706 | invokeMethod(testObject, "cleanupTestCase()" ); |
1707 | } |
1708 | QTestResult::finishedCurrentTestFunction(); |
1709 | QTestResult::setCurrentTestFunction(0); |
1710 | QTestTable::clearGlobalTestTable(); |
1711 | |
1712 | QTestLog::stopLogging(); |
1713 | } |
1714 | |
1715 | #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) |
1716 | class FatalSignalHandler |
1717 | { |
1718 | public: |
1719 | FatalSignalHandler(); |
1720 | ~FatalSignalHandler(); |
1721 | |
1722 | private: |
1723 | static void signal(int); |
1724 | sigset_t handledSignals; |
1725 | }; |
1726 | |
1727 | void FatalSignalHandler::signal(int signum) |
1728 | { |
1729 | qFatal("Received signal %d" , signum); |
1730 | #if defined(Q_OS_INTEGRITY) |
1731 | { |
1732 | struct sigaction act; |
1733 | memset(&act, 0, sizeof(struct sigaction)); |
1734 | act.sa_handler = SIG_DFL; |
1735 | sigaction(signum, &act, NULL); |
1736 | } |
1737 | #endif |
1738 | } |
1739 | |
1740 | FatalSignalHandler::FatalSignalHandler() |
1741 | { |
1742 | sigemptyset(&handledSignals); |
1743 | |
1744 | const int fatalSignals[] = { |
1745 | SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, 0 }; |
1746 | |
1747 | struct sigaction act; |
1748 | memset(&act, 0, sizeof(act)); |
1749 | act.sa_handler = FatalSignalHandler::signal; |
1750 | |
1751 | // Remove the handler after it is invoked. |
1752 | #if !defined(Q_OS_INTEGRITY) |
1753 | act.sa_flags = SA_RESETHAND; |
1754 | #endif |
1755 | // Block all fatal signals in our signal handler so we don't try to close |
1756 | // the testlog twice. |
1757 | sigemptyset(&act.sa_mask); |
1758 | for (int i = 0; fatalSignals[i]; ++i) |
1759 | sigaddset(&act.sa_mask, fatalSignals[i]); |
1760 | |
1761 | struct sigaction oldact; |
1762 | |
1763 | for (int i = 0; fatalSignals[i]; ++i) { |
1764 | sigaction(fatalSignals[i], &act, &oldact); |
1765 | #ifndef Q_WS_QWS |
1766 | // Don't overwrite any non-default handlers |
1767 | // however, we need to replace the default QWS handlers |
1768 | if ( |
1769 | #ifdef SA_SIGINFO |
1770 | oldact.sa_flags & SA_SIGINFO || |
1771 | #endif |
1772 | oldact.sa_handler != SIG_DFL) { |
1773 | sigaction(fatalSignals[i], &oldact, 0); |
1774 | } else |
1775 | #endif |
1776 | { |
1777 | sigaddset(&handledSignals, fatalSignals[i]); |
1778 | } |
1779 | } |
1780 | } |
1781 | |
1782 | |
1783 | FatalSignalHandler::~FatalSignalHandler() |
1784 | { |
1785 | // Unregister any of our remaining signal handlers |
1786 | struct sigaction act; |
1787 | memset(&act, 0, sizeof(act)); |
1788 | act.sa_handler = SIG_DFL; |
1789 | |
1790 | struct sigaction oldact; |
1791 | |
1792 | for (int i = 1; i < 32; ++i) { |
1793 | if (!sigismember(&handledSignals, i)) |
1794 | continue; |
1795 | sigaction(i, &act, &oldact); |
1796 | |
1797 | // If someone overwrote it in the mean time, put it back |
1798 | if (oldact.sa_handler != FatalSignalHandler::signal) |
1799 | sigaction(i, &oldact, 0); |
1800 | } |
1801 | } |
1802 | |
1803 | #endif |
1804 | |
1805 | |
1806 | } // namespace |
1807 | |
1808 | /*! |
1809 | Executes tests declared in \a testObject. In addition, the private slots |
1810 | \c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()} |
1811 | are executed if they exist. See \l{Creating a Test} for more details. |
1812 | |
1813 | Optionally, the command line arguments \a argc and \a argv can be provided. |
1814 | For a list of recognized arguments, read \l {QTestLib Command Line Arguments}. |
1815 | |
1816 | For stand-alone tests, the convenience macro \l QTEST_MAIN() can |
1817 | be used to declare a main method that parses the command line arguments |
1818 | and executes the tests. |
1819 | |
1820 | Returns 0 if all tests passed. Returns a value other than 0 if tests failed |
1821 | or in case of unhandled exceptions. The return value from this function is |
1822 | also the exit code of the test application when the \l QTEST_MAIN() macro |
1823 | is used. |
1824 | |
1825 | The following example will run all tests in \c MyFirstTestObject and |
1826 | \c{MySecondTestObject}: |
1827 | |
1828 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 18 |
1829 | |
1830 | Note: This function is not reentrant, only one test can run at a time. A |
1831 | test that was executed with qExec() can't run another test via qExec() and |
1832 | threads are not allowed to call qExec() simultaneously. |
1833 | |
1834 | If you have programatically created the arguments, as opposed to getting them |
1835 | from the arguments in \c main(), it is likely of interest to use |
1836 | QTest::qExec(QObject *, const QStringList &) since it is Unicode safe. |
1837 | |
1838 | \sa QTEST_MAIN() |
1839 | */ |
1840 | |
1841 | int QTest::qExec(QObject *testObject, int argc, char **argv) |
1842 | { |
1843 | QBenchmarkGlobalData benchmarkData; |
1844 | QBenchmarkGlobalData::current = &benchmarkData; |
1845 | |
1846 | #ifdef QTESTLIB_USE_VALGRIND |
1847 | int callgrindChildExitCode = 0; |
1848 | #endif |
1849 | |
1850 | #ifdef Q_WS_MAC |
1851 | bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication" ) == 0); |
1852 | #ifdef QT_MAC_USE_COCOA |
1853 | IOPMAssertionID powerID; |
1854 | #endif |
1855 | #endif |
1856 | #ifndef QT_NO_EXCEPTIONS |
1857 | try { |
1858 | #endif |
1859 | |
1860 | #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
1861 | SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX); |
1862 | #endif |
1863 | |
1864 | #ifdef Q_WS_MAC |
1865 | // Starting with Qt 4.4, applications launched from the command line |
1866 | // no longer get focus automatically. Since some tests might depend |
1867 | // on this, call SetFrontProcess here to get the pre 4.4 behavior. |
1868 | if (macNeedsActivate) { |
1869 | ProcessSerialNumber psn = { 0, kCurrentProcess }; |
1870 | SetFrontProcess(&psn); |
1871 | # ifdef QT_MAC_USE_COCOA |
1872 | IOReturn ok = IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, &powerID); |
1873 | if (ok != kIOReturnSuccess) |
1874 | macNeedsActivate = false; // no need to release the assertion on exit. |
1875 | # else |
1876 | UpdateSystemActivity(1); // Wake the display. |
1877 | # endif |
1878 | } |
1879 | #endif |
1880 | |
1881 | #if defined(Q_OS_SYMBIAN) && defined(Q_CC_NOKIAX86) |
1882 | // Delay execution of tests in Symbian emulator. |
1883 | // Needed to allow worst of other higher priority apps and services launched by emulator |
1884 | // to get out of the way before we run our test. Otherwise some of the timing sensitive tests |
1885 | // will not work properly. |
1886 | qSleep(3000); |
1887 | #endif |
1888 | |
1889 | QTestResult::reset(); |
1890 | |
1891 | QTEST_ASSERT(testObject); |
1892 | QTEST_ASSERT(!currentTestObject); |
1893 | currentTestObject = testObject; |
1894 | |
1895 | const QMetaObject *metaObject = testObject->metaObject(); |
1896 | QTEST_ASSERT(metaObject); |
1897 | |
1898 | QTestResult::setCurrentTestObject(metaObject->className()); |
1899 | if (argc > 0) |
1900 | QTestResult::setCurrentAppName(argv[0]); |
1901 | |
1902 | qtest_qParseArgs(argc, argv, false); |
1903 | if (QTest::randomOrder) { |
1904 | seedRandom(); |
1905 | } |
1906 | #ifdef QTESTLIB_USE_VALGRIND |
1907 | if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) { |
1908 | const QStringList origAppArgs(QCoreApplication::arguments()); |
1909 | if (!QBenchmarkValgrindUtils::rerunThroughCallgrind(origAppArgs, callgrindChildExitCode)) |
1910 | return -1; |
1911 | |
1912 | QBenchmarkValgrindUtils::cleanup(); |
1913 | |
1914 | } else |
1915 | #endif |
1916 | { |
1917 | #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) |
1918 | QScopedPointer<FatalSignalHandler> handler; |
1919 | if (!noCrashHandler) |
1920 | handler.reset(new FatalSignalHandler); |
1921 | #endif |
1922 | qInvokeTestMethods(testObject); |
1923 | } |
1924 | |
1925 | #ifndef QT_NO_EXCEPTIONS |
1926 | } catch (...) { |
1927 | QTestResult::addFailure("Caught unhandled exception" , __FILE__, __LINE__); |
1928 | if (QTestResult::currentTestFunction()) { |
1929 | QTestResult::finishedCurrentTestFunction(); |
1930 | QTestResult::setCurrentTestFunction(0); |
1931 | } |
1932 | |
1933 | QTestLog::stopLogging(); |
1934 | #ifdef QT_MAC_USE_COCOA |
1935 | if (macNeedsActivate) { |
1936 | IOPMAssertionRelease(powerID); |
1937 | } |
1938 | #endif |
1939 | currentTestObject = 0; |
1940 | |
1941 | // Rethrow exception to make debugging easier. |
1942 | throw; |
1943 | return 1; |
1944 | } |
1945 | # endif |
1946 | |
1947 | currentTestObject = 0; |
1948 | #ifdef QT_MAC_USE_COCOA |
1949 | if (macNeedsActivate) { |
1950 | IOPMAssertionRelease(powerID); |
1951 | } |
1952 | #endif |
1953 | |
1954 | #if defined(QTEST_NOEXITCODE) |
1955 | return 0; |
1956 | #else |
1957 | |
1958 | #ifdef QTESTLIB_USE_VALGRIND |
1959 | if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) |
1960 | return callgrindChildExitCode; |
1961 | #endif |
1962 | // make sure our exit code is never going above 127 |
1963 | // since that could wrap and indicate 0 test fails |
1964 | return qMin(QTestResult::failCount(), 127); |
1965 | |
1966 | #endif |
1967 | } |
1968 | |
1969 | /*! |
1970 | \overload |
1971 | \since 4.4 |
1972 | |
1973 | Behaves identically to qExec(QObject *, int, char**) but takes a |
1974 | QStringList of \a arguments instead of a \c char** list. |
1975 | */ |
1976 | int QTest::qExec(QObject *testObject, const QStringList &arguments) |
1977 | { |
1978 | const int argc = arguments.count(); |
1979 | QVarLengthArray<char *> argv(argc); |
1980 | |
1981 | QVector<QByteArray> args; |
1982 | args.reserve(argc); |
1983 | |
1984 | for(int i = 0; i < argc; ++i) |
1985 | { |
1986 | args.append(arguments.at(i).toLocal8Bit().constData()); |
1987 | argv[i] = args.last().data(); |
1988 | } |
1989 | |
1990 | return qExec(testObject, argc, argv.data()); |
1991 | } |
1992 | |
1993 | /*! \internal |
1994 | */ |
1995 | void QTest::qFail(const char *statementStr, const char *file, int line) |
1996 | { |
1997 | QTestResult::addFailure(statementStr, file, line); |
1998 | } |
1999 | |
2000 | /*! \internal |
2001 | */ |
2002 | bool QTest::qVerify(bool statement, const char *statementStr, const char *description, |
2003 | const char *file, int line) |
2004 | { |
2005 | return QTestResult::verify(statement, statementStr, description, file, line); |
2006 | } |
2007 | |
2008 | /*! \fn void QTest::qSkip(const char *message, SkipMode mode, const char *file, int line) |
2009 | \internal |
2010 | */ |
2011 | void QTest::qSkip(const char *message, QTest::SkipMode mode, |
2012 | const char *file, int line) |
2013 | { |
2014 | QTestResult::addSkip(message, mode, file, line); |
2015 | if (mode == QTest::SkipAll) |
2016 | QTestResult::setSkipCurrentTest(true); |
2017 | } |
2018 | |
2019 | /*! \fn bool QTest::qExpectFail(const char *dataIndex, const char *comment, TestFailMode mode, const char *file, int line) |
2020 | \internal |
2021 | */ |
2022 | bool QTest::qExpectFail(const char *dataIndex, const char *, |
2023 | QTest::TestFailMode mode, const char *file, int line) |
2024 | { |
2025 | return QTestResult::expectFail(dataIndex, qstrdup(comment), mode, file, line); |
2026 | } |
2027 | |
2028 | /*! \internal |
2029 | */ |
2030 | void QTest::qWarn(const char *message) |
2031 | { |
2032 | QTestLog::warn(message); |
2033 | } |
2034 | |
2035 | /*! |
2036 | Ignores messages created by qDebug() or qWarning(). If the \a message |
2037 | with the corresponding \a type is outputted, it will be removed from the |
2038 | test log. If the test finished and the \a message was not outputted, |
2039 | a test failure is appended to the test log. |
2040 | |
2041 | \bold {Note:} Invoking this function will only ignore one message. |
2042 | If the message you want to ignore is outputted twice, you have to |
2043 | call ignoreMessage() twice, too. |
2044 | |
2045 | Example: |
2046 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 19 |
2047 | |
2048 | The example above tests that QDir::mkdir() outputs the right warning when invoked |
2049 | with an invalid file name. |
2050 | */ |
2051 | void QTest::ignoreMessage(QtMsgType type, const char *message) |
2052 | { |
2053 | QTestResult::ignoreMessage(type, message); |
2054 | } |
2055 | |
2056 | /*! \internal |
2057 | */ |
2058 | void *QTest::qData(const char *tagName, int typeId) |
2059 | { |
2060 | return fetchData(QTestResult::currentTestData(), tagName, typeId); |
2061 | } |
2062 | |
2063 | /*! \internal |
2064 | */ |
2065 | void *QTest::qGlobalData(const char *tagName, int typeId) |
2066 | { |
2067 | return fetchData(QTestResult::currentGlobalTestData(), tagName, typeId); |
2068 | } |
2069 | |
2070 | /*! \internal |
2071 | */ |
2072 | void *QTest::qElementData(const char *tagName, int metaTypeId) |
2073 | { |
2074 | QTEST_ASSERT(tagName); |
2075 | QTestData *data = QTestResult::currentTestData(); |
2076 | QTEST_ASSERT(data); |
2077 | QTEST_ASSERT(data->parent()); |
2078 | |
2079 | int idx = data->parent()->indexOf(tagName); |
2080 | QTEST_ASSERT(idx != -1); |
2081 | QTEST_ASSERT(data->parent()->elementTypeId(idx) == metaTypeId); |
2082 | |
2083 | return data->data(data->parent()->indexOf(tagName)); |
2084 | } |
2085 | |
2086 | /*! \internal |
2087 | */ |
2088 | void QTest::addColumnInternal(int id, const char *name) |
2089 | { |
2090 | QTestTable *tbl = QTestTable::currentTestTable(); |
2091 | QTEST_ASSERT_X(tbl, "QTest::addColumn()" , "Cannot add testdata outside of a _data slot." ); |
2092 | |
2093 | tbl->addColumn(id, name); |
2094 | } |
2095 | |
2096 | /*! |
2097 | Appends a new row to the current test data. \a dataTag is the name of |
2098 | the testdata that will appear in the test output. Returns a QTestData reference |
2099 | that can be used to stream in data. |
2100 | |
2101 | Example: |
2102 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 20 |
2103 | |
2104 | \bold {Note:} This macro can only be used in a test's data function |
2105 | that is invoked by the test framework. |
2106 | |
2107 | See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for |
2108 | a more extensive example. |
2109 | |
2110 | \sa addColumn(), QFETCH() |
2111 | */ |
2112 | QTestData &QTest::newRow(const char *dataTag) |
2113 | { |
2114 | QTestTable *tbl = QTestTable::currentTestTable(); |
2115 | QTEST_ASSERT_X(tbl, "QTest::addColumn()" , "Cannot add testdata outside of a _data slot." ); |
2116 | |
2117 | return *tbl->newData(dataTag); |
2118 | } |
2119 | |
2120 | /*! \fn void QTest::addColumn(const char *name, T *dummy = 0) |
2121 | |
2122 | Adds a column with type \c{T} to the current test data. |
2123 | \a name is the name of the column. \a dummy is a workaround |
2124 | for buggy compilers and can be ignored. |
2125 | |
2126 | To populate the column with values, newRow() can be used. Use |
2127 | \l QFETCH() to fetch the data in the actual test. |
2128 | |
2129 | Example: |
2130 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 21 |
2131 | |
2132 | To add custom types to the testdata, the type must be registered with |
2133 | QMetaType via \l Q_DECLARE_METATYPE(). |
2134 | |
2135 | \bold {Note:} This macro can only be used in a test's data function |
2136 | that is invoked by the test framework. |
2137 | |
2138 | See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for |
2139 | a more extensive example. |
2140 | |
2141 | \sa QTest::newRow(), QFETCH(), QMetaType |
2142 | */ |
2143 | |
2144 | /*! |
2145 | Returns the name of the binary that is currently executed. |
2146 | */ |
2147 | const char *QTest::currentAppName() |
2148 | { |
2149 | return QTestResult::currentAppName(); |
2150 | } |
2151 | |
2152 | /*! |
2153 | Returns the name of the test function that is currently executed. |
2154 | |
2155 | Example: |
2156 | |
2157 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 22 |
2158 | */ |
2159 | const char *QTest::currentTestFunction() |
2160 | { |
2161 | return QTestResult::currentTestFunction(); |
2162 | } |
2163 | |
2164 | /*! |
2165 | Returns the name of the current test data. If the test doesn't |
2166 | have any assigned testdata, the function returns 0. |
2167 | */ |
2168 | const char *QTest::currentDataTag() |
2169 | { |
2170 | return QTestResult::currentDataTag(); |
2171 | } |
2172 | |
2173 | /*! |
2174 | Returns true if the current test function failed, otherwise false. |
2175 | */ |
2176 | bool QTest::currentTestFailed() |
2177 | { |
2178 | return QTestResult::currentTestFailed(); |
2179 | } |
2180 | |
2181 | /*! |
2182 | Sleeps for \a ms milliseconds, blocking execution of the |
2183 | test. qSleep() will not do any event processing and leave your test |
2184 | unresponsive. Network communication might time out while |
2185 | sleeping. Use \l qWait() to do non-blocking sleeping. |
2186 | |
2187 | \a ms must be greater than 0. |
2188 | |
2189 | \bold {Note:} The qSleep() function calls either \c nanosleep() on |
2190 | unix or \c Sleep() on windows, so the accuracy of time spent in |
2191 | qSleep() depends on the operating system. |
2192 | |
2193 | Example: |
2194 | \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 23 |
2195 | |
2196 | \sa qWait() |
2197 | */ |
2198 | void QTest::qSleep(int ms) |
2199 | { |
2200 | QTEST_ASSERT(ms > 0); |
2201 | |
2202 | #ifdef Q_OS_WIN |
2203 | Sleep(uint(ms)); |
2204 | #else |
2205 | struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; |
2206 | nanosleep(&ts, NULL); |
2207 | #endif |
2208 | } |
2209 | |
2210 | /*! \internal |
2211 | */ |
2212 | QObject *QTest::testObject() |
2213 | { |
2214 | return currentTestObject; |
2215 | } |
2216 | |
2217 | /*! \internal |
2218 | */ |
2219 | bool QTest::compare_helper(bool success, const char *msg, const char *file, int line) |
2220 | { |
2221 | return QTestResult::compare(success, msg, file, line); |
2222 | } |
2223 | |
2224 | /*! \internal |
2225 | */ |
2226 | bool QTest::compare_helper(bool success, const char *msg, char *val1, char *val2, |
2227 | const char *actual, const char *expected, const char *file, int line) |
2228 | { |
2229 | return QTestResult::compare(success, msg, val1, val2, actual, expected, file, line); |
2230 | } |
2231 | |
2232 | /*! \fn bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) |
2233 | \internal |
2234 | */ |
2235 | template <> |
2236 | Q_TESTLIB_EXPORT bool QTest::qCompare<float>(float const &t1, float const &t2, const char *actual, const char *expected, |
2237 | const char *file, int line) |
2238 | { |
2239 | return qFuzzyCompare(t1, t2) |
2240 | ? compare_helper(true, "COMPARE()" , file, line) |
2241 | : compare_helper(false, "Compared floats are not the same (fuzzy compare)" , |
2242 | toString(t1), toString(t2), actual, expected, file, line); |
2243 | } |
2244 | |
2245 | /*! \fn bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) |
2246 | \internal |
2247 | */ |
2248 | template <> |
2249 | Q_TESTLIB_EXPORT bool QTest::qCompare<double>(double const &t1, double const &t2, const char *actual, const char *expected, |
2250 | const char *file, int line) |
2251 | { |
2252 | return qFuzzyCompare(t1, t2) |
2253 | ? compare_helper(true, "COMPARE()" , file, line) |
2254 | : compare_helper(false, "Compared doubles are not the same (fuzzy compare)" , |
2255 | toString(t1), toString(t2), actual, expected, file, line); |
2256 | } |
2257 | |
2258 | #define COMPARE_IMPL2(TYPE, FORMAT) \ |
2259 | template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE >(const TYPE &t) \ |
2260 | { \ |
2261 | char *msg = new char[128]; \ |
2262 | qt_snprintf(msg, 128, #FORMAT, t); \ |
2263 | return msg; \ |
2264 | } |
2265 | |
2266 | COMPARE_IMPL2(short, %hd) |
2267 | COMPARE_IMPL2(ushort, %hu) |
2268 | COMPARE_IMPL2(int, %d) |
2269 | COMPARE_IMPL2(uint, %u) |
2270 | COMPARE_IMPL2(long, %ld) |
2271 | COMPARE_IMPL2(ulong, %lu) |
2272 | #if defined(Q_OS_WIN) |
2273 | COMPARE_IMPL2(qint64, %I64d) |
2274 | COMPARE_IMPL2(quint64, %I64u) |
2275 | #else |
2276 | COMPARE_IMPL2(qint64, %lld) |
2277 | COMPARE_IMPL2(quint64, %llu) |
2278 | #endif |
2279 | COMPARE_IMPL2(bool, %d) |
2280 | COMPARE_IMPL2(char, %c) |
2281 | COMPARE_IMPL2(float, %g) |
2282 | COMPARE_IMPL2(double, %lg) |
2283 | |
2284 | /*! \internal |
2285 | */ |
2286 | char *QTest::toString(const char *str) |
2287 | { |
2288 | if (!str) |
2289 | return 0; |
2290 | char *msg = new char[strlen(str) + 1]; |
2291 | return qstrcpy(msg, str); |
2292 | } |
2293 | |
2294 | /*! \internal |
2295 | */ |
2296 | char *QTest::toString(const void *p) |
2297 | { |
2298 | char *msg = new char[128]; |
2299 | qt_snprintf(msg, 128, "%p" , p); |
2300 | return msg; |
2301 | } |
2302 | |
2303 | /*! \internal |
2304 | */ |
2305 | bool QTest::compare_string_helper(const char *t1, const char *t2, const char *actual, |
2306 | const char *expected, const char *file, int line) |
2307 | { |
2308 | return (qstrcmp(t1, t2) == 0) |
2309 | ? compare_helper(true, "COMPARE()" , file, line) |
2310 | : compare_helper(false, "Compared strings are not the same" , |
2311 | toString(t1), toString(t2), actual, expected, file, line); |
2312 | } |
2313 | |
2314 | /*! \fn bool QTest::compare_ptr_helper(const void *t1, const void *t2, const char *actual, const char *expected, const char *file, int line); |
2315 | \internal |
2316 | */ |
2317 | |
2318 | /*! \fn bool QTest::qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int); |
2319 | \internal |
2320 | */ |
2321 | |
2322 | |
2323 | /*! \fn void QTest::mouseEvent(MouseAction action, QWidget *widget, Qt::MouseButton button, Qt::KeyboardModifiers stateKey, QPoint pos, int delay=-1) |
2324 | \internal |
2325 | */ |
2326 | |
2327 | /*! \fn bool QTest::qCompare(QIcon const &t1, QIcon const &t2, const char *actual, const char *expected, const char *file, int line) |
2328 | \internal |
2329 | */ |
2330 | |
2331 | /*! \fn bool QTest::qCompare(QPixmap const &t1, QPixmap const &t2, const char *actual, const char *expected, const char *file, int line) |
2332 | \internal |
2333 | */ |
2334 | |
2335 | /*! \fn bool QTest::qCompare(T const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line) |
2336 | \internal |
2337 | */ |
2338 | |
2339 | /*! \fn bool QTest::qCompare(const T *t1, const T *t2, const char *actual, const char *expected, const char *file, int line) |
2340 | \internal |
2341 | */ |
2342 | |
2343 | /*! \fn bool QTest::qCompare(T *t1, T *t2, const char *actual, const char *expected, const char *file, int line) |
2344 | \internal |
2345 | */ |
2346 | |
2347 | /*! \fn bool QTest::qCompare(const T1 *t1, const T2 *t2, const char *actual, const char *expected, const char *file, int line) |
2348 | \internal |
2349 | */ |
2350 | |
2351 | /*! \fn bool QTest::qCompare(T1 *t1, T2 *t2, const char *actual, const char *expected, const char *file, int line) |
2352 | \internal |
2353 | */ |
2354 | |
2355 | /*! \fn bool QTest::qCompare(const char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line) |
2356 | \internal |
2357 | */ |
2358 | |
2359 | /*! \fn bool QTest::qCompare(char *t1, char *t2, const char *actual, const char *expected, const char *file, int line) |
2360 | \internal |
2361 | */ |
2362 | |
2363 | /*! \fn bool QTest::qCompare(char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line) |
2364 | \internal |
2365 | */ |
2366 | |
2367 | /*! \fn bool QTest::qCompare(const char *t1, char *t2, const char *actual, const char *expected, const char *file, int line) |
2368 | \internal |
2369 | */ |
2370 | |
2371 | /*! \fn bool QTest::qCompare(QString const &t1, QLatin1String const &t2, const char *actual, const char *expected, const char *file, int line) |
2372 | \internal |
2373 | */ |
2374 | |
2375 | /*! \fn bool QTest::qCompare(QLatin1String const &t1, QString const &t2, const char *actual, const char *expected, const char *file, int line) |
2376 | \internal |
2377 | */ |
2378 | |
2379 | /*! \fn bool QTest::qCompare(QStringList const &t1, QStringList const &t2, const char *actual, const char *expected, const char *file, int line) |
2380 | \internal |
2381 | */ |
2382 | |
2383 | /*! \fn bool QTest::qCompare(QFlags<T> const &t1, T const &t2, const char *actual, const char *expected, const char *file, int line) |
2384 | \internal |
2385 | */ |
2386 | |
2387 | /*! \fn bool QTest::qCompare(QFlags<T> const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line) |
2388 | \internal |
2389 | */ |
2390 | |
2391 | /*! \fn bool QTest::qCompare(bool const &t1, int const &t2, const char *actual, const char *expected, const char *file, int line) |
2392 | \internal |
2393 | */ |
2394 | |
2395 | /*! \fn bool QTest::qTest(const T& actual, const char *elementName, const char *actualStr, const char *expected, const char *file, int line) |
2396 | \internal |
2397 | */ |
2398 | |
2399 | /*! \fn void QTest::sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, QString text, Qt::KeyboardModifiers modifier, int delay=-1) |
2400 | \internal |
2401 | */ |
2402 | |
2403 | /*! \fn void QTest::sendKeyEvent(KeyAction action, QWidget *widget, Qt::Key code, char ascii, Qt::KeyboardModifiers modifier, int delay=-1) |
2404 | \internal |
2405 | */ |
2406 | |
2407 | /*! \fn void QTest::simulateEvent(QWidget *widget, bool press, int code, Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1) |
2408 | \internal |
2409 | */ |
2410 | |
2411 | QT_END_NAMESPACE |
2412 | |