diff options
author | Marc Mutz <[email protected]> | 2024-07-22 14:37:59 +0200 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2024-08-03 12:30:05 +0200 |
commit | b5115d1c2fc73feb149a8ee97de011b3c75694fb (patch) | |
tree | 128068e5f13e4bfc2fad71a0bfec2cfa8456f690 | |
parent | a15ff49be73228bbbc72989736d32059322c414f (diff) |
QtTest: port from qsnprintf to std::snprintf and mark the module as qsnprintf-free
Drive-by remove an explicit NUL-termination (std::snprintf() does
that) and port a repeated use of printf argument checking to the
protect() idiom.
Pick-to: 6.8
Change-Id: Ida15940fe9aef0622e9836a229a398c909503a9a
Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r-- | src/testlib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/testlib/qabstracttestlogger.cpp | 4 | ||||
-rw-r--r-- | src/testlib/qcsvbenchmarklogger.cpp | 10 | ||||
-rw-r--r-- | src/testlib/qjunittestlogger.cpp | 10 | ||||
-rw-r--r-- | src/testlib/qplaintestlogger.cpp | 34 | ||||
-rw-r--r-- | src/testlib/qtestcase.cpp | 27 | ||||
-rw-r--r-- | src/testlib/qtestlog.cpp | 6 | ||||
-rw-r--r-- | src/testlib/qtestresult.cpp | 46 |
8 files changed, 76 insertions, 62 deletions
diff --git a/src/testlib/CMakeLists.txt b/src/testlib/CMakeLists.txt index 15c040a2e3c..186418669ac 100644 --- a/src/testlib/CMakeLists.txt +++ b/src/testlib/CMakeLists.txt @@ -70,6 +70,7 @@ qt_internal_add_module(Test QT_NO_CONTEXTLESS_CONNECT QT_NO_DATASTREAM QT_NO_FOREACH + QT_NO_QSNPRINTF QT_USE_NODISCARD_FILE_OPEN # Ensure uniform location info between release and debug builds QT_NO_MESSAGELOGCONTEXT diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp index de6fb635607..87975e6b6aa 100644 --- a/src/testlib/qabstracttestlogger.cpp +++ b/src/testlib/qabstracttestlogger.cpp @@ -9,6 +9,8 @@ #include <QtCore/qbytearray.h> #include <QtCore/qstring.h> +#include <cstdio> + #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -405,7 +407,7 @@ int qt_asprintf(QTestCharBuffer *str, const char *format, ...) do { va_start(ap, format); - res = qvsnprintf(str->data(), size, format, ap); + res = std::vsnprintf(str->data(), size, format, ap); va_end(ap); // vsnprintf() reliably '\0'-terminates Q_ASSERT(res < 0 || str->data()[res < size ? res : size - 1] == '\0'); diff --git a/src/testlib/qcsvbenchmarklogger.cpp b/src/testlib/qcsvbenchmarklogger.cpp index d4de8f08b7e..2d05172e3df 100644 --- a/src/testlib/qcsvbenchmarklogger.cpp +++ b/src/testlib/qcsvbenchmarklogger.cpp @@ -5,6 +5,8 @@ #include "qtestresult_p.h" #include "qbenchmark_p.h" +#include <cstdio> + /*! \internal \class QCsvBenchmarkLogger \inmodule QtTest @@ -61,10 +63,10 @@ void QCsvBenchmarkLogger::addBenchmarkResult(const QBenchmarkResult &result) char buf[1024]; // "function","[globaltag:]tag","metric",value_per_iteration,total,iterations - qsnprintf(buf, sizeof(buf), "\"%s\",\"%s%s%s\",\"%s\",%.13g,%.13g,%u\n", - fn, gtag, filler, tag, metric, - result.measurement.value / result.iterations, - result.measurement.value, result.iterations); + std::snprintf(buf, sizeof(buf), "\"%s\",\"%s%s%s\",\"%s\",%.13g,%.13g,%u\n", + fn, gtag, filler, tag, metric, + result.measurement.value / result.iterations, + result.measurement.value, result.iterations); outputString(buf); } diff --git a/src/testlib/qjunittestlogger.cpp b/src/testlib/qjunittestlogger.cpp index 4ee5788beea..eb3c38b8b16 100644 --- a/src/testlib/qjunittestlogger.cpp +++ b/src/testlib/qjunittestlogger.cpp @@ -11,6 +11,8 @@ #include <QtCore/qlibraryinfo.h> +#include <cstdio> + #include <string.h> QT_BEGIN_NAMESPACE @@ -93,16 +95,16 @@ void QJUnitTestLogger::stopLogging() { char buf[10]; - qsnprintf(buf, sizeof(buf), "%i", testCounter); + std::snprintf(buf, sizeof(buf), "%i", testCounter); currentTestSuite->addAttribute(QTest::AI_Tests, buf); - qsnprintf(buf, sizeof(buf), "%i", failureCounter); + std::snprintf(buf, sizeof(buf), "%i", failureCounter); currentTestSuite->addAttribute(QTest::AI_Failures, buf); - qsnprintf(buf, sizeof(buf), "%i", errorCounter); + std::snprintf(buf, sizeof(buf), "%i", errorCounter); currentTestSuite->addAttribute(QTest::AI_Errors, buf); - qsnprintf(buf, sizeof(buf), "%i", QTestLog::skipCount()); + std::snprintf(buf, sizeof(buf), "%i", QTestLog::skipCount()); currentTestSuite->addAttribute(QTest::AI_Skipped, buf); currentTestSuite->addAttribute(QTest::AI_Time, diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index cc757b4ad07..290d4253742 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -11,6 +11,7 @@ #include <QtCore/private/qlogging_p.h> #include <array> +#include <cstdio> #include <stdio.h> #include <stdlib.h> @@ -67,7 +68,7 @@ template <int N> struct FixedBufString template <typename... Args> void appendf(const char *format, Args... args) { // vsnprintf includes the terminating null - used += qsnprintf(buf.data() + used, MaxSize - used + 1, format, + used += std::snprintf(buf.data() + used, MaxSize - used + 1, format, args...); } @@ -413,13 +414,13 @@ void QPlainTestLogger::startLogging() char buf[1024]; if (QTestLog::verboseLevel() < 0) { - qsnprintf(buf, sizeof(buf), "Testing %s\n", QTestResult::currentTestObjectName()); + std::snprintf(buf, sizeof(buf), "Testing %s\n", QTestResult::currentTestObjectName()); } else { - qsnprintf(buf, sizeof(buf), - "********* Start testing of %s *********\n" - "Config: Using QtTest library " QTEST_VERSION_STR - ", %s, %s %s\n", QTestResult::currentTestObjectName(), QLibraryInfo::build(), - qPrintable(QSysInfo::productType()), qPrintable(QSysInfo::productVersion())); + std::snprintf(buf, sizeof(buf), + "********* Start testing of %s *********\n" + "Config: Using QtTest library " QTEST_VERSION_STR + ", %s, %s %s\n", QTestResult::currentTestObjectName(), QLibraryInfo::build(), + qPrintable(QSysInfo::productType()), qPrintable(QSysInfo::productVersion())); } outputMessage(buf); } @@ -429,16 +430,17 @@ void QPlainTestLogger::stopLogging() char buf[1024]; const int timeMs = qRound(QTestLog::msecsTotalTime()); if (QTestLog::verboseLevel() < 0) { - qsnprintf(buf, sizeof(buf), "Totals: %d passed, %d failed, %d skipped, %d blacklisted, %dms\n", - QTestLog::passCount(), QTestLog::failCount(), - QTestLog::skipCount(), QTestLog::blacklistCount(), timeMs); + std::snprintf(buf, sizeof(buf), + "Totals: %d passed, %d failed, %d skipped, %d blacklisted, %dms\n", + QTestLog::passCount(), QTestLog::failCount(), + QTestLog::skipCount(), QTestLog::blacklistCount(), timeMs); } else { - qsnprintf(buf, sizeof(buf), - "Totals: %d passed, %d failed, %d skipped, %d blacklisted, %dms\n" - "********* Finished testing of %s *********\n", - QTestLog::passCount(), QTestLog::failCount(), - QTestLog::skipCount(), QTestLog::blacklistCount(), timeMs, - QTestResult::currentTestObjectName()); + std::snprintf(buf, sizeof(buf), + "Totals: %d passed, %d failed, %d skipped, %d blacklisted, %dms\n" + "********* Finished testing of %s *********\n", + QTestLog::passCount(), QTestLog::failCount(), + QTestLog::skipCount(), QTestLog::blacklistCount(), timeMs, + QTestResult::currentTestObjectName()); } outputMessage(buf); diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 2de43eb33cb..463c850d3d3 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -61,6 +61,7 @@ #endif #include <chrono> #include <cmath> +#include <cstdio> #include <limits> #include <memory> #include <mutex> @@ -1349,7 +1350,7 @@ bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<Wat QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex)); if (curGlobalDataIndex == 0) { - qsnprintf(member, 512, "%s_data()", name.constData()); + std::snprintf(member, 512, "%s_data()", name.constData()); invokeTestMethodIfExists(member); if (QTestResult::skipCurrentTest()) break; @@ -2587,9 +2588,10 @@ QTestData &QTest::newRow(const char *dataTag) 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 function's arguments are passed to std::snprintf() for + formatting according to \a format. See the + \l{https://en.cppreference.com/w/cpp/io/c/fprintf}{std::snprintf() + documentation} for caveats and limitations. The test output will identify the test run with this test data using the name that results from this formatting. @@ -2622,8 +2624,7 @@ QTestData &QTest::addRow(const char *format, ...) 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'; + std::vsnprintf(buf, sizeof buf, format, va); va_end(va); return *tbl->newData(buf); @@ -2996,7 +2997,7 @@ bool QTest::qCompare(const QLatin1StringView &t1, QStringView t2, const char *ac template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \ { \ char *msg = new char[128]; \ - qsnprintf(msg, 128, #FORMAT, t); \ + std::snprintf(msg, 128, #FORMAT, t); \ return msg; \ } @@ -3053,7 +3054,7 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString<TYPE>(const TYPE &t) \ qstrncpy(msg, "nan", 128); \ break; \ default: \ - qsnprintf(msg, 128, #FORMAT, double(t)); \ + std::snprintf(msg, 128, #FORMAT, double(t)); \ massageExponent(msg); \ break; \ } \ @@ -3104,9 +3105,9 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString<char>(const char &t) break; default: if (c < 0x20 || c >= 0x7F) - qsnprintf(msg, 16, "'\\x%02x'", c); + std::snprintf(msg, 16, "'\\x%02x'", c); else - qsnprintf(msg, 16, "'%c'" , c); + std::snprintf(msg, 16, "'%c'" , c); } return msg; } @@ -3129,7 +3130,7 @@ char *QTest::toString(const char *str) char *QTest::toString(const volatile void *p) // Use volatile to match compare_ptr_helper() { char *msg = new char[128]; - qsnprintf(msg, 128, "%p", p); + std::snprintf(msg, 128, "%p", p); return msg; } @@ -3154,9 +3155,9 @@ char *QTest::toString(const QObject *o) const char *className = o->metaObject()->className(); char *msg = new char[256]; if (name.isEmpty()) - qsnprintf(msg, 256, "%s/%p", className, o); + std::snprintf(msg, 256, "%s/%p", className, o); else - qsnprintf(msg, 256, "%s/\"%s\"", className, qPrintable(name)); + std::snprintf(msg, 256, "%s/\"%s\"", className, qPrintable(name)); return msg; } diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 89149f3d47a..39178feb2b7 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -30,6 +30,8 @@ #include <QtCore/QRegularExpression> #endif +#include <cstdio> + #include <stdlib.h> #include <string.h> #include <limits.h> @@ -194,8 +196,8 @@ namespace QTest { const size_t maxMsgLen = 1024; char msg[maxMsgLen] = {'\0'}; - qsnprintf(msg, maxMsgLen, "Received a warning that resulted in a failure:\n%s", - qPrintable(message)); + std::snprintf(msg, maxMsgLen, "Received a warning that resulted in a failure:\n%s", + qPrintable(message)); QTestResult::addFailure(msg, context.file, context.line); return true; } diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp index 0e1c9d7ad95..24ab6f43b95 100644 --- a/src/testlib/qtestresult.cpp +++ b/src/testlib/qtestresult.cpp @@ -307,14 +307,14 @@ bool QTestResult::verify(bool statement, const char *statementStr, msg[0] = '\0'; if (QTestLog::verboseLevel() >= 2) { - qsnprintf(msg, maxMsgLen, "QVERIFY(%s)", statementStr); + std::snprintf(msg, maxMsgLen, "QVERIFY(%s)", statementStr); QTestLog::info(msg, file, line); } if (statement == !!QTest::expectFailMode) { - qsnprintf(msg, maxMsgLen, - statement ? "'%s' returned TRUE unexpectedly. (%s)" : "'%s' returned FALSE. (%s)", - statementStr, description ? description : ""); + std::snprintf(msg, maxMsgLen, + statement ? "'%s' returned TRUE unexpectedly. (%s)" : "'%s' returned FALSE. (%s)", + statementStr, description ? description : ""); } return checkStatement(statement, msg, file, line); @@ -350,20 +350,22 @@ void formatFailMessage(char *msg, size_t maxMsgLen, { const auto len1 = approx_wide_len(actual); const auto len2 = approx_wide_len(expected); - const int written = qsnprintf(msg, maxMsgLen, "%s\n", failureMsg); + const int written = std::snprintf(msg, maxMsgLen, "%s\n", failureMsg); msg += written; maxMsgLen -= written; + const auto protect = [](const char *s) { return s ? s : "<null>"; }; + if (val1 || val2) { - qsnprintf(msg, maxMsgLen, " %s(%s)%*s %s\n %s(%s)%*s %s", - leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":", - val1 ? val1 : "<null>", - rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":", - val2 ? val2 : "<null>"); + std::snprintf(msg, maxMsgLen, " %s(%s)%*s %s\n %s(%s)%*s %s", + leftArgNameForOp(op), actual, qMax(len1, len2) - len1 + 1, ":", + protect(val1), + rightArgNameForOp(op), expected, qMax(len1, len2) - len2 + 1, ":", + protect(val2)); } else { // only print variable names if neither value can be represented as a string - qsnprintf(msg, maxMsgLen, " %s: %s\n %s: %s", - leftArgNameForOp(op), actual, rightArgNameForOp(op), expected); + std::snprintf(msg, maxMsgLen, " %s: %s\n %s: %s", + leftArgNameForOp(op), actual, rightArgNameForOp(op), expected); } } @@ -409,7 +411,7 @@ static bool compareHelper(bool success, const char *failureMsg, QTEST_ASSERT(actual); if (QTestLog::verboseLevel() >= 2) { - qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); + std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); QTestLog::info(msg, file, line); } @@ -418,15 +420,15 @@ static bool compareHelper(bool success, const char *failureMsg, if (success) { if (QTest::expectFailMode) { - qsnprintf(msg, maxMsgLen, - "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); + std::snprintf(msg, maxMsgLen, + "QCOMPARE(%s, %s) returned TRUE unexpectedly.", actual, expected); } return checkStatement(success, msg, file, line); } if (!hasValues) { - qsnprintf(msg, maxMsgLen, "%s", failureMsg); + std::snprintf(msg, maxMsgLen, "%s", failureMsg); return checkStatement(success, msg, file, line); } @@ -453,14 +455,14 @@ static bool compareHelper(bool success, const char *failureMsg, QTEST_ASSERT(success || failureMsg); if (QTestLog::verboseLevel() >= 2) { - qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); + std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s)", actual, expected); QTestLog::info(msg, file, line); } if (success) { if (QTest::expectFailMode) { - qsnprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.", - actual, expected); + std::snprintf(msg, maxMsgLen, "QCOMPARE(%s, %s) returned TRUE unexpectedly.", + actual, expected); } return checkStatement(success, msg, file, line); } @@ -669,14 +671,14 @@ bool QTestResult::reportResult(bool success, const void *lhs, const void *rhs, QTEST_ASSERT(rhsExpr); if (QTestLog::verboseLevel() >= 2) { - qsnprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr); + std::snprintf(msg, maxMsgLen, "%s(%s, %s)", macroNameForOp(op), lhsExpr, rhsExpr); QTestLog::info(msg, file, line); } if (success) { if (QTest::expectFailMode) { - qsnprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.", - macroNameForOp(op), lhsExpr, rhsExpr); + std::snprintf(msg, maxMsgLen, "%s(%s, %s) returned TRUE unexpectedly.", + macroNameForOp(op), lhsExpr, rhsExpr); } return checkStatement(success, msg, file, line); } |