Added -datatags option to QTestLib
authorJo Asplin <jo.asplin@nokia.com>
Tue, 1 Nov 2011 11:19:39 +0000 (12:19 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 4 Nov 2011 18:23:33 +0000 (19:23 +0100)
(Note: This feature is ported from Qt 4.8.
 See the following commits:
  01575deafb7d26ca2431374e92c6d71de96547c7
  4866d1ba8afbab61e102942d1ea93b81fea053d6
)

Passing the -datatags option to a QTestLib program prints the
available data tags to standard output.

For completeness, the test case name is also printed
at the start of each output line. (Although the file name
is supposed to match the lower-case version of the test case
name, this is currently not true in all cases (particularly not
under tests/benchmarks/). Even if there was a script to enforce this
convention, the -datatags option provides this information in a
reliable way.)

Data tags for each test function (f() in this case) are printed in
four different ways depending on the presence of local and global
data tags:

Case 1: No tags:
    tst_MyTestCasetst_MyTestCase f

Case 2: Local tags only:
    tst_MyTestCase f local tag 1
    tst_MyTestCase f local tag 2
    ...

Case 3: Global tags only:
    tst_MyTestCase f __global__ global tag 1
    tst_MyTestCase f __global__ global tag 2
    ...

Case 4: Local and global tags:
    tst_MyTestCase f local tag 1 __global__ global tag 1
    tst_MyTestCase f local tag 2 __global__ global tag 1
    ...
    tst_MyTestCase f local tag 1 __global__ global tag 2
    tst_MyTestCase f local tag 2 __global__ global tag 2
    ...
    ...

Note that the string __global__ is assumed to be highly unlikely to occur
in a data tag (if it does, an ambiguity results).

Change-Id: Ib51aa0c3c32ad52e52ce519729292cf8f0ec5d50
Reviewed-by: Jason McDonald <jason.mcdonald@nokia.com>
Reviewed-by: Sergio Ahumada <sergio.ahumada@nokia.com>
12 files changed:
src/testlib/qtestcase.cpp
src/testlib/qtestlog.cpp
src/testlib/qtestlog_p.h
tests/auto/testlib/selftests/expected_printdatatags.txt [new file with mode: 0644]
tests/auto/testlib/selftests/expected_printdatatagswithglobaltags.txt [new file with mode: 0644]
tests/auto/testlib/selftests/printdatatags/printdatatags.pro [new file with mode: 0644]
tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp [new file with mode: 0644]
tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro [new file with mode: 0644]
tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp [new file with mode: 0644]
tests/auto/testlib/selftests/selftests.pro
tests/auto/testlib/selftests/selftests.qrc
tests/auto/testlib/selftests/tst_selftests.cpp

index 713004d..4e0205c 100644 (file)
@@ -1015,6 +1015,71 @@ static void qPrintTestSlots(FILE *stream)
     }
 }
 
+static void qPrintDataTags(FILE *stream)
+{
+    // Avoid invoking the actual test functions, and also avoid printing irrelevant output:
+    QTestLog::setPrintAvailableTagsMode();
+
+    // Get global data tags:
+    QTestTable::globalTestTable();
+    invokeMethod(QTest::currentTestObject, "initTestCase_data()");
+    const QTestTable *gTable = QTestTable::globalTestTable();
+
+    const QMetaObject *currTestMetaObj = QTest::currentTestObject->metaObject();
+
+    // Process test functions:
+    for (int i = 0; i < currTestMetaObj->methodCount(); ++i) {
+        QMetaMethod tf = currTestMetaObj->method(i);
+
+        if (isValidSlot(tf)) {
+
+            // Retrieve local tags:
+            QStringList localTags;
+            QTestTable table;
+            char *slot = qstrdup(tf.signature());
+            slot[strlen(slot) - 2] = '\0';
+            QByteArray member;
+            member.resize(qstrlen(slot) + qstrlen("_data()") + 1);
+            QTest::qt_snprintf(member.data(), member.size(), "%s_data()", slot);
+            invokeMethod(QTest::currentTestObject, member.constData());
+            for (int j = 0; j < table.dataCount(); ++j)
+                localTags << QLatin1String(table.testData(j)->dataTag());
+
+            // Print all tag combinations:
+            if (gTable->dataCount() == 0) {
+                if (localTags.count() == 0) {
+                    // No tags at all, so just print the test function:
+                    fprintf(stream, "%s %s\n", currTestMetaObj->className(), slot);
+                } else {
+                    // Only local tags, so print each of them:
+                    for (int k = 0; k < localTags.size(); ++k)
+                        fprintf(
+                            stream, "%s %s %s\n",
+                            currTestMetaObj->className(), slot, localTags.at(k).toLatin1().data());
+                }
+            } else {
+                for (int j = 0; j < gTable->dataCount(); ++j) {
+                    if (localTags.count() == 0) {
+                        // Only global tags, so print the current one:
+                        fprintf(
+                            stream, "%s %s __global__ %s\n",
+                            currTestMetaObj->className(), slot, gTable->testData(j)->dataTag());
+                    } else {
+                        // Local and global tags, so print each of the local ones and
+                        // the current global one:
+                        for (int k = 0; k < localTags.size(); ++k)
+                            fprintf(
+                                stream, "%s %s %s __global__ %s\n", currTestMetaObj->className(), slot,
+                                localTags.at(k).toLatin1().data(), gTable->testData(j)->dataTag());
+                    }
+                }
+            }
+
+            delete[] slot;
+        }
+    }
+}
+
 static int qToInt(char *str)
 {
     char *pEnd;
@@ -1061,6 +1126,8 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
          "\n"
          " Testing options:\n"
          " -functions          : Returns a list of current testfunctions\n"
+         " -datatags           : Returns a list of current data tags.\n"
+         "                       A global data tag is preceded by ' __global__ '.\n"
          " -eventdelay ms      : Set default delay for mouse and keyboard simulation to ms milliseconds\n"
          " -keydelay ms        : Set default delay for keyboard simulation to ms milliseconds\n"
          " -mousedelay ms      : Set default delay for mouse simulation to ms milliseconds\n"
@@ -1111,6 +1178,11 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml)
                 qPrintTestSlots(stdout);
                 exit(0);
             }
+        } else if (strcmp(argv[i], "-datatags") == 0) {
+            if (!qml) {
+                qPrintDataTags(stdout);
+                exit(0);
+            }
         } else if (strcmp(argv[i], "-txt") == 0) {
             logFormat = QTestLog::Plain;
         } else if (strcmp(argv[i], "-xunitxml") == 0) {
index 58de622..0951b9b 100644 (file)
@@ -258,6 +258,9 @@ namespace QTest {
 
 void QTestLog::enterTestFunction(const char* function)
 {
+    if (printAvailableTags)
+        return;
+
     QTEST_ASSERT(function);
 
     QTest::TestLoggers::enterTestFunction(function);
@@ -276,6 +279,9 @@ int QTestLog::unhandledIgnoreMessages()
 
 void QTestLog::leaveTestFunction()
 {
+    if (printAvailableTags)
+        return;
+
     QTest::IgnoreResultList::clearList(QTest::ignoreResultList);
     QTest::TestLoggers::leaveTestFunction();
 }
@@ -294,6 +300,9 @@ void QTestLog::printUnhandledIgnoreMessages()
 
 void QTestLog::addPass(const char *msg)
 {
+    if (printAvailableTags)
+        return;
+
     QTEST_ASSERT(msg);
 
     QTest::TestLoggers::addIncident(QAbstractTestLogger::Pass, msg);
@@ -431,4 +440,11 @@ void QTestLog::setMaxWarnings(int m)
     QTest::maxWarnings = m <= 0 ? INT_MAX : m + 2;
 }
 
+bool QTestLog::printAvailableTags = false;
+
+void QTestLog::setPrintAvailableTagsMode()
+{
+    printAvailableTags = true;
+}
+
 QT_END_NAMESPACE
index 692a36a..b2aa8c1 100644 (file)
@@ -93,9 +93,13 @@ public:
 
     static void setMaxWarnings(int max);
 
+    static void setPrintAvailableTagsMode();
+
 private:
     QTestLog();
     ~QTestLog();
+
+    static bool printAvailableTags;
 };
 
 QT_END_NAMESPACE
diff --git a/tests/auto/testlib/selftests/expected_printdatatags.txt b/tests/auto/testlib/selftests/expected_printdatatags.txt
new file mode 100644 (file)
index 0000000..ac22f23
--- /dev/null
@@ -0,0 +1,6 @@
+tst_MyTestCase a data tag a1 
+tst_MyTestCase a data tag a2
+tst_MyTestCase b
+tst_MyTestCase c data tag c1
+tst_MyTestCase c data tag c2
+tst_MyTestCase c data tag c3
diff --git a/tests/auto/testlib/selftests/expected_printdatatagswithglobaltags.txt b/tests/auto/testlib/selftests/expected_printdatatagswithglobaltags.txt
new file mode 100644 (file)
index 0000000..32feba4
--- /dev/null
@@ -0,0 +1,12 @@
+tst_MyTestCase a data tag a1  __global__ global data tag 1 
+tst_MyTestCase a data tag a2 __global__ global data tag 1 
+tst_MyTestCase a data tag a1  __global__ global data tag 2
+tst_MyTestCase a data tag a2 __global__ global data tag 2
+tst_MyTestCase b __global__ global data tag 1 
+tst_MyTestCase b __global__ global data tag 2
+tst_MyTestCase c data tag c1 __global__ global data tag 1 
+tst_MyTestCase c data tag c2 __global__ global data tag 1 
+tst_MyTestCase c data tag c3 __global__ global data tag 1 
+tst_MyTestCase c data tag c1 __global__ global data tag 2
+tst_MyTestCase c data tag c2 __global__ global data tag 2
+tst_MyTestCase c data tag c3 __global__ global data tag 2
diff --git a/tests/auto/testlib/selftests/printdatatags/printdatatags.pro b/tests/auto/testlib/selftests/printdatatags/printdatatags.pro
new file mode 100644 (file)
index 0000000..4db717f
--- /dev/null
@@ -0,0 +1,8 @@
+CONFIG += testcase
+SOURCES += tst_printdatatags.cpp
+QT = core testlib
+
+mac:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = printdatatags
diff --git a/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp b/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp
new file mode 100644 (file)
index 0000000..79f8890
--- /dev/null
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+class tst_MyTestCase: public QObject
+{
+    Q_OBJECT
+private slots:
+    void a_data() const;
+    void a() const;
+
+    void b() const;
+
+    void c_data() const;
+    void c() const;
+};
+
+void tst_MyTestCase::a_data() const
+{
+    QTest::addColumn<int>("x");
+    QTest::addColumn<int>("y");
+
+    QTest::newRow("data tag a1 ") << 1 << 2;
+    QTest::newRow("data tag a2") << 1 << 2;
+}
+
+void tst_MyTestCase::a() const
+{
+}
+
+void tst_MyTestCase::b() const
+{
+}
+
+void tst_MyTestCase::c_data() const
+{
+    QTest::addColumn<int>("x");
+
+    QTest::newRow("data tag c1") << 1;
+    QTest::newRow("data tag c2") << 1;
+    QTest::newRow("data tag c3") << 1;
+}
+
+void tst_MyTestCase::c() const
+{
+}
+
+QTEST_MAIN(tst_MyTestCase)
+
+#include "tst_printdatatags.moc"
diff --git a/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro b/tests/auto/testlib/selftests/printdatatagswithglobaltags/printdatatagswithglobaltags.pro
new file mode 100644 (file)
index 0000000..baec7da
--- /dev/null
@@ -0,0 +1,8 @@
+CONFIG += testcase
+SOURCES += tst_printdatatagswithglobaltags.cpp
+QT = core testlib
+
+mac:CONFIG -= app_bundle
+CONFIG -= debug_and_release_target
+
+TARGET = printdatatagswithglobaltags
diff --git a/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp b/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp
new file mode 100644 (file)
index 0000000..6b0e61b
--- /dev/null
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+class tst_MyTestCase: public QObject
+{
+    Q_OBJECT
+private slots:
+    void initTestCase_data() const;
+    void initTestCase() const;
+
+    void a_data() const;
+    void a() const;
+
+    void b() const;
+
+    void c_data() const;
+    void c() const;
+};
+
+void tst_MyTestCase::initTestCase_data() const
+{
+    QTest::addColumn<int>("f");
+    QTest::addColumn<int>("g");
+
+    QTest::newRow("global data tag 1 ") << 1 << 2;
+    QTest::newRow("global data tag 2") << 1 << 2;
+}
+
+void tst_MyTestCase::initTestCase() const
+{
+}
+
+void tst_MyTestCase::a_data() const
+{
+    QTest::addColumn<int>("x");
+    QTest::addColumn<int>("y");
+
+    QTest::newRow("data tag a1 ") << 1 << 2;
+    QTest::newRow("data tag a2") << 1 << 2;
+}
+
+void tst_MyTestCase::a() const
+{
+}
+
+void tst_MyTestCase::b() const
+{
+}
+
+void tst_MyTestCase::c_data() const
+{
+    QTest::addColumn<int>("x");
+
+    QTest::newRow("data tag c1") << 1;
+    QTest::newRow("data tag c2") << 1;
+    QTest::newRow("data tag c3") << 1;
+}
+
+void tst_MyTestCase::c() const
+{
+}
+
+QTEST_MAIN(tst_MyTestCase)
+
+#include "tst_printdatatagswithglobaltags.moc"
index a43ecdf..9f772eb 100644 (file)
@@ -5,7 +5,8 @@ SUBDIRS = subtest test warnings maxwarnings cmptest globaldata skip \
           skipinit skipinitdata datetime singleskip assert differentexec \
           exceptionthrow qexecstringlist datatable commandlinedata\
           benchlibwalltime benchlibcallgrind benchlibeventcounter benchlibtickcounter \
-          benchliboptions xunit badxml longstring float
+          benchliboptions xunit badxml longstring float printdatatags \
+          printdatatagswithglobaltags
 
 INSTALLS =
 
index 10c16cc..2baa49c 100644 (file)
@@ -93,6 +93,8 @@
         <file>expected_multiexec.txt</file>
         <file>expected_multiexec.xml</file>
         <file>expected_multiexec.xunitxml</file>
+        <file>expected_printdatatags.txt</file>
+        <file>expected_printdatatagswithglobaltags.txt</file>
         <file>expected_qexecstringlist.txt</file>
         <file>expected_singleskip.lightxml</file>
         <file>expected_singleskip.txt</file>
index 9a56ce8..7f82b7d 100644 (file)
@@ -325,6 +325,8 @@ void tst_Selftests::runSubTest_data()
         << "longstring"
         << "maxwarnings"
         << "multiexec"
+        << "printdatatags"
+        << "printdatatagswithglobaltags"
         << "qexecstringlist"
         << "singleskip"
         << "skip"
@@ -370,6 +372,13 @@ void tst_Selftests::runSubTest_data()
             else if (subtest == "badxml") {
                 arguments << "-eventcounter";
             }
+            else if (subtest == "printdatatags") {
+                arguments << "-datatags";
+            }
+            else if (subtest == "printdatatagswithglobaltags") {
+                arguments << "-datatags";
+            }
+
 
             // These tests don't work right unless logging plain text to
             // standard output, either because they execute multiple test
@@ -388,6 +397,12 @@ void tst_Selftests::runSubTest_data()
                 if (subtest == "benchliboptions") {
                     continue;
                 }
+                if (subtest == "printdatatags") {
+                    continue;
+                }
+                if (subtest == "printdatatagswithglobaltags") {
+                    continue;
+                }
                 // `crashes' will not output valid XML on platforms without a crash handler
                 if (subtest == "crashes") {
                     continue;