Improve std::tuple handling in tests

Currently when doing comparison with std::tuple the fallback toString
method is called which returns a Q_NULLPTR thus not allowing proper
diagnostic of the values that triggered an error. This patch
adds support for std::tuple to improve the tests output readability.

[ChangeLog][QtTest][QCOMPARE] Now outputs contents of std::tuple on
failure.

Change-Id: I046a55e2ce44c3f7728d51e4745120d38aa5e007
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Samuel Gaist 2017-12-07 09:46:30 +01:00
parent 9998654eac
commit 04b180f7f2
13 changed files with 279 additions and 0 deletions

View File

@ -59,6 +59,8 @@
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
#include <memory>
QT_BEGIN_NAMESPACE
@ -215,6 +217,25 @@ inline char *toString(const std::pair<T1, T2> &pair)
return toString(QString::asprintf("std::pair(%s,%s)", first.data(), second.data()));
}
template <typename Tuple, int... I>
inline char *toString(const Tuple & tuple, QtPrivate::IndexesList<I...>) {
using UP = std::unique_ptr<char[]>;
// Generate a table of N + 1 elements where N is the number of
// elements in the tuple.
// The last element is needed to support the empty tuple use case.
const UP data[] = {
UP(toString(std::get<I>(tuple)))..., UP{}
};
return formatString("std::tuple(", ")", sizeof...(I), data[I].get()...);
}
template <class... Types>
inline char *toString(const std::tuple<Types...> &tuple)
{
static const std::size_t params_count = sizeof...(Types);
return toString(tuple, typename QtPrivate::Indexes<params_count>::Value());
}
inline char *toString(std::nullptr_t)
{
return toString(QLatin1String("nullptr"));

View File

@ -1146,6 +1146,31 @@ void *fetchData(QTestData *data, const char *tagName, int typeId)
return data->data(idx);
}
/*!
* \internal
*/
char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...)
{
va_list ap;
va_start(ap, numArguments);
QByteArray arguments;
arguments += prefix;
if (numArguments > 0) {
arguments += va_arg(ap, const char *);
for (size_t i = 1; i < numArguments; ++i) {
arguments += ", ";
arguments += va_arg(ap, const char *);
}
}
va_end(ap);
arguments += suffix;
return qstrdup(arguments.constData());
}
/*!
\fn char* QTest::toHexRepresentation(const char *ba, int length)

View File

@ -283,6 +283,9 @@ namespace QTest
template <typename T1, typename T2>
inline char *toString(const std::pair<T1, T2> &pair);
template <class... Types>
inline char *toString(const std::tuple<Types...> &tuple);
Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length);
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
@ -388,6 +391,8 @@ namespace QTest
Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual,
const char *expected, const char *file, int line);
Q_TESTLIB_EXPORT char *formatString(const char *prefix, const char *suffix, size_t numArguments, ...);
#ifndef Q_QDOC
QTEST_COMPARE_DECL(short)
QTEST_COMPARE_DECL(ushort)

View File

@ -0,0 +1,34 @@
<Environment>
<QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
<QtBuild/>
<QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
</Environment>
<TestFunction name="initTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testEmptyTuple">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testSimpleTuple">
<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (std::tuple<int>{1}): std::tuple(1)
Expected (std::tuple<int>{2}): std::tuple(2)]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testTuple">
<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (tuple1): std::tuple(42, 'Y', "tuple1")
Expected (tuple2): std::tuple(42, 'Y', "tuple2")]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<Duration msecs="0"/>

View File

@ -0,0 +1,33 @@
TAP version 13
# tst_TupleDiagnostics
ok 1 - initTestCase()
ok 2 - testEmptyTuple()
not ok 3 - testSimpleTuple()
---
type: QCOMPARE
message: Compared values are not the same
wanted: std::tuple(2) (std::tuple<int>{2})
found: std::tuple(1) (std::tuple<int>{1})
expected: std::tuple(2) (std::tuple<int>{2})
actual: std::tuple(1) (std::tuple<int>{1})
at: tst_TupleDiagnostics::testSimpleTuple() (/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp:53)
file: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
line: 53
...
not ok 4 - testTuple()
---
type: QCOMPARE
message: Compared values are not the same
wanted: std::tuple(42, 'Y', "tuple2") (tuple2)
found: std::tuple(42, 'Y', "tuple1") (tuple1)
expected: std::tuple(42, 'Y', "tuple2") (tuple2)
actual: std::tuple(42, 'Y', "tuple1") (tuple1)
at: tst_TupleDiagnostics::testTuple() (/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp:60)
file: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp
line: 60
...
ok 5 - cleanupTestCase()
1..5
# tests 5
# pass 3
# fail 2

View File

@ -0,0 +1,14 @@
##teamcity[testSuiteStarted name='tst_TupleDiagnostics' flowId='tst_TupleDiagnostics']
##teamcity[testStarted name='initTestCase()' flowId='tst_TupleDiagnostics']
##teamcity[testFinished name='initTestCase()' flowId='tst_TupleDiagnostics']
##teamcity[testStarted name='testEmptyTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testFinished name='testEmptyTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testStarted name='testSimpleTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testFailed name='testSimpleTuple()' message='Failure! |[Loc: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (std::tuple<int>{1}): std::tuple(1)|n Expected (std::tuple<int>{2}): std::tuple(2)' flowId='tst_TupleDiagnostics']
##teamcity[testFinished name='testSimpleTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testStarted name='testTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testFailed name='testTuple()' message='Failure! |[Loc: /localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)|]' details='Compared values are not the same|n Actual (tuple1): std::tuple(42, |'Y|', "tuple1")|n Expected (tuple2): std::tuple(42, |'Y|', "tuple2")' flowId='tst_TupleDiagnostics']
##teamcity[testFinished name='testTuple()' flowId='tst_TupleDiagnostics']
##teamcity[testStarted name='cleanupTestCase()' flowId='tst_TupleDiagnostics']
##teamcity[testFinished name='cleanupTestCase()' flowId='tst_TupleDiagnostics']
##teamcity[testSuiteFinished name='tst_TupleDiagnostics' flowId='tst_TupleDiagnostics']

View File

@ -0,0 +1,15 @@
********* Start testing of tst_TupleDiagnostics *********
Config: Using QtTest library
PASS : tst_TupleDiagnostics::initTestCase()
PASS : tst_TupleDiagnostics::testEmptyTuple()
FAIL! : tst_TupleDiagnostics::testSimpleTuple() Compared values are not the same
Actual (std::tuple<int>{1}): std::tuple(1)
Expected (std::tuple<int>{2}): std::tuple(2)
Loc: [/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)]
FAIL! : tst_TupleDiagnostics::testTuple() Compared values are not the same
Actual (tuple1): std::tuple(42, 'Y', "tuple1")
Expected (tuple2): std::tuple(42, 'Y', "tuple2")
Loc: [/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp(0)]
PASS : tst_TupleDiagnostics::cleanupTestCase()
Totals: 3 passed, 2 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of tst_TupleDiagnostics *********

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestCase name="tst_TupleDiagnostics">
<Environment>
<QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
<QtBuild/>
<QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
</Environment>
<TestFunction name="initTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testEmptyTuple">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testSimpleTuple">
<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (std::tuple<int>{1}): std::tuple(1)
Expected (std::tuple<int>{2}): std::tuple(2)]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="testTuple">
<Incident type="fail" file="/localqtbase/tests/auto/testlib/selftests/tuplediagnostics/tst_tuplediagnostics.cpp" line="0">
<Description><![CDATA[Compared values are not the same
Actual (tuple1): std::tuple(42, 'Y', "tuple1")
Expected (tuple2): std::tuple(42, 'Y', "tuple2")]]></Description>
</Incident>
<Duration msecs="0"/>
</TestFunction>
<TestFunction name="cleanupTestCase">
<Incident type="pass" file="" line="0" />
<Duration msecs="0"/>
</TestFunction>
<Duration msecs="0"/>
</TestCase>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<testsuite errors="0" failures="2" tests="5" name="tst_TupleDiagnostics">
<properties>
<property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
<property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
<property value="" name="QtBuild"/>
</properties>
<testcase result="pass" name="initTestCase"/>
<testcase result="pass" name="testEmptyTuple"/>
<testcase result="fail" name="testSimpleTuple">
<failure message="Compared values are not the same
Actual (std::tuple&lt;int&gt;{1}): std::tuple(1)
Expected (std::tuple&lt;int&gt;{2}): std::tuple(2)" result="fail"/>
</testcase>
<testcase result="fail" name="testTuple">
<failure message="Compared values are not the same
Actual (tuple1): std::tuple(42, &apos;Y&apos;, &quot;tuple1&quot;)
Expected (tuple2): std::tuple(42, &apos;Y&apos;, &quot;tuple2&quot;)" result="fail"/>
</testcase>
<testcase result="pass" name="cleanupTestCase"/>
<system-err/>
</testsuite>

View File

@ -45,6 +45,7 @@ SUBPROGRAMS = \
sleep \
strcmp \
subtest \
tuplediagnostics \
verbose1 \
verbose2 \
verifyexceptionthrown \

View File

@ -494,6 +494,7 @@ void tst_Selftests::runSubTest_data()
<< "sleep"
<< "strcmp"
<< "subtest"
<< "tuplediagnostics"
<< "verbose1"
<< "verbose2"
#ifndef QT_NO_EXCEPTIONS

View File

@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2017 Samuel Gaist <samuel.gaist@edeltech.ch>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// Make sure we get a real Q_ASSERT even in release builds
#ifdef QT_NO_DEBUG
# undef QT_NO_DEBUG
#endif
#include <QtTest/QtTest>
class tst_TupleDiagnostics: public QObject
{
Q_OBJECT
private slots:
void testEmptyTuple() const;
void testSimpleTuple() const;
void testTuple() const;
};
void tst_TupleDiagnostics::testEmptyTuple() const
{
QCOMPARE(std::tuple<>{}, std::tuple<>{});
}
void tst_TupleDiagnostics::testSimpleTuple() const
{
QCOMPARE(std::tuple<int>{1}, std::tuple<int>{2});
}
void tst_TupleDiagnostics::testTuple() const
{
std::tuple<int, char, QString> tuple1{42, 'Y', QStringLiteral("tuple1")};
std::tuple<int, char, QString> tuple2{42, 'Y', QStringLiteral("tuple2")};
QCOMPARE(tuple1, tuple2);
}
QTEST_MAIN(tst_TupleDiagnostics)
#include "tst_tuplediagnostics.moc"

View File

@ -0,0 +1,6 @@
SOURCES += tst_tuplediagnostics.cpp
QT = core testlib
CONFIG -= app_bundle debug_and_release_target
TARGET = tuplediagnostics