/* * Copyright 2012-2016 Canonical Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authors: * Renato Araujo Oliveira Filho * Marco Trevisan */ #include #include "converter.h" #include #include #include class QGVariantType { public: QGVariantType() : type(NULL) {} QGVariantType(const GVariantType *gvtype) : type(gvtype) {} const GVariantType *getType() const { return type; } operator const GVariantType*() const { return type; } private: const GVariantType *type; }; Q_DECLARE_METATYPE(QGVariantType); class QGVariant { public: QGVariant() : variant(NULL) {} ~QGVariant() { if (variant) g_variant_unref(variant); } QGVariant(GVariant *gv) : variant(g_variant_ref_sink(gv)) {} QGVariant(const QGVariant &other) : QGVariant(other.variant) {} GVariant *gvariant() const { return variant; } operator GVariant*() const { return variant; } private: GVariant *variant; }; Q_DECLARE_METATYPE(QGVariant); class ConverterTest : public QObject { Q_OBJECT private: bool compare(const QVariant &qv, const GVariantType *type) { bool result; GVariant *gv = Converter::toGVariant(qv); result = g_variant_type_equal(g_variant_get_type(gv), type); if (!result) { qWarning() << "types are different: QVariant:" << qv.typeName() << "Result:" << g_variant_type_peek_string(g_variant_get_type(gv)) << "Expected:"<< g_variant_type_peek_string(type); } g_variant_unref(gv); return result; } bool compare(GVariant *gv, const QVariant::Type type) { g_variant_ref_sink(gv); const QVariant& qv = Converter::toQVariant(gv); bool result = (qv.type() == type); if (!result) { qWarning() << "types are different: GVariant:" << g_variant_type_peek_string(g_variant_get_type(gv)) << "Result:" << qv.type() << "Expected:"<< type; } g_variant_unref(gv); return result; } bool compareWithSchema(const QVariant &qv, const QString strType) { GVariantType* expected_type; expected_type = g_variant_type_new(strType.toUtf8().data()); bool result; GVariant *gv = Converter::toGVariantWithSchema(qv, strType.toUtf8().data()); result = g_variant_type_equal(g_variant_get_type(gv), expected_type); if (!result) { qWarning() << "types are different: QVariant:" << qv.typeName() << "Result:" << g_variant_type_peek_string(g_variant_get_type(gv)) << "Expected:"<< g_variant_type_peek_string(expected_type); } g_variant_unref(gv); g_variant_type_free(expected_type); return result; } private Q_SLOTS: /* * Test converter QVariant to GVariant */ void testConvertToGVariant_data() { QTest::addColumn("value"); QTest::addColumn("expectedType"); QTest::newRow("Boolean") << QVariant(true) << QGVariantType(G_VARIANT_TYPE_BOOLEAN); QTest::newRow("Byte") << QVariant::fromValue(42) << QGVariantType(G_VARIANT_TYPE_BYTE); QTest::newRow("Int16") << QVariant::fromValue(-42) << QGVariantType(G_VARIANT_TYPE_INT16); QTest::newRow("UInt16") << QVariant::fromValue(-42) << QGVariantType(G_VARIANT_TYPE_UINT16); QTest::newRow("Int32") << QVariant(-42) << QGVariantType(G_VARIANT_TYPE_INT32); QTest::newRow("UInt32") << QVariant((uint)42) << QGVariantType(G_VARIANT_TYPE_UINT32); QTest::newRow("Int64") << QVariant::fromValue(-42) << QGVariantType(G_VARIANT_TYPE_INT64); QTest::newRow("UInt64") << QVariant::fromValue(42) << QGVariantType(G_VARIANT_TYPE_UINT64); QTest::newRow("Int64") << QVariant::fromValue(-42) << QGVariantType(G_VARIANT_TYPE_INT64); QTest::newRow("UInt64") << QVariant::fromValue(42) << QGVariantType(G_VARIANT_TYPE_UINT64); QTest::newRow("Double") << QVariant((double)42.42) << QGVariantType(G_VARIANT_TYPE_DOUBLE); QTest::newRow("String") << QVariant(QString("42")) << QGVariantType(G_VARIANT_TYPE_STRING); QTest::newRow("String List") << QVariant(QStringList({"42", "42"})) << QGVariantType(G_VARIANT_TYPE_STRING_ARRAY); QTest::newRow("ByteArray") << QVariant(QByteArray("42")) << QGVariantType(G_VARIANT_TYPE_BYTESTRING); QTest::newRow("Map") << QVariant(QVariantMap()) << QGVariantType(G_VARIANT_TYPE_VARDICT); QTest::newRow("Map Filled") << QVariant(QVariantMap({{"fooBar", 0xdeadbeef}})) << QGVariantType(G_VARIANT_TYPE_VARDICT); QTest::newRow("List") << QVariant(QVariantList()) << QGVariantType(G_VARIANT_TYPE_UNIT); QTest::newRow("List Filled") << QVariant(QVariantList({"fooBar", 0xdeadbeef})) << QGVariantType(G_VARIANT_TYPE("(su)")); QVariant result; result.setValue(QByteArrayList({"42", "53"})); QTest::newRow("ByteArrayList") << result << QGVariantType(G_VARIANT_TYPE_BYTESTRING_ARRAY); } void testConvertToGVariant() { QFETCH(QVariant, value); QFETCH(QGVariantType, expectedType); QVERIFY(compare(value, expectedType)); } void testConvertToGVariantAndBack_data() { testConvertToGVariant_data(); } void testConvertToGVariantAndBack() { QFETCH(QVariant, value); GVariant *gv = Converter::toGVariant(value); QVERIFY(gv != NULL); QCOMPARE(Converter::toQVariant(gv), value); g_variant_unref(gv); } void testTupleConversion() { QVariantList qTuple; qTuple << 1 << "2" << 3.3; GVariant *gTuple = Converter::toGVariant(qTuple); QVERIFY(g_variant_type_is_tuple(g_variant_get_type(gTuple))); QCOMPARE(g_variant_n_children(gTuple), (gsize)3); GVariant *v = g_variant_get_child_value(gTuple, 0); int v0 = g_variant_get_int32(v); QCOMPARE(v0, 1); g_variant_unref(v); v = g_variant_get_child_value(gTuple, 1); const gchar *v1 = g_variant_get_string(v, NULL); QCOMPARE(QString(v1), QString("2")); g_variant_unref(v); v = g_variant_get_child_value(gTuple, 2); gdouble v2 = g_variant_get_double(v); QCOMPARE(v2, 3.3); g_variant_unref(v); g_variant_unref(gTuple); } void testConvertToGVariantWithSchema_data() { QTest::addColumn("value"); QTest::addColumn("schema"); // convert to byte QTest::newRow("byte") << QVariant::fromValue(1) << "y"; // convert to integer QTest::newRow("integer") << QVariant::fromValue(1) << "i"; QTest::newRow("integer from double") << QVariant::fromValue(1.1) << "i"; QTest::newRow("int16") << QVariant::fromValue(-1) << "n"; QTest::newRow("uint16") << QVariant::fromValue(1) << "q"; QTest::newRow("uint32") << QVariant::fromValue(1) << "u"; QTest::newRow("int64") << QVariant::fromValue(1) << "x"; QTest::newRow("uint64") << QVariant::fromValue(1) << "t"; // convert to variant QTest::newRow("variant from int") << QVariant::fromValue(1) << "v"; QTest::newRow("variant from double") << QVariant::fromValue(1.1) << "v"; QTest::newRow("variant from string") << QVariant::fromValue("string") << "v"; // convert to bool QTest::newRow("bool") << QVariant::fromValue(true) << "b"; QTest::newRow("bool from int") << QVariant::fromValue(1) << "b"; // convert to double QTest::newRow("double") << QVariant::fromValue(1.0) << "d"; QTest::newRow("double from int") << QVariant::fromValue(1) << "d"; // convert to string QTest::newRow("string") << QVariant::fromValue("FoooBar") << "s"; QTest::newRow("string from int") << QVariant::fromValue(1) << "s"; QTest::newRow("string from double") << QVariant::fromValue(1.1) << "s"; // convert to tuple QVariantList list = QVariantList() << QVariant::fromValue(true) << QVariant::fromValue(1) << QVariant::fromValue(1) << QVariant::fromValue("test1"); QTest::newRow("tuple") << QVariant(list) << "(bdis)"; // convert to array list = QVariantList() << QVariant::fromValue(1) << QVariant::fromValue(1); QTest::newRow("int list") << QVariant(list) << "ad"; list = QVariantList() << QVariant::fromValue("test1") << QVariant::fromValue("test2"); QTest::newRow("string list") << QVariant(list) << "as"; // convert to array of tuple QVariantList si1(QVariantList() << QVariant::fromValue("test1") << QVariant::fromValue(1)); QVariantList si2(QVariantList() << QVariant::fromValue("test1") << QVariant::fromValue(1)); list = QVariantList() << QVariant::fromValue(si1) << QVariant::fromValue(si2); QTest::newRow("array of tuple") << QVariant(list) << "a(sd)"; // convert to vardict QVariantMap map; map["test1"] = QVariant::fromValue(1); map["test2"] = QVariant::fromValue(1); QTest::newRow("map") << QVariant(map) << "a{sv}"; } void testConvertToGVariantWithSchema() { QFETCH(QVariant, value); QFETCH(QString, schema); QVERIFY(compareWithSchema(value, schema)); } /* * Test converter GVariant to QVariant */ void testConvertToQVariant_data() { QTest::addColumn("value"); QTest::addColumn("expectedType"); QTest::newRow("Boolean") << QGVariant(g_variant_new_boolean(TRUE)) << (unsigned) QVariant::Bool; QTest::newRow("Byte") << QGVariant(g_variant_new_byte(53)) << (unsigned) QMetaType::UChar; QTest::newRow("Int16") << QGVariant(g_variant_new_int16(-53)) << (unsigned) QMetaType::Short; QTest::newRow("UInt16") << QGVariant(g_variant_new_uint16(53)) << (unsigned) QMetaType::UShort; QTest::newRow("Int32") << QGVariant(g_variant_new_int32(-53)) << (unsigned) QVariant::Int; QTest::newRow("UInt32") << QGVariant(g_variant_new_uint32(53)) << (unsigned) QVariant::UInt; QTest::newRow("Int64") << QGVariant(g_variant_new_int64(-53)) << (unsigned) QVariant::LongLong; QTest::newRow("UInt64") << QGVariant(g_variant_new_uint64(53)) << (unsigned) QVariant::ULongLong; QTest::newRow("Double") << QGVariant(g_variant_new_double(53.3)) << (unsigned) QVariant::Double; QTest::newRow("String") << QGVariant(g_variant_new_string("53")) << (unsigned) QVariant::String; QTest::newRow("Byte string") << QGVariant(g_variant_new_bytestring("53")) << (unsigned) QVariant::ByteArray; QTest::newRow("Tuple") << QGVariant(g_variant_new("(si)", "foo", 53)) << (unsigned) QVariant::List; GVariantBuilder* builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT); g_variant_builder_add(builder, "{sv}", "fooo", g_variant_new_int64(53)); QTest::newRow("Map") << QGVariant(g_variant_builder_end(builder)) << (unsigned) QVariant::Map; g_variant_builder_unref(builder); builder = g_variant_builder_new(G_VARIANT_TYPE("ai")); g_variant_builder_add(builder, "i", g_variant_new_int32(53)); QTest::newRow("List") << QGVariant(g_variant_new("ai", builder)) << (unsigned) QVariant::List; g_variant_builder_unref(builder); QTest::newRow("Tuple") << QGVariant(g_variant_new("(i)", 53)) << (unsigned) QVariant::List; const gchar *byteArray[] = {"42", "53", NULL}; QTest::newRow("ByteArrayList") << QGVariant(g_variant_new_bytestring_array(byteArray, -1)) << (unsigned) QMetaType::QByteArrayList; QTest::newRow("String List") << QGVariant(g_variant_new_strv(byteArray, -1)) << (unsigned) QVariant::StringList; } void testConvertToQVariant() { QFETCH(QGVariant, value); QFETCH(unsigned, expectedType); QVERIFY(compare(value, (QVariant::Type) expectedType)); } void testConvertToQVariantAndBack_data() { testConvertToQVariant_data(); } void testConvertToQVariantAndBack() { QFETCH(QGVariant, value); QVariant qv = Converter::toQVariant(value); QVERIFY(qv.isValid()); GVariant *gv = Converter::toGVariant(qv); gboolean equals = g_variant_equal(value, gv); if (!equals && qv.type() == QVariant::List) { QVERIFY(g_variant_type_is_array(g_variant_get_type(value))); QVERIFY(g_variant_type_is_tuple(g_variant_get_type(gv))); gsize vsize = g_variant_n_children(value); QCOMPARE(vsize, g_variant_n_children(gv)); for (gsize i = 0; i < vsize; ++i) { equals = g_variant_equal(g_variant_get_child_value(value, i), g_variant_get_child_value(gv, i)); if (!equals) break; } } if (!equals) { gchar *vs = g_variant_print(value, TRUE); gchar *gvs = g_variant_print(gv, TRUE); qWarning() << "Values do not match. Old" << vs << "converted" << gvs; g_free(vs); g_free(gvs); } g_variant_unref(gv); QVERIFY(equals != FALSE); } void testConvertToQVariantFromString_data() { QTest::addColumn("value"); QTest::addColumn("expectedType"); QTest::newRow("Boolean") << "true" << (unsigned) QVariant::Bool; QTest::newRow("Byte") << "byte 0xFF" << (unsigned) QMetaType::UChar; QTest::newRow("Int16") << "int16 65" << (unsigned) QMetaType::Short; QTest::newRow("UInt16") << "uint16 65" << (unsigned) QMetaType::UShort; QTest::newRow("Int32") << "int32 65" << (unsigned) QVariant::Int; QTest::newRow("UInt32") << "uint32 65" << (unsigned) QVariant::UInt; QTest::newRow("Int64") << "int64 65" << (unsigned) QVariant::LongLong; QTest::newRow("UInt64") << "uint64 65" << (unsigned) QVariant::ULongLong; QTest::newRow("Double") << "double 65" << (unsigned) QVariant::Double; QTest::newRow("String") << "string '65'" << (unsigned) QVariant::String; QTest::newRow("String simple") << "\"65\"" << (unsigned) QVariant::String; QTest::newRow("String List") << "['foo', 'bar']" << (unsigned) QVariant::StringList; QTest::newRow("Byte string") << "b'fooo'" << (unsigned) QVariant::ByteArray; QTest::newRow("Map") << "{'foo': <65>}" << (unsigned) QVariant::Map; QTest::newRow("List") << "[65, 66]" << (unsigned) QVariant::List; QTest::newRow("Tuple") << "('foo', 65)" << (unsigned) QVariant::List; QTest::newRow("ByteArrayList") << "[b'foo', b'bar']" << (unsigned) QMetaType::QByteArrayList; } void testConvertToQVariantFromString() { QFETCH(QString, value); QFETCH(unsigned, expectedType); QCOMPARE(Converter::toQVariantFromVariantString(value).type(), (QVariant::Type) expectedType); } }; QTEST_MAIN(ConverterTest) #include "convertertest.moc"