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
static void runTestFunction()
{
QFETCH(QFunctionPointer, testFunction);
testFunction();
}
public:
tst_QVariant(QObject *parent = nullptr)
: QObject(parent), customNonQObjectPointer(0)
@ -293,11 +299,18 @@ private slots:
void implicitConstruction();
void iterateSequentialContainerElements_data();
void iterateSequentialContainerElements() { runTestFunction(); }
void iterateAssociativeContainerElements_data();
void iterateAssociativeContainerElements() { runTestFunction(); }
void iterateContainerElements();
void pairElements();
void pairElements_data();
void pairElements() { runTestFunction(); }
void enums();
void metaEnums();
void enums_data();
void enums() { runTestFunction(); }
void metaEnums_data();
void metaEnums() { runTestFunction(); }
void nullConvert();
@ -4589,7 +4602,7 @@ void sortIterable(QSequentialIterable *iterable)
}
template<typename Container>
void testSequentialIteration()
static void testSequentialIteration()
{
int numSeen = 0;
Container sequence;
@ -4708,7 +4721,7 @@ void testSequentialIteration()
}
template<typename Container>
void testAssociativeIteration()
static void testAssociativeIteration()
{
using Key = typename Container::key_type;
using Mapped = typename Container::mapped_type;
@ -4779,35 +4792,53 @@ void testAssociativeIteration()
QCOMPARE(f, iter.constEnd());
}
void tst_QVariant::iterateContainerElements()
void tst_QVariant::iterateSequentialContainerElements_data()
{
testSequentialIteration<QQueue<int>>();
testSequentialIteration<QQueue<QVariant>>();
testSequentialIteration<QQueue<QString>>();
testSequentialIteration<QList<int>>();
testSequentialIteration<QList<QVariant>>();
testSequentialIteration<QList<QString>>();
testSequentialIteration<QList<QByteArray>>();
testSequentialIteration<QStack<int>>();
testSequentialIteration<QStack<QVariant>>();
testSequentialIteration<QStack<QString>>();
testSequentialIteration<std::vector<int>>();
testSequentialIteration<std::vector<QVariant>>();
testSequentialIteration<std::vector<QString>>();
testSequentialIteration<std::list<int>>();
testSequentialIteration<std::list<QVariant>>();
testSequentialIteration<std::list<QString>>();
testSequentialIteration<QStringList>();
testSequentialIteration<QByteArrayList>();
testSequentialIteration<QString>();
testSequentialIteration<QByteArray>();
QTest::addColumn<QFunctionPointer>("testFunction");
#define ADD(T) QTest::newRow(#T) << &testSequentialIteration<T>
ADD(QQueue<int>);
ADD(QQueue<QVariant>);
ADD(QQueue<QString>);
ADD(QList<int>);
ADD(QList<QVariant>);
ADD(QList<QString>);
ADD(QList<QByteArray>);
ADD(QStack<int>);
ADD(QStack<QVariant>);
ADD(QStack<QString>);
ADD(std::vector<int>);
ADD(std::vector<QVariant>);
ADD(std::vector<QString>);
ADD(std::list<int>);
ADD(std::list<QVariant>);
ADD(std::list<QString>);
ADD(QStringList);
ADD(QByteArrayList);
ADD(QString);
ADD(QByteArray);
#ifdef TEST_FORWARD_LIST
testSequentialIteration<std::forward_list<int>>();
testSequentialIteration<std::forward_list<QVariant>>();
testSequentialIteration<std::forward_list<QString>>();
ADD(std::forward_list<int>);
ADD(std::forward_list<QVariant>);
ADD(std::forward_list<QString>);
#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;
ints << 1 << 2 << 3;
@ -4830,12 +4861,6 @@ void tst_QVariant::iterateContainerElements()
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;
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) \
{ \
PAIR<T1, T2> p(VALUE1, VALUE2); \
QVariant v = QVariant::fromValue(p); \
\
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)
QVERIFY(v.canConvert<QVariantPair>());
QVariantPair pi = v.value<QVariantPair>();
QCOMPARE(pi.first, QVariant::fromValue(p.first));
QCOMPARE(pi.second, QVariant::fromValue(p.second));
}
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) {
return sizeof(value) <= sizeof(zero) ||
value == Enum(decltype(zero)(qToUnderlying(value)));
@ -4916,7 +4958,6 @@ template<typename Enum> void testVariant(Enum value, bool *ok)
bool losslessConvertToInt = canLosslesslyConvert(int{});
QVariant var = QVariant::fromValue(value);
QCOMPARE(var.userType(), qMetaTypeId<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_NE(var, QString::number(qToUnderlying(value2)));
QCOMPARE_NE(QString::number(qToUnderlying(value2)), var);
*ok = true;
}
void tst_QVariant::enums()
void tst_QVariant::enums_data()
{
bool ok = false;
testVariant(EnumTest_Enum0_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum0_negValue, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum1_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum1_bigValue, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum3::EnumTest_Enum3_bigValue, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum4::EnumTest_Enum4_value, &ok);
QVERIFY(ok);
testVariant(EnumTest_Enum4::EnumTest_Enum4_bigValue, &ok);
QVERIFY(ok);
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);
QTest::addColumn<QFunctionPointer>("testFunction");
#define ADD(V) QTest::newRow(#V) << &testVariantEnum<V>
ADD(EnumTest_Enum0_value);
ADD(EnumTest_Enum0_negValue);
ADD(EnumTest_Enum1_value);
ADD(EnumTest_Enum1_bigValue);
ADD(EnumTest_Enum3::EnumTest_Enum3_value);
ADD(EnumTest_Enum3::EnumTest_Enum3_bigValue);
ADD(EnumTest_Enum4::EnumTest_Enum4_value);
ADD(EnumTest_Enum4::EnumTest_Enum4_bigValue);
ADD(EnumTest_Enum5::EnumTest_Enum5_value);
ADD(EnumTest_Enum6::EnumTest_Enum6_value);
ADD(EnumTest_Enum7::EnumTest_Enum7_value);
ADD(EnumTest_Enum8::EnumTest_Enum8_value);
ADD(EnumTest_Enum3::EnumTest_Enum3_value);
#undef ADD
}
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);
QVERIFY(ok);
*ok = false;
Enum value(Value);
QFETCH(QString, string);
QVariant var = QVariant::fromValue(value);
QVERIFY(var.canConvert<QString>());
QVERIFY(var.canConvert<QByteArray>());
QCOMPARE(var.value<QString>(), QString::fromLatin1(string));
QCOMPARE(var.value<QByteArray>(), QByteArray(string));
QCOMPARE(var.value<QString>(), string);
QCOMPARE(var.value<QByteArray>(), string.toLatin1());
QVariant strVar = QString::fromLatin1(string);
QVariant strVar = string;
QVERIFY(strVar.canConvert<Enum>());
// unary + to silence gcc warning
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);
*ok = true;
}
QCOMPARE(strVar.value<Enum>(), value);
strVar = QByteArray(string);
strVar = string.toLatin1();
QVERIFY(strVar.canConvert<Enum>());
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) \
testVariantMeta(Value, &ok, #Value); QVERIFY(ok)
QTest::newRow(#Value) << &testVariantMetaEnum<decltype(Value), Value> << #Value;
METAENUMS_TEST(MetaEnumTest_Enum0_value);
METAENUMS_TEST(MetaEnumTest_Enum1_value);
@ -5094,13 +5123,15 @@ void tst_QVariant::metaEnums()
METAENUMS_TEST(MetaEnumTest_Enum5_value);
METAENUMS_TEST(MetaEnumTest_Enum6_value);
METAENUMS_TEST(MetaEnumTest_Enum8_value);
{ using namespace Qt; METAENUMS_TEST(RichText); }
#undef METAENUMS_TEST
testVariantMeta(Qt::RichText, &ok, "RichText");
testVariantMeta(Qt::Alignment(Qt::AlignBottom), &ok, "AlignBottom");
testVariantMeta(Qt::Alignment(Qt::AlignHCenter | Qt::AlignBottom), &ok,
"AlignHCenter|AlignBottom");
QTest::newRow("AlignBottom")
<< &testVariantMetaEnum<Qt::Alignment, Qt::AlignBottom> << "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()