tst_QVariant: convert some test functions to table-driven

Most of them were easy to change. The pair one was a bit of a stretch,
but still worked. I've removed the lines on QPair, since QPair is
std::pair in Qt 6.

Change-Id: I3d74c753055744deb8acfffd17246ec98c583d08
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Thiago Macieira 2022-11-04 09:32:53 -07:00
parent bdc8778d7a
commit 64dc886db7

View File

@ -86,6 +86,12 @@ class tst_QVariant : public QObject
{ {
Q_OBJECT Q_OBJECT
static void runTestFunction()
{
QFETCH(QFunctionPointer, testFunction);
testFunction();
}
public: public:
tst_QVariant(QObject *parent = nullptr) tst_QVariant(QObject *parent = nullptr)
: QObject(parent), customNonQObjectPointer(0) : QObject(parent), customNonQObjectPointer(0)
@ -293,11 +299,18 @@ private slots:
void implicitConstruction(); void implicitConstruction();
void iterateSequentialContainerElements_data();
void iterateSequentialContainerElements() { runTestFunction(); }
void iterateAssociativeContainerElements_data();
void iterateAssociativeContainerElements() { runTestFunction(); }
void iterateContainerElements(); void iterateContainerElements();
void pairElements(); void pairElements_data();
void pairElements() { runTestFunction(); }
void enums(); void enums_data();
void metaEnums(); void enums() { runTestFunction(); }
void metaEnums_data();
void metaEnums() { runTestFunction(); }
void nullConvert(); void nullConvert();
@ -4589,7 +4602,7 @@ void sortIterable(QSequentialIterable *iterable)
} }
template<typename Container> template<typename Container>
void testSequentialIteration() static void testSequentialIteration()
{ {
int numSeen = 0; int numSeen = 0;
Container sequence; Container sequence;
@ -4708,7 +4721,7 @@ void testSequentialIteration()
} }
template<typename Container> template<typename Container>
void testAssociativeIteration() static void testAssociativeIteration()
{ {
using Key = typename Container::key_type; using Key = typename Container::key_type;
using Mapped = typename Container::mapped_type; using Mapped = typename Container::mapped_type;
@ -4779,35 +4792,53 @@ void testAssociativeIteration()
QCOMPARE(f, iter.constEnd()); QCOMPARE(f, iter.constEnd());
} }
void tst_QVariant::iterateContainerElements() void tst_QVariant::iterateSequentialContainerElements_data()
{ {
testSequentialIteration<QQueue<int>>(); QTest::addColumn<QFunctionPointer>("testFunction");
testSequentialIteration<QQueue<QVariant>>(); #define ADD(T) QTest::newRow(#T) << &testSequentialIteration<T>
testSequentialIteration<QQueue<QString>>(); ADD(QQueue<int>);
testSequentialIteration<QList<int>>(); ADD(QQueue<QVariant>);
testSequentialIteration<QList<QVariant>>(); ADD(QQueue<QString>);
testSequentialIteration<QList<QString>>(); ADD(QList<int>);
testSequentialIteration<QList<QByteArray>>(); ADD(QList<QVariant>);
testSequentialIteration<QStack<int>>(); ADD(QList<QString>);
testSequentialIteration<QStack<QVariant>>(); ADD(QList<QByteArray>);
testSequentialIteration<QStack<QString>>(); ADD(QStack<int>);
testSequentialIteration<std::vector<int>>(); ADD(QStack<QVariant>);
testSequentialIteration<std::vector<QVariant>>(); ADD(QStack<QString>);
testSequentialIteration<std::vector<QString>>(); ADD(std::vector<int>);
testSequentialIteration<std::list<int>>(); ADD(std::vector<QVariant>);
testSequentialIteration<std::list<QVariant>>(); ADD(std::vector<QString>);
testSequentialIteration<std::list<QString>>(); ADD(std::list<int>);
testSequentialIteration<QStringList>(); ADD(std::list<QVariant>);
testSequentialIteration<QByteArrayList>(); ADD(std::list<QString>);
testSequentialIteration<QString>(); ADD(QStringList);
testSequentialIteration<QByteArray>(); ADD(QByteArrayList);
ADD(QString);
ADD(QByteArray);
#ifdef TEST_FORWARD_LIST #ifdef TEST_FORWARD_LIST
testSequentialIteration<std::forward_list<int>>(); ADD(std::forward_list<int>);
testSequentialIteration<std::forward_list<QVariant>>(); ADD(std::forward_list<QVariant>);
testSequentialIteration<std::forward_list<QString>>(); ADD(std::forward_list<QString>);
#endif #endif
#undef ADD
}
void tst_QVariant::iterateAssociativeContainerElements_data()
{
QTest::addColumn<QFunctionPointer>("testFunction");
#define ADD(C, K, V) QTest::newRow(#C #K #V) << &testAssociativeIteration<C<K, V>>;
ADD(QHash, int, bool);
ADD(QHash, int, int);
ADD(QMap, int, bool);
ADD(std::map, int, bool);
ADD(std::unordered_map, int, bool);
#undef ADD
}
void tst_QVariant::iterateContainerElements()
{
{ {
QVariantList ints; QVariantList ints;
ints << 1 << 2 << 3; ints << 1 << 2 << 3;
@ -4830,12 +4861,6 @@ void tst_QVariant::iterateContainerElements()
QCOMPARE(ints, intsCopy); QCOMPARE(ints, intsCopy);
} }
testAssociativeIteration<QHash<int, bool>>();
testAssociativeIteration<QHash<int, int>>();
testAssociativeIteration<QMap<int, bool>>();
testAssociativeIteration<std::map<int, bool>>();
testAssociativeIteration<std::unordered_map<int, bool>>();
{ {
QMap<int, QString> mapping; QMap<int, QString> mapping;
mapping.insert(1, "one"); mapping.insert(1, "one");
@ -4878,37 +4903,54 @@ void tst_QVariant::iterateContainerElements()
} }
} }
void tst_QVariant::pairElements() template <typename Pair> static void testVariantPairElements()
{ {
typedef QPair<QVariant, QVariant> QVariantPair; QFETCH(std::function<void(void *)>, makeValue);
Pair p;
makeValue(&p);
QVariant v = QVariant::fromValue(p);
#define TEST_PAIR_ELEMENT_ACCESS(PAIR, T1, T2, VALUE1, VALUE2) \ QVERIFY(v.canConvert<QVariantPair>());
{ \ QVariantPair pi = v.value<QVariantPair>();
PAIR<T1, T2> p(VALUE1, VALUE2); \ QCOMPARE(pi.first, QVariant::fromValue(p.first));
QVariant v = QVariant::fromValue(p); \ QCOMPARE(pi.second, QVariant::fromValue(p.second));
\
QVERIFY(v.canConvert<QVariantPair>()); \
QVariantPair pi = v.value<QVariantPair>(); \
QCOMPARE(pi.first, QVariant::fromValue(VALUE1)); \
QCOMPARE(pi.second, QVariant::fromValue(VALUE2)); \
}
TEST_PAIR_ELEMENT_ACCESS(QPair, int, int, 4, 5)
TEST_PAIR_ELEMENT_ACCESS(std::pair, int, int, 4, 5)
TEST_PAIR_ELEMENT_ACCESS(QPair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
TEST_PAIR_ELEMENT_ACCESS(std::pair, QString, QString, QStringLiteral("one"), QStringLiteral("two"))
TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, QVariant, 4, 5)
TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, QVariant, 4, 5)
TEST_PAIR_ELEMENT_ACCESS(QPair, QVariant, int, 41, 15)
TEST_PAIR_ELEMENT_ACCESS(std::pair, QVariant, int, 34, 65)
TEST_PAIR_ELEMENT_ACCESS(QPair, int, QVariant, 24, 25)
TEST_PAIR_ELEMENT_ACCESS(std::pair, int, QVariant, 44, 15)
} }
template<typename Enum> void testVariant(Enum value, bool *ok) void tst_QVariant::pairElements_data()
{ {
*ok = false; QTest::addColumn<QFunctionPointer>("testFunction");
QTest::addColumn<std::function<void(void *)>>("makeValue");
static auto makeString = [](auto &&value) -> QString {
using T = std::decay_t<decltype(value)>;
if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
return QString::number(value);
} else if constexpr (std::is_same_v<T, QVariant>) {
return value.toString();
} else {
return value;
}
};
auto addRow = [](auto &&first, auto &&second) {
using Pair = std::pair<std::decay_t<decltype(first)>, std::decay_t<decltype(second)>>;
std::function<void(void *)> makeValue = [=](void *pair) {
*static_cast<Pair *>(pair) = Pair{first, second};
};
QTest::addRow("%s", qPrintable(makeString(first) + u',' + makeString(second)))
<< &testVariantPairElements<Pair> << makeValue;
};
addRow(4, 5);
addRow(QStringLiteral("one"), QStringLiteral("two"));
addRow(QVariant(4), QVariant(5));
addRow(QVariant(41), 65);
addRow(41, QVariant(15));
}
template <auto value> static void testVariantEnum()
{
using Enum = decltype(value);
auto canLosslesslyConvert = [=](auto zero) { auto canLosslesslyConvert = [=](auto zero) {
return sizeof(value) <= sizeof(zero) || return sizeof(value) <= sizeof(zero) ||
value == Enum(decltype(zero)(qToUnderlying(value))); value == Enum(decltype(zero)(qToUnderlying(value)));
@ -4916,7 +4958,6 @@ template<typename Enum> void testVariant(Enum value, bool *ok)
bool losslessConvertToInt = canLosslesslyConvert(int{}); bool losslessConvertToInt = canLosslesslyConvert(int{});
QVariant var = QVariant::fromValue(value); QVariant var = QVariant::fromValue(value);
QCOMPARE(var.userType(), qMetaTypeId<Enum>()); QCOMPARE(var.userType(), qMetaTypeId<Enum>());
QVERIFY(var.canConvert<Enum>()); QVERIFY(var.canConvert<Enum>());
@ -5015,73 +5056,61 @@ template<typename Enum> void testVariant(Enum value, bool *ok)
QCOMPARE_EQ(QString::number(qToUnderlying(value)), var); QCOMPARE_EQ(QString::number(qToUnderlying(value)), var);
QCOMPARE_NE(var, QString::number(qToUnderlying(value2))); QCOMPARE_NE(var, QString::number(qToUnderlying(value2)));
QCOMPARE_NE(QString::number(qToUnderlying(value2)), var); QCOMPARE_NE(QString::number(qToUnderlying(value2)), var);
*ok = true;
} }
void tst_QVariant::enums() void tst_QVariant::enums_data()
{ {
bool ok = false; QTest::addColumn<QFunctionPointer>("testFunction");
testVariant(EnumTest_Enum0_value, &ok);
QVERIFY(ok); #define ADD(V) QTest::newRow(#V) << &testVariantEnum<V>
testVariant(EnumTest_Enum0_negValue, &ok); ADD(EnumTest_Enum0_value);
QVERIFY(ok); ADD(EnumTest_Enum0_negValue);
testVariant(EnumTest_Enum1_value, &ok); ADD(EnumTest_Enum1_value);
QVERIFY(ok); ADD(EnumTest_Enum1_bigValue);
testVariant(EnumTest_Enum1_bigValue, &ok); ADD(EnumTest_Enum3::EnumTest_Enum3_value);
QVERIFY(ok); ADD(EnumTest_Enum3::EnumTest_Enum3_bigValue);
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok); ADD(EnumTest_Enum4::EnumTest_Enum4_value);
QVERIFY(ok); ADD(EnumTest_Enum4::EnumTest_Enum4_bigValue);
testVariant(EnumTest_Enum3::EnumTest_Enum3_bigValue, &ok); ADD(EnumTest_Enum5::EnumTest_Enum5_value);
QVERIFY(ok); ADD(EnumTest_Enum6::EnumTest_Enum6_value);
testVariant(EnumTest_Enum4::EnumTest_Enum4_value, &ok); ADD(EnumTest_Enum7::EnumTest_Enum7_value);
QVERIFY(ok); ADD(EnumTest_Enum8::EnumTest_Enum8_value);
testVariant(EnumTest_Enum4::EnumTest_Enum4_bigValue, &ok); ADD(EnumTest_Enum3::EnumTest_Enum3_value);
QVERIFY(ok); #undef ADD
testVariant(EnumTest_Enum5::EnumTest_Enum5_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum6::EnumTest_Enum6_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum7::EnumTest_Enum7_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum8::EnumTest_Enum8_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
} }
template<typename Enum> void testVariantMeta(Enum value, bool *ok, const char *string) // ### C++20: this would be easier if QFlags were a structural type
template <typename Enum, auto Value> static void testVariantMetaEnum()
{ {
testVariant<Enum>(value, ok); Enum value(Value);
QVERIFY(ok); QFETCH(QString, string);
*ok = false;
QVariant var = QVariant::fromValue(value); QVariant var = QVariant::fromValue(value);
QVERIFY(var.canConvert<QString>()); QVERIFY(var.canConvert<QString>());
QVERIFY(var.canConvert<QByteArray>()); QVERIFY(var.canConvert<QByteArray>());
QCOMPARE(var.value<QString>(), QString::fromLatin1(string)); QCOMPARE(var.value<QString>(), string);
QCOMPARE(var.value<QByteArray>(), QByteArray(string)); QCOMPARE(var.value<QByteArray>(), string.toLatin1());
QVariant strVar = QString::fromLatin1(string); QVariant strVar = string;
QVERIFY(strVar.canConvert<Enum>()); QVERIFY(strVar.canConvert<Enum>());
// unary + to silence gcc warning // unary + to silence gcc warning
if ((+static_cast<qint64>(value) > INT_MAX) || (+static_cast<qint64>(value) < INT_MIN)) { if ((+static_cast<qint64>(value) > INT_MAX) || (+static_cast<qint64>(value) < INT_MIN)) {
QEXPECT_FAIL("", "QMetaEnum api uses 'int' as return type QTBUG-27451", Abort); QEXPECT_FAIL("", "QMetaEnum api uses 'int' as return type QTBUG-27451", Abort);
*ok = true;
} }
QCOMPARE(strVar.value<Enum>(), value); QCOMPARE(strVar.value<Enum>(), value);
strVar = QByteArray(string); strVar = string.toLatin1();
QVERIFY(strVar.canConvert<Enum>()); QVERIFY(strVar.canConvert<Enum>());
QCOMPARE(strVar.value<Enum>(), value); QCOMPARE(strVar.value<Enum>(), value);
*ok = true;
} }
void tst_QVariant::metaEnums() void tst_QVariant::metaEnums_data()
{ {
bool ok = false; QTest::addColumn<QFunctionPointer>("testFunction");
QTest::addColumn<QString>("string");
#define METAENUMS_TEST(Value) \ #define METAENUMS_TEST(Value) \
testVariantMeta(Value, &ok, #Value); QVERIFY(ok) QTest::newRow(#Value) << &testVariantMetaEnum<decltype(Value), Value> << #Value;
METAENUMS_TEST(MetaEnumTest_Enum0_value); METAENUMS_TEST(MetaEnumTest_Enum0_value);
METAENUMS_TEST(MetaEnumTest_Enum1_value); METAENUMS_TEST(MetaEnumTest_Enum1_value);
@ -5094,13 +5123,15 @@ void tst_QVariant::metaEnums()
METAENUMS_TEST(MetaEnumTest_Enum5_value); METAENUMS_TEST(MetaEnumTest_Enum5_value);
METAENUMS_TEST(MetaEnumTest_Enum6_value); METAENUMS_TEST(MetaEnumTest_Enum6_value);
METAENUMS_TEST(MetaEnumTest_Enum8_value); METAENUMS_TEST(MetaEnumTest_Enum8_value);
{ using namespace Qt; METAENUMS_TEST(RichText); }
#undef METAENUMS_TEST #undef METAENUMS_TEST
testVariantMeta(Qt::RichText, &ok, "RichText"); QTest::newRow("AlignBottom")
testVariantMeta(Qt::Alignment(Qt::AlignBottom), &ok, "AlignBottom"); << &testVariantMetaEnum<Qt::Alignment, Qt::AlignBottom> << "AlignBottom";
testVariantMeta(Qt::Alignment(Qt::AlignHCenter | Qt::AlignBottom), &ok,
"AlignHCenter|AlignBottom"); constexpr auto AlignHCenterBottom = Qt::AlignmentFlag((Qt::AlignHCenter | Qt::AlignBottom).toInt());
QTest::newRow("AlignHCenter|AlignBottom")
<< &testVariantMetaEnum<Qt::Alignment, AlignHCenterBottom> << "AlignHCenter|AlignBottom";
} }
void tst_QVariant::nullConvert() void tst_QVariant::nullConvert()