From ec75c0f6847dd329dc502ad0fc583f736e02c2d1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 27 Aug 2014 23:16:13 +0200 Subject: tst_QString: refactor the append tests It is tedious to test all the overloads of QString::append(), so get the help of the compiler to do it. The framework developed for this will be used in subsequent commits for prepend and insert, too. Change-Id: I89df581b6d037a5af80b34dd6b5d37ac7484c774 Reviewed-by: Thiago Macieira --- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 215 +++++++++++++++++++++-- 1 file changed, 203 insertions(+), 12 deletions(-) (limited to 'tests/auto/corelib/tools/qstring/tst_qstring.cpp') diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 647a75ceb2..47ce067e6a 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -65,6 +65,150 @@ const QString padded = QString::fromLatin1(" %1 ").arg(string); \ QStringRef ref = padded.midRef(1, padded.size() - 2); +namespace { + +// this wraps an argument to a QString function, as well as how to apply +// the argument to a given QString member function. +template +class Arg; + +class ArgBase +{ +protected: + QString pinned; + explicit ArgBase(const char *str) + : pinned(QString::fromLatin1(str)) {} +}; + +template <> +class Arg : ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template + void apply0(QString &s, MemFun mf) const + { Q_FOREACH (QChar ch, this->pinned) (s.*mf)(ch); } +}; + +template <> +class Arg : ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(this->pinned); } +}; + +template <> +class Arg : ArgBase +{ + QStringRef ref() const + { return this->pinned.isNull() ? QStringRef() : this->pinned.midRef(0) ; } +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(ref()); } +}; + +template <> +class Arg > : ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(this->pinned.constData(), this->pinned.length()); } +}; + +template <> +class Arg +{ + QLatin1String l1; +public: + explicit Arg(const char *str) : l1(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(l1); } +}; + +template <> +class Arg +{ +protected: + const char *str; +public: + explicit Arg(const char *str) : str(str) {} + + template + void apply0(QString &s, MemFun mf) const + { + if (str) { + for (const char *it = str; *it; ++it) + (s.*mf)(*it); + } + } +}; + +template <> +class Arg +{ + const char *str; +public: + explicit Arg(const char *str) : str(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(str); } +}; + +template <> +class Arg +{ + QByteArray ba; +public: + explicit Arg(const char *str) : ba(str) {} + + template + void apply0(QString &s, MemFun mf) const + { (s.*mf)(ba); } +}; + +// const char* is not allowed as columns in data-driven tests (causes static_assert failure), +// so wrap it in a container (default ctor is a QMetaType/QVariant requirement): +class CharStarContainer +{ + const char *str; +public: + explicit Q_DECL_CONSTEXPR CharStarContainer(const char *s = Q_NULLPTR) : str(s) {} + Q_DECL_CONSTEXPR operator const char *() const { return str; } +}; + +} // unnamed namespace + +Q_DECLARE_METATYPE(CharStarContainer) + +// implementation helpers for append_impl/prepend_impl etc +template +static void do_apply0(MemFun mf) +{ + QFETCH(QString, s); + QFETCH(CharStarContainer, arg); + QFETCH(QString, expected); + + Arg(arg).apply0(s, mf); + + QCOMPARE(s, expected); + QCOMPARE(s.isEmpty(), expected.isEmpty()); + QCOMPARE(s.isNull(), expected.isNull()); +} + class tst_QString : public QObject { Q_OBJECT @@ -73,6 +217,12 @@ class tst_QString : public QObject void split_regexp(const QString &string, const QString &pattern, QStringList result); template void split(const QString &string, const QString &separator, QStringList result); + + template + void append_impl() const { do_apply0(MemFun(&QString::append)); } + template + void append_impl() const { append_impl(); } + void append_data(bool emptyIsNoop = false); public: tst_QString(); public slots: @@ -124,9 +274,27 @@ private slots: void prepend(); void prepend_bytearray_data(); void prepend_bytearray(); - void append(); - void append_bytearray_data(); - void append_bytearray(); + + void append_qstring() { append_impl(); } + void append_qstring_data() { append_data(); } + void append_qstringref() { append_impl(); } + void append_qstringref_data() { append_data(); } + void append_qlatin1string() { append_impl(); } + void append_qlatin1string_data() { append_data(); } + void append_qcharstar_int() { append_impl, QString&(QString::*)(const QChar *, int)>(); } + void append_qcharstar_int_data() { append_data(true); } + void append_qchar() { append_impl(); } + void append_qchar_data() { append_data(true); } + void append_qbytearray() { append_impl(); } + void append_qbytearray_data() { append_data(); } + void append_char() { append_impl(); } + void append_char_data() { append_data(true); } + void append_charstar() { append_impl(); } + void append_charstar_data() { append_data(); } + void append_special_cases(); + void append_bytearray_special_cases_data(); + void append_bytearray_special_cases(); + void operator_pluseq_bytearray_data(); void operator_pluseq_bytearray(); void operator_eqeq_bytearray_data(); @@ -2092,14 +2260,37 @@ void tst_QString::insert() QCOMPARE(a.insert(0, QLatin1String("a")), QString("aMontreal")); } -void tst_QString::append() +void tst_QString::append_data(bool emptyIsNoop) { - { - QString a; - a = "<>ABCABCABCABC"; - QCOMPARE(a.append(">"),QString("<>ABCABCABCABC>")); - } + QTest::addColumn("s"); + QTest::addColumn("arg"); + QTest::addColumn("expected"); + + const CharStarContainer nullC; + const CharStarContainer emptyC(""); + const CharStarContainer aC("a"); + const CharStarContainer bC("b"); + //const CharStarContainer abC("ab"); + const QString null; + const QString empty(""); + const QString a("a"); + //const QString b("b"); + const QString ab("ab"); + + QTest::newRow("null + null") << null << nullC << null; + QTest::newRow("null + empty") << null << emptyC << (emptyIsNoop ? null : empty); + QTest::newRow("null + a") << null << aC << a; + QTest::newRow("empty + null") << empty << nullC << empty; + QTest::newRow("empty + empty") << empty << emptyC << empty; + QTest::newRow("empty + a") << empty << aC << a; + QTest::newRow("a + null") << a << nullC << a; + QTest::newRow("a + empty") << a << emptyC << a; + QTest::newRow("a + b") << a << bC << ab; +} + +void tst_QString::append_special_cases() +{ { QString a; static const QChar unicode[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' }; @@ -2119,7 +2310,7 @@ void tst_QString::append() } } -void tst_QString::append_bytearray_data() +void tst_QString::append_bytearray_special_cases_data() { QTest::addColumn("str" ); QTest::addColumn("ba" ); @@ -2153,7 +2344,7 @@ void tst_QString::append_bytearray_data() QTest::newRow( "nonAsciiByteArray2") << QString() << QByteArray("\xc3\xa9") << QString::fromUtf8("\xc3\xa9"); } -void tst_QString::append_bytearray() +void tst_QString::append_bytearray_special_cases() { { QFETCH( QString, str ); @@ -2175,7 +2366,7 @@ void tst_QString::append_bytearray() void tst_QString::operator_pluseq_bytearray_data() { - append_bytearray_data(); + append_bytearray_special_cases_data(); } void tst_QString::operator_pluseq_bytearray() -- cgit v1.2.3