summaryrefslogtreecommitdiffstats
path: root/src/testlib/qtestcase.cpp
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2022-04-04 13:18:07 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2022-04-25 17:47:21 +0200
commit383368a32146c97c110ee95aac2c7e8b74aa06ef (patch)
tree0c49ce457441bc74478d20c700328d052be92926 /src/testlib/qtestcase.cpp
parent36507ae6175d07810ecba3b61a42a19e6edda5da (diff)
Support test-case selection based on global data tag
In the same ways as for blacklisting. In the process, move reporting of an unrecognised tag outside the global-data loop, as the tag might be, or start with, a global data tag; and also report the global data alongside the test-specific data. Indent the lines reporting tags, as this makes the structure of the lists more evident. Converted the tag argument to QLatin1String() to facilitate searching and matching. Updated documentation, including expanding on the option of specifying the data tags on the command-line. Drive-by: fixed a link in the documentation, removed a snippet that was nowhere used. [ChangeLog][QtTest] When specifying what tests to run on a QtTest command-line, it is now possible to include a global data tag in the same way as a function-specific data tag or in combination with it. Thus if the test reports itself as tst_Class::function(global:local), command-line option function:global:local will select that specific test and function:global will run all data-rows for the function on the given global data tag. Fixes: QTBUG-102269 Change-Id: I7c86d6026933b05f7994bfc3663a2ea6a47f5f38 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/testlib/qtestcase.cpp')
-rw-r--r--src/testlib/qtestcase.cpp60
1 files changed, 37 insertions, 23 deletions
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index c1b9e31d803..caaf22508db 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -327,7 +327,7 @@ public:
static QMetaMethod findMethod(const QObject *obj, const char *signature);
private:
- bool invokeTest(int index, const char *data, WatchDog *watchDog) const;
+ bool invokeTest(int index, QLatin1String tag, WatchDog *watchDog) const;
void invokeTestOnData(int index) const;
QMetaMethod m_initTestCaseMethod; // might not exist, check isValid().
@@ -1148,7 +1148,7 @@ public:
If the function was successfully called, true is returned, otherwise
false.
*/
-bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) const
+bool TestMethods::invokeTest(int index, QLatin1String tag, WatchDog *watchDog) const
{
QBenchmarkTestMethodData benchmarkData;
QBenchmarkTestMethodData::current = &benchmarkData;
@@ -1168,6 +1168,18 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
return globalDataCount ? gTable->testData(index)->dataTag() : nullptr;
};
+ const auto dataTagMatches = [](QLatin1String tag, QLatin1String local, QLatin1String global) {
+ if (tag.isEmpty()) // No tag specified => run all data sets for this function
+ return true;
+ if (tag == local || tag == global) // Equal to either => run it
+ return true;
+ // Also allow global:local as a match:
+ return tag.startsWith(global) && tag.endsWith(local) &&
+ tag.size() == global.size() + 1 + local.size() &&
+ tag[global.size()] == ':';
+ };
+ bool foundFunction = false;
+
/* For each entry in the global data table, do: */
do {
if (!gTable->isEmpty())
@@ -1180,7 +1192,6 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
break;
}
- bool foundFunction = false;
int curDataIndex = 0;
const int dataCount = table.dataCount();
const auto dataTag = [&table, dataCount](int index) {
@@ -1188,22 +1199,18 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
};
// Data tag requested but none available?
- if (data && !dataCount) {
- // Let empty data tag through.
- if (!*data)
- data = nullptr;
- else {
- fprintf(stderr, "Unknown testdata for function %s(): '%s'\n", name.constData(), data);
- fprintf(stderr, "Function has no testdata.\n");
- return false;
- }
+ if (!tag.isEmpty() && !dataCount && !globalDataCount) {
+ fprintf(stderr, "Unknown test data tag for function %s(): '%s'\n"
+ "Function has no testdata.\n", name.constData(), tag.data());
+ return false;
}
/* For each entry in this test's data table, do: */
do {
QTestResult::setSkipCurrentTest(false);
QTestResult::setBlacklistCurrentTest(false);
- if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) {
+ if (dataTagMatches(tag, QLatin1String(dataTag(curDataIndex)),
+ QLatin1String(globalDataTag(curGlobalDataIndex)))) {
foundFunction = true;
QTestPrivate::checkBlackLists(name.constData(), dataTag(curDataIndex),
@@ -1219,24 +1226,31 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
if (watchDog)
watchDog->testFinished();
- if (data)
+ if (!tag.isEmpty() && !globalDataCount)
break;
}
++curDataIndex;
} while (curDataIndex < dataCount);
- if (data && !foundFunction) {
- fprintf(stderr, "Unknown testdata for function %s: '%s()'\n", name.constData(), data);
- fprintf(stderr, "Available testdata:\n");
- for (int i = 0; i < table.dataCount(); ++i)
- fprintf(stderr, "%s\n", table.testData(i)->dataTag());
- return false;
- }
-
QTestResult::setCurrentGlobalTestData(nullptr);
++curGlobalDataIndex;
} while (curGlobalDataIndex < globalDataCount);
+ if (!tag.isEmpty() && !foundFunction) {
+ fprintf(stderr, "Unknown testdata for function %s(): '%s'\n", name.constData(), tag.data());
+ if (table.dataCount()) {
+ fputs("Available test-specific data tags:\n", stderr);
+ for (int i = 0; i < table.dataCount(); ++i)
+ fprintf(stderr, "\t%s\n", table.testData(i)->dataTag());
+ }
+ if (globalDataCount) {
+ fputs("Available global data tags:\n", stderr);
+ for (int i = 0; i < globalDataCount; ++i)
+ fprintf(stderr, "\t%s\n", gTable->testData(i)->dataTag());
+ }
+ return false;
+ }
+
QTestResult::finishedCurrentTestFunction();
QTestResult::setSkipCurrentTest(false);
QTestResult::setBlacklistCurrentTest(false);
@@ -1557,7 +1571,7 @@ void TestMethods::invokeTests(QObject *testObject) const
const char *data = nullptr;
if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
- const bool ok = invokeTest(i, data, watchDog.data());
+ const bool ok = invokeTest(i, QLatin1String(data), watchDog.data());
delete [] data;
if (!ok)
break;