/**************************************************************************** ** ** Copyright (C) 2012 Intel Corporation. ** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include class tst_qdbusxml2cpp : public QObject { Q_OBJECT enum { Interface, Adaptor }; private slots: void initTestCase_data(); void process_data(); void process(); }; struct BasicTypeList { char dbusType[3]; char cppType[24]; }; static const BasicTypeList basicTypeList[] = { { DBUS_TYPE_BOOLEAN_AS_STRING, "bool" }, { DBUS_TYPE_BYTE_AS_STRING, "uchar" }, { DBUS_TYPE_INT16_AS_STRING, "short" }, { DBUS_TYPE_UINT16_AS_STRING, "ushort" }, { DBUS_TYPE_INT32_AS_STRING, "int" }, { DBUS_TYPE_UINT32_AS_STRING, "uint" }, { DBUS_TYPE_INT64_AS_STRING, "qlonglong" }, { DBUS_TYPE_UINT64_AS_STRING, "qulonglong" }, { DBUS_TYPE_DOUBLE_AS_STRING, "double" }, { DBUS_TYPE_STRING_AS_STRING, "QString" }, { DBUS_TYPE_OBJECT_PATH_AS_STRING, "QDBusObjectPath" }, { DBUS_TYPE_SIGNATURE_AS_STRING, "QDBusSignature" }, #ifdef DBUS_TYPE_UNIX_FD_AS_STRING { DBUS_TYPE_UNIX_FD_AS_STRING, "QDBusUnixFileDescriptor" }, #endif { DBUS_TYPE_VARIANT_AS_STRING, "QDBusVariant" }, { DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, "QByteArray" }, { DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, "QStringList" }, { DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_VARIANT_AS_STRING, "QVariantList" } }; static const int basicTypeCount = sizeof(basicTypeList) / sizeof(basicTypeList[0]); static QString stripHeader(QString output) { static QRegularExpression header("^.*?(?=\\Rclass)", QRegularExpression::DotMatchesEverythingOption); return output.remove(header); } void tst_qdbusxml2cpp::initTestCase_data() { QTest::addColumn("outputMode"); QTest::addColumn("commandLineArg"); QTest::newRow("interface") << int(Interface) << "-p"; QTest::newRow("adaptor") << int(Adaptor) << "-a"; } void tst_qdbusxml2cpp::process_data() { QTest::addColumn("xmlSnippet"); QTest::addColumn("interfaceSearch"); QTest::addColumn("adaptorSearch"); // -- class info -- QTest::newRow("classinfo") << "" << QRegularExpression("staticInterfaceName\\(\\)\\s+" "{ return \"local\\.name\\.is\\.not\\.important\"\\; }") << QRegularExpression("Q_CLASSINFO\\(\"D-Bus Interface\", \"local\\.name\\.is\\.not\\.important\"\\)"); // -- properties -- for (int i = 0; i < basicTypeCount; ++i) { QRegularExpression rx(QString("\\bQ_PROPERTY\\(%1 PropertyIsPresent " "READ propertyIsPresent WRITE setPropertyIsPresent\\b") .arg(basicTypeList[i].cppType)); QTest::newRow(QByteArray("property-") + basicTypeList[i].dbusType) << QString("") .arg(basicTypeList[i].dbusType) << rx << rx; } QTest::newRow("property-readonly-multi") << "" << QRegularExpression("\\bQ_PROPERTY\\(int Value READ value(?! WRITE)") << QRegularExpression("\\bQ_PROPERTY\\(int Value READ value(?! WRITE)"); QTest::newRow("property-readonly") << "" << QRegularExpression("\\bQ_PROPERTY\\(int Value READ value(?! WRITE)") << QRegularExpression("\\bQ_PROPERTY\\(int Value READ value(?! WRITE)"); QTest::newRow("property-writeonly") << "" << QRegularExpression("\\bQ_PROPERTY\\(int Value WRITE setValue\\b") << QRegularExpression("\\bQ_PROPERTY\\(int Value WRITE setValue\\b"); QTest::newRow("property-getter-setter") << "" "" "" "" << QRegularExpression("\\bQ_PROPERTY\\(bool Enabled READ wasEnabled WRITE setEnabledFlag\\b.*" "\\bbool wasEnabled\\(\\) const.*" // no semi-colon "\\bvoid setEnabledFlag\\(bool", QRegularExpression::DotMatchesEverythingOption) << QRegularExpression("\\bQ_PROPERTY\\(bool Enabled READ wasEnabled WRITE setEnabledFlag\\b.*" "\\bbool wasEnabled\\(\\) const;.*" // has semi-colon "\\bvoid setEnabledFlag\\(bool", QRegularExpression::DotMatchesEverythingOption); QTest::newRow("property-complex") << "" "" "" << QRegularExpression("\\bQ_PROPERTY\\(Point Position READ position WRITE setPosition\\b") << QRegularExpression("\\bQ_PROPERTY\\(Point Position READ position WRITE setPosition\\b"); // -- methods -- for (int i = 0; i < basicTypeCount; ++i) { QTest::newRow(QByteArray("method-") + basicTypeList[i].dbusType) << QString("" "" "" "") .arg(basicTypeList[i].dbusType) << QRegularExpression(QString("Q_SLOTS:.*\\bQDBusPendingReply<%1> Method\\((const )?%1 ") .arg(basicTypeList[i].cppType), QRegularExpression::DotMatchesEverythingOption) << QRegularExpression(QString("Q_SLOTS:.*\\b%1 Method\\((const )?%1 ") .arg(basicTypeList[i].cppType), QRegularExpression::DotMatchesEverythingOption); } QTest::newRow("method-complex") << "" "" "" "" "" "" << QRegularExpression("Q_SLOTS:.*\\bQDBusPendingReply Method\\(PointF ", QRegularExpression::DotMatchesEverythingOption) << QRegularExpression("Q_SLOTS:.*\\bPoint Method\\(PointF ", QRegularExpression::DotMatchesEverythingOption); QTest::newRow("method-ss") << "" "" "" "" "" "" << QRegularExpression("Q_SLOTS:.*QDBusPendingReply Method\\(const QString &\\w*, const QString &", QRegularExpression::DotMatchesEverythingOption) << QRegularExpression("Q_SLOTS:.*QString Method\\(const QString &\\w*, const QString &\\w*, QString &", QRegularExpression::DotMatchesEverythingOption); // -- signals -- for (int i = 0; i < basicTypeCount; ++i) { QRegularExpression rx(QString("Q_SIGNALS:.*\\bvoid Signal\\((const )?%1\\b") .arg(basicTypeList[i].cppType), QRegularExpression::DotMatchesEverythingOption); QTest::newRow(QByteArray("signal-") + basicTypeList[i].dbusType) << QString("" "" "") .arg(basicTypeList[i].dbusType) << rx << rx; } } void tst_qdbusxml2cpp::process() { QFETCH(QString, xmlSnippet); QFETCH(QRegularExpression, interfaceSearch); QFETCH(QRegularExpression, adaptorSearch); QVERIFY2(interfaceSearch.isValid(), qPrintable(interfaceSearch.errorString())); QVERIFY2(adaptorSearch.isValid(), qPrintable(adaptorSearch.errorString())); // test both interface and adaptor generation QFETCH_GLOBAL(int, outputMode); QFETCH_GLOBAL(QString, commandLineArg); // Run the tool QProcess process; process.start("qdbusxml2cpp", QStringList() << commandLineArg << "-" << "-N"); QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); // feed it our XML data static const char xmlHeader[] = "\n" DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE // \n is included "\n" " \n" " \n"; static const char xmlFooter[] = "\n" " \n" " \n" "\n"; process.write(xmlHeader, int(sizeof xmlHeader) - 1); process.write(xmlSnippet.toLatin1()); process.write(xmlFooter, int(sizeof xmlFooter) - 1); while (process.bytesToWrite()) QVERIFY2(process.waitForBytesWritten(), qPrintable(process.errorString())); // fprintf(stderr, "%s%s%s", xmlHeader, xmlSnippet.toLatin1().constData(), xmlFooter); process.closeWriteChannel(); QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QByteArray errOutput = process.readAllStandardError(); QVERIFY2(errOutput.isEmpty(), errOutput); QCOMPARE(process.exitCode(), 0); QByteArray fullOutput = process.readAll(); QString output = stripHeader(QString::fromLatin1(fullOutput)); QVERIFY2(!output.isEmpty(), fullOutput); if (outputMode == Interface) QVERIFY2(output.count(interfaceSearch) == 1, qPrintable(interfaceSearch.pattern() + "\nin\n" + output)); else QVERIFY2(output.count(adaptorSearch) == 1, qPrintable(adaptorSearch.pattern() + "\nin\n" + output)); } QTEST_MAIN(tst_qdbusxml2cpp) #include "tst_qdbusxml2cpp.moc"