diff options
Diffstat (limited to 'src/testlib')
-rw-r--r-- | src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp | 11 | ||||
-rw-r--r-- | src/testlib/qbenchmark_p.h | 4 | ||||
-rw-r--r-- | src/testlib/qteamcitylogger.cpp | 23 | ||||
-rw-r--r-- | src/testlib/qtestcase.cpp | 87 | ||||
-rw-r--r-- | src/testlib/qtestcase.h | 5 | ||||
-rw-r--r-- | src/testlib/qtestsystem.h | 4 |
6 files changed, 110 insertions, 24 deletions
diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index 2c57550c3d..01ee8102f4 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -208,6 +208,17 @@ void myTestFunction_data() //! [20] +//! [addRow] +void myTestFunction_data() +{ + QTest::addColumn<int>("input"); + QTest::addColumn<QString>("output"); + QTest::addRow("%d", 0) << 0 << QString("0"); + QTest::addRow("%d", 1) << 1 << QString("1"); +} +//! [addRow] + + //! [21] void myTestFunction_data() { QTest::addColumn<int>("intval"); diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index 0b16f624df..797071d7a4 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -91,8 +91,8 @@ struct QBenchmarkContext QString toString() const { - QString s = QString::fromLatin1("%1,%2,%3").arg(slotName).arg(tag).arg(checkpointIndex); - return s; + return QString::fromLatin1("%1,%2,%3") + .arg(slotName, tag, QString::number(checkpointIndex)); } QBenchmarkContext() : checkpointIndex(-1) {} diff --git a/src/testlib/qteamcitylogger.cpp b/src/testlib/qteamcitylogger.cpp index 1d700d8201..81c2499bcb 100644 --- a/src/testlib/qteamcitylogger.cpp +++ b/src/testlib/qteamcitylogger.cpp @@ -167,17 +167,16 @@ void QTeamCityLogger::addIncident(IncidentTypes type, const char *description, messageText += QString(QLatin1String(" |[Loc: %1(%2)|]")).arg(QString::fromUtf8(file)).arg(line); buf = QString(QLatin1String("##teamcity[testFailed name='%1' message='%2' details='%3']\n")) - .arg(tmpFuncName) - .arg(messageText) - .arg(detailedText); + .arg(tmpFuncName, + messageText, + detailedText); outputString(qPrintable(buf)); } if (!pendingMessages.isEmpty()) { buf = QString(QLatin1String("##teamcity[testStdOut name='%1' out='%2']\n")) - .arg(tmpFuncName) - .arg(pendingMessages); + .arg(tmpFuncName, pendingMessages); outputString(qPrintable(buf)); @@ -209,8 +208,7 @@ void QTeamCityLogger::addMessage(MessageTypes type, const QString &message, escapedMessage.append(QString(QLatin1String(" |[Loc: %1(%2)|]")).arg(QString::fromUtf8(file)).arg(line)); buf = QString(QLatin1String("##teamcity[testIgnored name='%1' message='%2']\n")) - .arg(escapedTestFuncName()) - .arg(escapedMessage); + .arg(escapedTestFuncName(), escapedMessage); outputString(qPrintable(buf)); } @@ -259,10 +257,7 @@ QString QTeamCityLogger::escapedTestFuncName() const : "UnknownTestFunc"; const char *tag = QTestResult::currentDataTag() ? QTestResult::currentDataTag() : ""; - QString str = QString(QLatin1String("%1(%2)")).arg(QString::fromUtf8(fn)).arg(QString::fromUtf8(tag)); - str = tcEscapedString(str); - - return str; + return tcEscapedString(QString::asprintf("%s(%s)", fn, tag)); } void QTeamCityLogger::addPendingMessage(const char *type, const QString &msg, const char *file, int line) @@ -274,16 +269,14 @@ void QTeamCityLogger::addPendingMessage(const char *type, const QString &msg, co if (file) { pendMessage += QString(QLatin1String("%1 |[Loc: %2(%3)|]: %4")) - .arg(QString::fromUtf8(type)) - .arg(QString::fromUtf8(file)) + .arg(QString::fromUtf8(type), QString::fromUtf8(file)) .arg(line) .arg(msg); } else { pendMessage += QString(QLatin1String("%1: %2")) - .arg(QString::fromUtf8(type)) - .arg(msg); + .arg(QString::fromUtf8(type), msg); } pendingMessages.append(pendMessage); diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 31ffb36690..19d135e15f 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -99,11 +99,16 @@ #include <errno.h> #include <signal.h> #include <time.h> -#include <sys/resource.h> +# if !defined(Q_OS_INTEGRITY) +# include <sys/resource.h> +# endif #endif #if defined(Q_OS_MACX) #include <IOKit/pwr_mgt/IOPMLib.h> +#include <mach/task.h> +#include <mach/mach_init.h> +#include <CoreFoundation/CFPreferences.h> #endif #include <vector> @@ -138,6 +143,40 @@ static bool debuggerPresent() return pid != 0; #elif defined(Q_OS_WIN) return IsDebuggerPresent(); +#elif defined(Q_OS_MACOS) + auto equals = [](CFStringRef str1, CFStringRef str2) -> bool { + return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo; + }; + + // Check if there is an exception handler for the process: + mach_msg_type_number_t portCount = 0; + exception_mask_t masks[EXC_TYPES_COUNT]; + mach_port_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; + exception_mask_t mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD); + kern_return_t result = task_get_exception_ports(mach_task_self(), mask, masks, &portCount, + ports, behaviors, flavors); + if (result == KERN_SUCCESS) { + for (mach_msg_type_number_t portIndex = 0; portIndex < portCount; ++portIndex) { + if (MACH_PORT_VALID(ports[portIndex])) { + return true; + } + } + } + + // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we + // leave it to the OS to do the stack trace. + CFStringRef crashReporterType = static_cast<CFStringRef>( + CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter"))); + if (crashReporterType == nullptr) + return true; + + const bool createsStackTrace = + !equals(crashReporterType, CFSTR("server")) && + !equals(crashReporterType, CFSTR("none")); + CFRelease(crashReporterType); + return createsStackTrace; #else // TODO return false; @@ -149,7 +188,7 @@ static void disableCoreDump() bool ok = false; const int disableCoreDump = qEnvironmentVariableIntValue("QTEST_DISABLE_CORE_DUMP", &ok); if (ok && disableCoreDump == 1) { -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) struct rlimit limit; limit.rlim_cur = 0; limit.rlim_max = 0; @@ -2061,7 +2100,7 @@ QString QTest::qFindTestData(const QString& base, const char *file, int line, co // 5. Try current directory if (found.isEmpty()) { - QString candidate = QString::fromLatin1("%1/%2").arg(QDir::currentPath()).arg(base); + const QString candidate = QDir::currentPath() + QLatin1Char('/') + base; if (QFileInfo::exists(candidate)) found = candidate; } @@ -2160,6 +2199,48 @@ QTestData &QTest::newRow(const char *dataTag) return *tbl->newData(dataTag); } +/*! + \since 5.9 + + Appends a new row to the current test data. The function's arguments are passed + to qsnprintf() for formatting according to \a format. See the qvsnprintf() + documentation for caveats and limitations. + + The formatted string will appear as the name of this test data in the test output. + + Returns a QTestData reference that can be used to stream in data. + + Example: + \snippet code/src_qtestlib_qtestcase.cpp addRow + + \b {Note:} This function can only be used in a test's data function + that is invoked by the test framework. + + See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for + a more extensive example. + + \sa addColumn(), QFETCH() +*/ +QTestData &QTest::addRow(const char *format, ...) +{ + QTEST_ASSERT_X(format, "QTest::addRow()", "Format string cannot be null"); + QTestTable *tbl = QTestTable::currentTestTable(); + QTEST_ASSERT_X(tbl, "QTest::addRow()", "Cannot add testdata outside of a _data slot."); + QTEST_ASSERT_X(tbl->elementCount(), "QTest::addRow()", "Must add columns before attempting to add rows."); + + char buf[1024]; + + va_list va; + va_start(va, format); + // we don't care about failures, we accept truncation, as well as trailing garbage. + // Names with more than 1K characters are nonsense, anyway. + (void)qvsnprintf(buf, sizeof buf, format, va); + buf[sizeof buf - 1] = '\0'; + va_end(va); + + return *tbl->newData(buf); +} + /*! \fn void QTest::addColumn(const char *name, T *dummy = 0) Adds a column with type \c{T} to the current test data. diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index 57e0486686..26d8ff2766 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -240,14 +240,14 @@ namespace QTest namespace Internal { template<typename T> // Output registered enums - inline typename QtPrivate::QEnableIf<QtPrivate::IsQEnumHelper<T>::Value, char*>::Type toString(T e) + inline typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(T e) { QMetaEnum me = QMetaEnum::fromType<T>(); return qstrdup(me.valueToKey(int(e))); // int cast is necessary to support enum classes } template <typename T> // Fallback - inline typename QtPrivate::QEnableIf<!QtPrivate::IsQEnumHelper<T>::Value, char*>::Type toString(const T &) + inline typename std::enable_if<!QtPrivate::IsQEnumHelper<T>::Value, char*>::type toString(const T &) { return Q_NULLPTR; } @@ -318,6 +318,7 @@ namespace QTest addColumnInternal(qMetaTypeId<T>(), name); } Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag); + Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2); template <typename T> inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected, diff --git a/src/testlib/qtestsystem.h b/src/testlib/qtestsystem.h index b38cd2bdb4..b39fa17a34 100644 --- a/src/testlib/qtestsystem.h +++ b/src/testlib/qtestsystem.h @@ -116,14 +116,14 @@ namespace QTest #ifdef QT_WIDGETS_LIB inline static bool qWaitForWindowActive(QWidget *widget, int timeout = 1000) { - if (QWindow *window = widget->windowHandle()) + if (QWindow *window = widget->window()->windowHandle()) return qWaitForWindowActive(window, timeout); return false; } inline static bool qWaitForWindowExposed(QWidget *widget, int timeout = 1000) { - if (QWindow *window = widget->windowHandle()) + if (QWindow *window = widget->window()->windowHandle()) return qWaitForWindowExposed(window, timeout); return false; } |