summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestcase.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Exclude VxWorks platform from stack trace generationKrzysztof Sommerfeld2023-07-271-2/+2
| | | | | Change-Id: I71c2e542ef144f544610edb9245dcbc38ea7db3f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QtCore: Remove std::mutex and std::condition_variable fallbacksThiago Macieira2023-06-121-3/+3
| | | | | | | | | | | | They existed because INTEGRITY hadn't yet been updated to the C++11 Standard Library, with a minor for broken MinGW cross-compilation builds that forgot to enable gthreads support in libstdc++. The former appears to have been since fixed and the latter is a massive toolchain configuration mistake. Change-Id: I63b988479db546dabffcfffd1766b55132371f9b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Detect when Xcode is presenting os_log as structured log messagesTor Arne Vestbø2023-06-071-2/+2
| | | | | | | | | In that case, just like when os_log mirrors to stderr by itself, we want to disable Qt's fallback stderr handler. Pick-to: 6.6 6.5 Change-Id: Ia373b19788edbce616d4f0d3d9f0b217ddc1e5c0 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
* Testlib: fix the last few s/Q_OS_MAC/Q_OS_DARWIN/wEdward Welbourne2023-03-201-1/+1
| | | | | Change-Id: I6fe6a865aea37c6a2d153bd2c3aace5242362c88 Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
* Cross-reference newRow() and addRow() in QTest docs and improve wordingEdward Welbourne2023-01-311-12/+22
| | | | | | | | | | | | Mitch helpfully pointed out, in review of my change to the "Data Driven Testing" doc that the two functions didn't \sa each other, so I added that. Which naturally prompted a review of their language. Also, split a long line in the code. Pick-to: 6.5 Change-Id: I5f3e973052e0107bd5bdaeecaebe218e043380ff Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Jason McDonald <macadder1@gmail.com>
* Doc: Mark qRegisterTestCase as new in Qt 6.5Kai Köhne2023-01-161-1/+3
| | | | | | | | | Also remove reference to QTestCaseEvent loop class, which is not documented. Pick-to: 6.5 Change-Id: Ic09b3b102db535dfb090b9a4072ad29515a911ae Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io>
* QTest::WatchDog: fix missing timeout resets on test function changeMarc Mutz2022-12-161-3/+22
| | | | | | | | | | | | | | | | | | | | | | | | Since e0cad1aab53119a0e47467f2236f019ce8d6da2a, the code suffered from an ABA problem where the TestFunctionStart expectation is set in testFinished(), but by the time WatchDog::run() gets around to examining the state when returning from condition_variable::wait() in waitFor(), the next beginTest() has already set the expectation back to TestFunctionEnd. There are several known solutions for ABA problems. Embedding a generation count into the expectation state seemed to be the most straight-forward fix, and can be done without DWCAS support, because the state is just 2 bits, leaving the other 30 or 62 bits for the generation counter, so do that. [ChangeLog][QTestLib] Fixed a bug which caused QTEST_FUNCTION_TIMEOUT to be applied to the whole test execution, as opposed to each test function. Fixes: QTBUG-109466 Pick-to: 6.5 6.4 6.2 5.15 Change-Id: If71ade932330407b85d204d45c74350c651325fe Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QTest::WatchDog: Extract Method setExpectation()Marc Mutz2022-12-161-11/+10
| | | | | | | | | | Keeps the code DRY and enables a follow-up commit to fix QTBUG-109466. Task-number: QTBUG-109466 Pick-to: 6.5 6.4 6.2 5.15 Change-Id: I2b904ea7b38286b07049524ba63c2c5028e680bb Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QPlainTestLogger: don't print "RESULT" before each additional resultThiago Macieira2022-11-091-6/+2
| | | | | | | | | | | | | | | | | We do that by passing the full list of results to the logger, to a virtual that is present in the base class to call the existing function. For all but the plain logger, we'll just print multiple results. The plain logger now prints: RESULT : tst_MyClass::QString_toInt() 383 nsecs per iteration (total: 3,837,324, iterations: 10000) 1,069 CPU cycles per iteration (total: 10,692,457, iterations: 10000) 3,123 instructions per iteration (total: 31,230,101, iterations: 10000) 536 branch instructions per iteration (total: 5,360,022, iterations: 10000) Change-Id: I3c79b7e08fa346988dfefffd17203cb5802693dd Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QBenchlib: add support for a measurer reporting multiple resultsThiago Macieira2022-11-091-24/+32
| | | | | | | | | | | | | | | | | Implemented for the Linux Perf measurer, with four measurements by default. RESULT : tst_MyClass::QString_toInt(): 149.574444 CPU cycles per iteration (total: 149,574,445, iterations: 1000000) RESULT : tst_MyClass::QString_toInt(): 620.000181 instructions per iteration (total: 620,000,182, iterations: 1000000) RESULT : tst_MyClass::QString_toInt(): 131.000046 branch instructions per iteration (total: 131,000,047, iterations: 1000000) RESULT : tst_MyClass::QString_toInt(): 32.118771 nsecs per iteration (total: 32,118,771, iterations: 1000000) Change-Id: I3c79b7e08fa346988dfefffd17202cda3df8431b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QBenchlib: use QBenchmarkMeasurerBase::Measurement in QBenchmarkResultThiago Macieira2022-11-091-11/+5
| | | | | Change-Id: I3c79b7e08fa346988dfefffd17202a818cde1d84 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Port from container::count() and length() to size() - V5Marc Mutz2022-11-031-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator as in qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8, but extended to handle typedefs and accesses through pointers, too: const std::string o = "object"; auto hasTypeIgnoringPointer = [](auto type) { return anyOf(hasType(type), hasType(pointsTo(type))); }; auto derivedFromAnyOfClasses = [&](ArrayRef<StringRef> classes) { auto exprOfDeclaredType = [&](auto decl) { return expr(hasTypeIgnoringPointer(hasUnqualifiedDesugaredType(recordType(hasDeclaration(decl))))).bind(o); }; return exprOfDeclaredType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes)))); }; auto renameMethod = [&] (ArrayRef<StringRef> classes, StringRef from, StringRef to) { return makeRule(cxxMemberCallExpr(on(derivedFromAnyOfClasses(classes)), callee(cxxMethodDecl(hasName(from), parameterCountIs(0)))), changeTo(cat(access(o, cat(to)), "()")), cat("use '", to, "' instead of '", from, "'")); }; renameMethod(<classes>, "count", "size"); renameMethod(<classes>, "length", "size"); except that the on() matcher has been replaced by one that doesn't ignoreParens(). a.k.a qt-port-to-std-compatible-api V5 with config Scope: 'Container'. Added two NOLINTNEXTLINEs in tst_qbitarray and tst_qcontiguouscache, to avoid porting calls that explicitly test count(). Change-Id: Icfb8808c2ff4a30187e9935a51cad26987451c22 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QBenchlib: force the warmup to run a single iterationThiago Macieira2022-10-251-0/+2
| | | | | | | | | | | | The purpose of warming up is to get all code paths executed, so any lazy function resolving is processed, statics are allocated, etc. There's no reason to run it more than once -- if you're trying to train the Branch Predictor Unit, you'd want to do it another way anyway. This is useful when benchmarking with -iterations N, because QBenchlib currently runs 2*N iterations because of the warm up. That just wastes time. Change-Id: I3c79b7e08fa346988dfefffd172030c889b31a1f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Long live Q_UNREACHABLE_RETURN()!Marc Mutz2022-10-151-2/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a combination of Q_UNREACHABLE() with a return statement. ATM, the return statement is unconditionally included. If we notice that some compilers warn about return after __builtin_unreachable(), then we can map Q_UNREACHABLE_RETURN(...) to Q_UNREACHABLE() without having to touch all the code that uses explicit Q_UNREACHABLE() + return. The fact that Boost has BOOST_UNREACHABLE_RETURN() indicates that there are compilers that complain about a lack of return after Q_UNREACHABLE (we know that MSVC, ICC, and GHS are among them), as well as compilers that complained about a return being present (Coverity). Take this opportunity to properly adapt to Coverity, by leaving out the return statement on this compiler. Apply the macro around the code base, using a clang-tidy transformer rule: const std::string unr = "unr", val = "val", ret = "ret"; auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(", ifBound(val, cat(node(val)), cat("")), ")"); auto ignoringSwitchCases = [](auto stmt) { return anyOf(stmt, switchCase(subStmt(stmt))); }; makeRule( stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)), nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))), {changeTo(node(unr), cat(makeUnreachableReturn, ";")), // TODO: why is the ; lost w/o this? changeTo(node(ret), cat(""))}, cat("use ", makeUnreachableReturn)) ); where nextStmt() is copied from some upstream clang-tidy check's private implementation and subStmt() is a private matcher that gives access to SwitchCase's SubStmt. A.k.a. qt-use-unreachable-return. There were some false positives, suppressed them with NOLINTNEXTLINE. They're not really false positiives, it's just that Clang sees the world in one way and if conditonal compilation (#if) differs for other compilers, Clang doesn't know better. This is an artifact of matching two consecutive statements. I haven't figured out how to remove the empty line left by the deletion of the return statement, if it, indeed, was on a separate line, so post-processed the patch to remove all the lines matching ^\+ *$ from the diff: git commit -am meep git reset --hard HEAD^ git diff HEAD..HEAD@{1} | sed '/^\+ *$/d' | recountdiff - | patch -p1 [ChangeLog][QtCore][QtAssert] Added Q_UNREACHABLE_RETURN() macro. Change-Id: I9782939f16091c964f25b7826e1c0dbd13a71305 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Port from qAsConst() to std::as_const()Marc Mutz2022-10-111-1/+1
| | | | | | | | | | | | | | | | We've been requiring C++17 since Qt 6.0, and our qAsConst use finally starts to bother us (QTBUG-99313), so time to port away from it now. Since qAsConst has exactly the same semantics as std::as_const (down to rvalue treatment, constexpr'ness and noexcept'ness), there's really nothing more to it than a global search-and-replace, with manual unstaging of the actual definition and documentation in dist/, src/corelib/doc/ and src/corelib/global/. Task-number: QTBUG-99313 Change-Id: I4c7114444a325ad4e62d0fcbfd347d2bbfb21541 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* Port from container.count()/length() to size()Marc Mutz2022-10-041-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is semantic patch using ClangTidyTransformator: auto QtContainerClass = expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o) makeRule(cxxMemberCallExpr(on(QtContainerClass), callee(cxxMethodDecl(hasAnyName({"count", "length"), parameterCountIs(0))))), changeTo(cat(access(o, cat("size"), "()"))), cat("use 'size()' instead of 'count()/length()'")) a.k.a qt-port-to-std-compatible-api with config Scope: 'Container'. <classes> are: // sequential: "QByteArray", "QList", "QQueue", "QStack", "QString", "QVarLengthArray", "QVector", // associative: "QHash", "QMultiHash", "QMap", "QMultiMap", "QSet", // Qt has no QMultiSet Change-Id: Ibe8837be96e8d30d1846881ecd65180c1bc459af Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* Add QTest::currentTestResolved() and use in testlibEdward Welbourne2022-09-221-2/+22
| | | | | | | | | | | | | | | | | | The QTRY_* macros and QTestEventLoop have (since 6.3) been exiting their loops early if the test has failed. Where that was appropriate, they should also have been exiting early on skip. [ChangeLog][QtTest] Added QTest::currentTestResolved(), which is true if the test has failed or skipped. The QTRY_*() macros and QTestEventLoop now use this, rather than QTest::currentTestFailed(), to test whether they should stop looping, so that they also do so on a skip. Task-number: QTBUG-104441 Change-Id: Ibf3d5a095b35e6670bc3daf756f05b66f7f3ef9b Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io> Reviewed-by: Jason McDonald <macadder1@gmail.com>
* QDoc-ify QTest::runningTest()'s commentEdward Welbourne2022-09-221-1/+3
| | | | | | | | | | | While it's being picked into 6.3, it's not present in 6.3.[01], so I've left it out of QDoc's sight (even though it's still \internal) for the version picked to 6.3, but let's include it in internal docs as "from 6.4" since that's the first minor release to contain it. Pick-to: 6.4 Change-Id: I1704a1ca4ba1231d0213e9ca236ef8401a59ddd0 Reviewed-by: Paul Wicking <paul.wicking@qt.io>
* Skip early return from test loops during cleanup()Edward Welbourne2022-09-221-0/+14
| | | | | | | | | | | | | | | | The QTRY_* macros and QTestEventLoop exit early if the test has resolved; however, in the cleanup phase of a test, even if the test has failed, these loops should continue as normal. [ChangeLog][QtTest] During the cleanup() phase of a test, the QTRY_* macros and QTestEventLoop now ignore the test resolution, in contrast to when they are used from the test itself, which (since 6.3.0) exits the loops early if the test has failed. Pick-to: 6.4 6.3 Fixes: QTBUG-104441 Change-Id: I2673161967cbbc57815155af698a9338ab98a686 Reviewed-by: Jason McDonald <macadder1@gmail.com>
* Implement the batch_tests featureMikolaj Boc2022-08-241-0/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | An approach of test batching (joining multiple tests into a single binary) has been taken, due to long linking times/binary size on certain platforms, including WASM. This change adds a new feature 'batch_test_support' in Qt testlib. Based on the value of the feature, test batching may become enabled with the -batch-tests switch. Batching works for every target added via qt_internal_add_test. When first such target is being processed, a new combined target for all of the future test sources is created under the name of 'test_batch'. CMake attempts to merge the parameters of each of the tests, and some basic checks are run for parameter differences that are impossible to reconcile. On the C++ level, convenience macros instantiating the tests are redefined when batch_tests is on. The new, changed behavior triggered by the changes in the macros registers the tests in a central test registry, where they are available for execution based solely on their test name. The test name is interoperable with the names CMake is aware of, so CTest is able to run the tests one by one in the combined binary. Task-number: QTBUG-105273 Change-Id: I2b6071d58be16979bd967eab2d405249f5a4e658 Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
* Include current test name in crash reportsEdward Welbourne2022-08-121-5/+9
| | | | | | | | | | | | | | | | Previously a crashing test's output would end with the last completed test's output followed by a crash report, leading readers (understandably enough) to conclude that the last-named test is the one that crashed. In fact the crashing test is typically the next one in the class definition. Include the current test function's name (when non-null) in the output accompanying crash logs. This always goes to stderr so does not show up in the expected output. Pick-to: 6.4 Change-Id: Icab0ccd1fe434827ee92459ab0c97f9dc034754e Reviewed-by: Jason McDonald <macadder1@gmail.com>
* WindowsFaultHandler: print the backtrace to stderr, not stdoutThiago Macieira2022-07-271-12/+11
| | | | | | | | | Otherwise the contents that vary per architecture and build will make it impossible to self-check (tst_selftests) Change-Id: Ibcde9b9795ad42ac9978fffd16f2cbc352c3503c Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Replace 0 with \nullptr in QTest::currentDataTag()'s docEdward Welbourne2022-07-111-1/+1
| | | | | | | The function's return type is a pointer, not an integer. Change-Id: Iab6686ac7e4e24b9b1bd0127346c5854cf593a57 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Improve formatting of QTest message on missing functionEdward Welbourne2022-07-111-6/+15
| | | | | | | | | | | | | | | | | | | If there were no matches to the name given on the command line, the message reported included a "Possible matches:" preamble for a list of functions containing the requested function name. This looked incongruous when no actual functions matched. Turn that preamble into an optional parameter to qPrintTestSlots(), that it'll output before the first match if it finds one, rework qPrintTestSlots() to package its matching condition in a lambda and return true if it found any matches. Change this caller to output a newline in place of the preamble (which ended in a newline), if no match was found. Change-Id: I9716ffa29c3c46e3c7e7fcf25a676c0356dab91c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Dimitrios Apostolou <jimis@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* qtestlib: exit with error if a test is invoked with unknown data tagDimitrios Apostolou2022-06-281-21/+22
| | | | | | | | | | | | | | Previously trying to execute a test function with an unknown data tag would print an error message but exit with 0. This patch stores a test failure, and continues trying to execute the rest of the command line arguments, if any. In the end the process exits with the usual exit code (number of failed tests) which is now !=0. Pick-to: 6.4 6.3 6.2 Fixes: QTBUG-24240 Change-Id: Id4d422035f173e01e77ca88028dfd94dc0f9085c Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: print some more information from siginfo_tThiago Macieira2022-06-281-6/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | The siginfo_t parameter allows us to show what process sent a signal or the crashing address. Additionally, it allows us to determine if the crashing signal was indeed sent due to a crash. The selftest tst_crashes produces now: $ QTEST_DISABLE_STACK_DUMP=1 ./crashes ********* Start testing of tst_Crashes ********* Config: Using QtTest library 6.4.0, Qt 6.4.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 11.2.1 20220420 [revision 691af15031e00227ba6d5935c1d737026cda4129]), opensuse-tumbleweed 20220428 PASS : tst_Crashes::initTestCase() Received signal 11 (SIGSEGV), code 1, for address 0x0000000000000004 Function time: 0ms, total time: 0ms [1] 201995 segmentation fault (core dumped) QTEST_DISABLE_STACK_DUMP=1 ./crashes The last line comes from the shell. The code isn't decoded, but on Linux it's a SEGV_MAPERR. macOS prints exactly the same thing. I've updated one of the expected_crashes_*.txt output that doesn't seem possible (the "Received a fatal error" message does not appear in Qt anywhere). Pick-to: 6.4 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16ebc8391234f0e2 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QTest: switch some text-conversion functions to use qsizetypeMårten Nordheim2022-06-281-10/+8
| | | | | | | | | To avoid potential narrowing. Pick-to: 6.4 Task-number: QTBUG-104125 Change-Id: I37bfc5c49e7c919f5204a76a905758a92527d864 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Fix typos in docs and commentsKai Köhne2022-06-151-2/+2
| | | | | | | | | Found by codespell Pick-to: 6.4 Change-Id: Ie3e301a23830c773a2e9aff487c702a223d246eb Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Don't exit(1) on unrecognised test function name, just report a failureEdward Welbourne2022-06-151-9/+23
| | | | | | | | | | This way, if you name several test functions on the command-line, you'll at least get the ones that do exist run (and you'll be told all of the ones that don't exist, rather than only the first). Pick-to: 6.4 6.3 6.2 Change-Id: I14a515fcfacb6ca49e0470b236c05475b25db4f2 Reviewed-by: Dimitrios Apostolou <jimis@qt.io>
* FatalSignalHandler: print the signal name on crashThiago Macieira2022-06-081-2/+34
| | | | | | | | | | | | | It's easier to remember what "SIGSEGV" means instead of "11". GNU libc has offered sigabbrev_np() (non-portable) since 2.32; for older libcs, we'll be happy with a hardcoded list. Selftest updated to match... though it didn't seem to be necessary. Pick-to: 6.4 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16ebc66ecf6e9465 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QTest: Remove pre-Qt6 codeMårten Nordheim2022-06-081-10/+0
| | | | | | | | | It's disabled now, so can be deleted Pick-to: 6.4 6.3 6.2 Change-Id: I0d548327e7ef42bbca9ed88556bf9f8456038cc7 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Define out unused functions on WASM buildMikolaj Boc2022-06-081-5/+7
| | | | | | | | | | | | | | | The struct iovec conversion functions that are needed on Unix are unused on WASM build. This makes the build fail with -Werror on Mac since the WASM build is treated as a variant of Unix. Cross-compilation with clang: Apple clang version 13.0.0 (clang-1300.0.27.3) Target: arm64-apple-darwin21.3.0 Fixes: QTBUG-103974 Pick-to: 6.3 6.4 Change-Id: I34c65a18832ceedb9064a98f5729e45667749461 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QTestLib: improve documentationIvan Solovev2022-06-081-0/+2
| | | | | | | | | | | | Add missing '\since' version numbers. This commit amends cc6d984390dc937b9d8440b6ba7d4f578e22ac0d and 0681a2dd5a8095baddb5905fb21a58ce19b958c5 Pick-to: 6.4 Change-Id: Ia10b991c996fb58f08a17e485c4dfcbfbe8eba0a Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* qtestcase.cpp: create a common function to print the test runtimeThiago Macieira2022-06-031-12/+28
| | | | | | | | | | | The time was getting printed twice for the stack trace, but zero for the watch dog if the stack trace was disabled. Selftest appears to pass (though I thought it shouldn't). Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16ebc4ec99e7fc5a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QTestLib: rework QTest::compare_helper()Ivan Solovev2022-06-031-6/+56
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ChangeLog][QTestLib] QCOMPARE now evaluates toString() on its arguments lazily, speeding up the general case where the comparison doesn't fail. This is true for the QCOMPARE functionality provided by Qt. If you specialized qCompare() for your own types, then you need to change its implementation in line with Qt's own qCompare() specializations in order to enable this feature. [ChangeLog][QTestLib] QCOMPARE calls with nullptr argument(s) will now print the actual and expected values upon failure. Previously it was not like that because of the compareHelper() overload in qtestresult.cpp that treated the presence of nullptr-arguments as a reason to ignore formatFailMessage() call. New implementation does not have this check, and correctly executes formatFailMessage() for all arguments. Note that the qCompare() overloads that call QTestResult::compare() internally were not affected by this patch, because they already defer toString() invocation until the comparison fails. Some numbers, collected against shared release developer build. I checked how this change affects the test execution. The idea was to pick some tests for types that do not have a specific QTestResult::compare overload, so I picked a couple of QByteArray tests. The comparison is done by running a test 10 times and taking the average execution duration, as reported in the log. tst_qbytearrayapisymmetry: Before: 15.6 ms After: 14.2 ms tst_qbytearray: Before: 41 ms After: 36 ms The benefit is around 9% and 12% respectively. Fixes: QTBUG-98874 Change-Id: I7d59ddc760168b15974e7720930f629fb34efa13 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Add QCOMPARE_{EQ,NE,LT,LE,GT,GE}()Ivan Solovev2022-06-031-0/+8
| | | | | | | | | | | | | | | | | | | | | [ChangeLog][QTestLib] Add QCOMPARE_{EQ,NE,LT,LE,GT,GE}() macros. These new macros behave similarly to QVERIFY(a op b), where 'op' is ==, !=, <, <=, >, >= respectively, but print a formatted error message with argument values in case of failure. The formatting is done lazily, which means that the strings will be generated only when the comparison fails. Also add a new test for tst_selftest and generate expected output for it. Fixes: QTBUG-98873 Task-number: QTBUG-98874 Change-Id: Ic8074798901d7a469b1f58d5cd28bbf49a3da1db Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QtTest: move the disabling of core dumps from load-time to qInit()Thiago Macieira2022-06-011-2/+2
| | | | | | | | | | | | | There's no reason it has to be done THAT early. It was added in commit aec85a53df3dbe3047c6db0f6eb39cb161cd3e6b to have the selftests (which do crash) not leave lots of core files around. I could replace it with a QProcess::setChildProcessModifier() function, but the variable is now documented in the QtTest manual, so it would be no gain. Function renamed to reflect its implementation. Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16ebc25df97a98e3 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: handle SIGABRT tooThiago Macieira2022-05-301-1/+1
| | | | | | | Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb77e9c77d10ba Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: expand to more Unix OSes than just Linux and macOSThiago Macieira2022-05-301-7/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | At least for my FreeBSD this makes sense. The default debugger search is gdb first then lldb on Linux-not-Android and for QNX (qcc is GCC after all), but lldb first everywhere else. With LLVM14 from Ports, I get: $ tests/auto/corelib/tools/qhashseed/tst_qhashseed | head -1 ********* Start testing of tst_QHashSeed ********* Config: Using QtTest library 6.4.0, Qt 6.4.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by Clang 14.0.0), freebsd 13.0 === Received signal at function time: 1ms, total time: 3ms, dumping stack === (lldb) process attach --pid 1782 Process 1782 stopped Executable module set to "/usr/home/tjmaciei/obj/qt/qt6/qtbase/tests/auto/corelib/tools/qhashseed/tst_qhashseed". Architecture set to: x86_64--freebsd13.0. (lldb) bt all * thread #1, name = 'tst_qhashseed' * frame #0: 0x0000000800f227c8 libc.so.7`_wait4 at _wait4.S:4 frame #1: 0x00000008003243bc libthr.so.3`__thr_wait4(pid=<unavailable>, status=<unavailable>, options=<unavailable>, rusage=<unavailable>) at thr_syscalls.c:581:8 frame #2: 0x00000008002b9c73 libQt6Test.t.so.6`(anonymous namespace)::StackTraceHandler::generate() at qtestcase.cpp:393:9 [...] === End of stack trace === Received signal 13 Function time: 1ms Total time: 3ms Support for Windows left as an exercise for later. The WindowsFaultHandler code doesn't even call generateStackTrace(). Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eba471f58ff3cb Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* FatalSignalHandler: use mmap() to create the alternate stackThiago Macieira2022-05-301-21/+67
| | | | | | | | | | | | So we can mark the bottom page as inaccessible, thus be able to catch a stack overflow in the handler itself. Our code shouldn't cause overflows, but it's possible that a chained handler does more work than expected. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb83a294ab7958 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* StackTraceHandler: call the debugger directly, instead of via /bin/shThiago Macieira2022-05-231-14/+29
| | | | | | | | | | | | | This removes one middle-man and a 512-byte variable in favor of a simple 32-bit enum. This was done in a way so we can extend to use either gdb or lldb in any OS. I've renamed the debuggerPresent() function to make its meaning clearer. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eba561628ff89b Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* StackTraceHandler: simplify the gdb and lldb commandsThiago Macieira2022-05-231-11/+2
| | | | | | | | | | Instead of piping stuff via the shell into them, just use batch mode. And also take the opportunity to tell them not to read their user- provided configuration files. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eba21e71afaefa Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: chain back to the original crash handlerThiago Macieira2022-05-201-0/+31
| | | | | | | | | | | | | | | | | | | | | | | | | If a previous handler was already installed, ensure it is called, because there may be a reason why it was there. For example, the Android ART adds a signal action to every fatal signal for logging purposes. We do that by restoring the signal handler we had and re-raising the signal. If our handler was overridden by something else, then that handler was already called, but will get uninstalled after our code runs. It won't be a problem, because the application is exiting anyway. [ChangeLog][QtTest][Behavior Change] On Unix, the QtTest code to handle Unix/POSIX fatal signals will now call back to the original handler that was installed, if there was one. This allows logging frameworks (such as Android ART's), for example, to log the crash too. Additionally, if there was no handler, the application should exit with the correct signal instead of SIGABRT. Fixes: QTBUG-97652 Pick-to: 6.3 Change-Id: Ifc4fca159b490d8d0b614d736e46caefcb903a4c Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: remember the previous signal's handlerThiago Macieira2022-05-201-41/+23
| | | | | | | | | | | | And only restore those signals, instead of iterating over all possible signals, instead of attempting to restore to SIG_DFL. Also, as a consequence, we will install our handler even if there was already a handler installed for the signal. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb756685f4e8b8 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* FatalSignalHandler: simplify SA_RESETHAND codeThiago Macieira2022-05-201-13/+6
| | | | | | | | | And remove the unreachable code after std::abort() that was meant to mimic that in INTEGRITY. The next commit will fix this properly. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb772018add694 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: simplify the SA_SIGINFO handlingThiago Macieira2022-05-201-9/+10
| | | | | | | | | The #if around the function declaration was ugly. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb7540f5da080f Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: use std::optional instead of QScopedPointerThiago Macieira2022-05-201-2/+4
| | | | | | | | We get stack space reserved instead of using the heap. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb73fff0174150 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: split the Windows and Unix contentsThiago Macieira2022-05-201-57/+58
| | | | | | | | | | | | They're very different, so there's no point in having them even in the same class body. I've renamed the Windows one because Windows does not report crashes via signals anyway. If you have an IDE that can scan both branches of the #if, it will help you find the Windows-specific code too. Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb73ba196cfb74 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* Put DebugSymbolResolver and FatalSignalHandler in an unnamed namespaceThiago Macieira2022-05-201-1/+4
| | | | | | | Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb735315b337b6 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* FatalSignalHandler: remove call to qEnvironmentXxx from handler codeThiago Macieira2022-05-201-1/+6
| | | | | | | | | | | | | | The Qt environment handling functions lock a mutex. That's a big no-no in signal handlers. [ChangeLog][QtTest][Behavior Change] QtTest will now check the value of the environment variable QTEST_PAUSE_ON_CRASH in QTest::qRun(), so if a test wants to modify this variable, it must do so from the main() or initMain() functions, not in the test itself (including initTestCase()). Pick-to: 6.3 Change-Id: I5ff8e16fcdcb4ffd9ab6fffd16eb78867cd8f54e Reviewed-by: Marc Mutz <marc.mutz@qt.io>