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:
parent
9998654eac
commit
04b180f7f2
@ -59,6 +59,8 @@
|
|||||||
#include <QtCore/qsize.h>
|
#include <QtCore/qsize.h>
|
||||||
#include <QtCore/qrect.h>
|
#include <QtCore/qrect.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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()));
|
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)
|
inline char *toString(std::nullptr_t)
|
||||||
{
|
{
|
||||||
return toString(QLatin1String("nullptr"));
|
return toString(QLatin1String("nullptr"));
|
||||||
|
@ -1146,6 +1146,31 @@ void *fetchData(QTestData *data, const char *tagName, int typeId)
|
|||||||
return data->data(idx);
|
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)
|
\fn char* QTest::toHexRepresentation(const char *ba, int length)
|
||||||
|
|
||||||
|
@ -283,6 +283,9 @@ namespace QTest
|
|||||||
template <typename T1, typename T2>
|
template <typename T1, typename T2>
|
||||||
inline char *toString(const std::pair<T1, T2> &pair);
|
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 *toHexRepresentation(const char *ba, int length);
|
||||||
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
|
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
|
||||||
Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
|
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,
|
Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual,
|
||||||
const char *expected, const char *file, int line);
|
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
|
#ifndef Q_QDOC
|
||||||
QTEST_COMPARE_DECL(short)
|
QTEST_COMPARE_DECL(short)
|
||||||
QTEST_COMPARE_DECL(ushort)
|
QTEST_COMPARE_DECL(ushort)
|
||||||
|
@ -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"/>
|
33
tests/auto/testlib/selftests/expected_tuplediagnostics.tap
Normal file
33
tests/auto/testlib/selftests/expected_tuplediagnostics.tap
Normal 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
|
@ -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']
|
15
tests/auto/testlib/selftests/expected_tuplediagnostics.txt
Normal file
15
tests/auto/testlib/selftests/expected_tuplediagnostics.txt
Normal 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 *********
|
37
tests/auto/testlib/selftests/expected_tuplediagnostics.xml
Normal file
37
tests/auto/testlib/selftests/expected_tuplediagnostics.xml
Normal 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>
|
@ -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<int>{1}): std::tuple(1)
|
||||||
|
Expected (std::tuple<int>{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, 'Y', "tuple1")
|
||||||
|
Expected (tuple2): std::tuple(42, 'Y', "tuple2")" result="fail"/>
|
||||||
|
</testcase>
|
||||||
|
<testcase result="pass" name="cleanupTestCase"/>
|
||||||
|
<system-err/>
|
||||||
|
</testsuite>
|
@ -45,6 +45,7 @@ SUBPROGRAMS = \
|
|||||||
sleep \
|
sleep \
|
||||||
strcmp \
|
strcmp \
|
||||||
subtest \
|
subtest \
|
||||||
|
tuplediagnostics \
|
||||||
verbose1 \
|
verbose1 \
|
||||||
verbose2 \
|
verbose2 \
|
||||||
verifyexceptionthrown \
|
verifyexceptionthrown \
|
||||||
|
@ -494,6 +494,7 @@ void tst_Selftests::runSubTest_data()
|
|||||||
<< "sleep"
|
<< "sleep"
|
||||||
<< "strcmp"
|
<< "strcmp"
|
||||||
<< "subtest"
|
<< "subtest"
|
||||||
|
<< "tuplediagnostics"
|
||||||
<< "verbose1"
|
<< "verbose1"
|
||||||
<< "verbose2"
|
<< "verbose2"
|
||||||
#ifndef QT_NO_EXCEPTIONS
|
#ifndef QT_NO_EXCEPTIONS
|
||||||
|
@ -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"
|
@ -0,0 +1,6 @@
|
|||||||
|
SOURCES += tst_tuplediagnostics.cpp
|
||||||
|
QT = core testlib
|
||||||
|
|
||||||
|
CONFIG -= app_bundle debug_and_release_target
|
||||||
|
|
||||||
|
TARGET = tuplediagnostics
|
Loading…
x
Reference in New Issue
Block a user