diff options
Diffstat (limited to 'tests/auto')
52 files changed, 4461 insertions, 858 deletions
diff --git a/tests/auto/dbus.pro b/tests/auto/dbus.pro index e5f87e3..31b46a3 100644 --- a/tests/auto/dbus.pro +++ b/tests/auto/dbus.pro @@ -11,9 +11,9 @@ SUBDIRS=\ qdbusmetatype \ qdbuspendingcall \ qdbuspendingreply \ - qdbusperformance \ qdbusreply \ qdbusservicewatcher \ + qdbustype \ qdbusthreading \ qdbusxmlparser \ diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml index 8addcb9..6467c42 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalAssignment.2.qml @@ -1,5 +1,5 @@ import Qt.test 1.0 MyQmlObject { - onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c) + onArgumentSignal: setString('pass ' + a + ' ' + b + ' ' + c + ' ' + d + ' ' + e) } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml b/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml index ffbe317..4fc2dab 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/signalParameterTypes.qml @@ -7,10 +7,12 @@ MyQmlObject property real realProperty property color colorProperty property variant variantProperty + property int enumProperty + property int qtEnumProperty - signal mySignal(int a, real b, color c, variant d) + signal mySignal(int a, real b, color c, variant d, int e, int f) - onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; } + onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; enumProperty = e; qtEnumProperty = f; } - onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1)) + onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1), MyQmlObject.EnumValue3, Qt.LeftButton) } diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 7e63bd5..1d65b15 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -127,6 +127,8 @@ void registerTypes() qmlRegisterType<QPlainTextEdit>("Qt.test",1,0,"QPlainTextEdit"); qRegisterMetaType<MyQmlObject::MyType>("MyQmlObject::MyType"); + qRegisterMetaType<MyQmlObject::MyType>("MyEnum2"); + qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons"); } #include "testtypes.moc" diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 081cc4c..94cec3f 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -159,7 +159,7 @@ public: signals: void basicSignal(); - void argumentSignal(int a, QString b, qreal c); + void argumentSignal(int a, QString b, qreal c, MyEnum2 d, Qt::MouseButtons e); void stringChanged(); void objectChanged(); void anotherBasicSignal(); diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 48466d5..7876671 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -304,8 +304,8 @@ void tst_qdeclarativeecmascript::signalAssignment() MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create()); QVERIFY(object != 0); QCOMPARE(object->string(), QString()); - emit object->argumentSignal(19, "Hello world!", 10.25); - QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25")); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); + QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2")); } } @@ -870,7 +870,7 @@ void tst_qdeclarativeecmascript::scope() QCOMPARE(object->property("test").toInt(), 0); QCOMPARE(object->property("test2").toString(), QString()); - emit object->argumentSignal(13, "Argument Scope", 9); + emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 13); QCOMPARE(object->property("test2").toString(), QString("Argument Scope")); @@ -895,6 +895,8 @@ void tst_qdeclarativeecmascript::signalParameterTypes() QCOMPARE(object->property("realProperty").toReal(), 19.2); QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255)); QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255))); + QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3); + QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton); } /* @@ -1139,7 +1141,7 @@ void tst_qdeclarativeecmascript::signalTriggeredBindings() QCOMPARE(object->property("test1").toReal(), 200.); QCOMPARE(object->property("test2").toReal(), 200.); - object->argumentSignal(10, QString(), 10); + object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("base").toReal(), 400.); QCOMPARE(object->property("test1").toReal(), 400.); @@ -1940,7 +1942,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toBool(), false); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toBool(), true); delete object; @@ -1953,7 +1955,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toBool(), false); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toBool(), true); delete object; @@ -1966,7 +1968,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toBool(), false); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toBool(), true); delete object; @@ -1979,7 +1981,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->methodCalled(), false); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->methodCalled(), true); delete object; @@ -1992,7 +1994,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->methodCalled(), false); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->methodCalled(), true); delete object; @@ -2005,7 +2007,7 @@ void tst_qdeclarativeecmascript::scriptConnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 0); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); delete object; @@ -2021,13 +2023,13 @@ void tst_qdeclarativeecmascript::scriptDisconnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 0); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 1); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); emit object->basicSignal(); QCOMPARE(object->property("test").toInt(), 2); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); delete object; @@ -2040,13 +2042,13 @@ void tst_qdeclarativeecmascript::scriptDisconnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 0); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 1); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); emit object->basicSignal(); QCOMPARE(object->property("test").toInt(), 2); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); delete object; @@ -2059,13 +2061,13 @@ void tst_qdeclarativeecmascript::scriptDisconnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 0); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 1); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); emit object->basicSignal(); QCOMPARE(object->property("test").toInt(), 2); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 3); delete object; @@ -2077,13 +2079,13 @@ void tst_qdeclarativeecmascript::scriptDisconnect() QVERIFY(object != 0); QCOMPARE(object->property("test").toInt(), 0); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 1); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 2); emit object->basicSignal(); QCOMPARE(object->property("test").toInt(), 2); - emit object->argumentSignal(19, "Hello world!", 10.25); + emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton); QCOMPARE(object->property("test").toInt(), 3); delete object; diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 45072f3..2f7513f 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -106,6 +106,7 @@ private slots: void property_changes_data(); void property_changes_worker(); void property_changes_worker_data(); + void clear(); }; int tst_qdeclarativelistmodel::roleFromName(const QDeclarativeListModel *model, const QString &roleName) { @@ -1091,6 +1092,47 @@ void tst_qdeclarativelistmodel::property_changes_worker_data() property_changes_data(); } +void tst_qdeclarativelistmodel::clear() +{ + QDeclarativeEngine engine; + QDeclarativeListModel model; + QDeclarativeEngine::setContextForObject(&model, engine.rootContext()); + engine.rootContext()->setContextObject(&model); + + QScriptEngine *seng = QDeclarativeEnginePrivate::getScriptEngine(&engine); + QScriptValue sv = seng->newObject(); + QVariant result; + + model.clear(); + QCOMPARE(model.count(), 0); + + sv.setProperty("propertyA", "value a"); + sv.setProperty("propertyB", "value b"); + model.append(sv); + QCOMPARE(model.count(), 1); + + model.clear(); + QCOMPARE(model.count(), 0); + + model.append(sv); + model.append(sv); + QCOMPARE(model.count(), 2); + + model.clear(); + QCOMPARE(model.count(), 0); + + // clearing does not remove the roles + sv.setProperty("propertyC", "value c"); + model.append(sv); + QList<int> roles = model.roles(); + model.clear(); + QCOMPARE(model.count(), 0); + QCOMPARE(model.roles(), roles); + QCOMPARE(model.toString(roles[0]), QString("propertyA")); + QCOMPARE(model.toString(roles[1]), QString("propertyB")); + QCOMPARE(model.toString(roles[2]), QString("propertyC")); +} + QTEST_MAIN(tst_qdeclarativelistmodel) #include "tst_qdeclarativelistmodel.moc" diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 8dc7b5f..0d77fff 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -136,6 +136,7 @@ SUBDIRS=\ qpushbutton \ qquaternion \ qradiobutton \ + qrawfont \ qregexpvalidator \ qregion \ qscrollarea \ diff --git a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp index a809101..34be20c 100644 --- a/tests/auto/qbuttongroup/tst_qbuttongroup.cpp +++ b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp @@ -98,10 +98,7 @@ private slots: void task106609(); - // fixed for Qt 4.6.0 -#if QT_VERSION >= 0x040600 void autoIncrementId(); -#endif void task209485_removeFromGroupInEventHandler_data(); void task209485_removeFromGroupInEventHandler(); @@ -338,10 +335,7 @@ void tst_QButtonGroup::testSignals() QCOMPARE(clickedSpy.count(), 1); QCOMPARE(clickedIdSpy.count(), 1); - int expectedId = -1; -#if QT_VERSION >= 0x040600 - expectedId = -2; -#endif + int expectedId = -2; QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == expectedId); QCOMPARE(pressedSpy.count(), 1); @@ -500,7 +494,6 @@ void tst_QButtonGroup::task209485_removeFromGroupInEventHandler() QCOMPARE(spy1.count() + spy2.count(), signalCount); } -#if QT_VERSION >= 0x040600 void tst_QButtonGroup::autoIncrementId() { QDialog dlg(0); @@ -529,7 +522,6 @@ void tst_QButtonGroup::autoIncrementId() dlg.show(); } -#endif QTEST_MAIN(tst_QButtonGroup) #include "tst_qbuttongroup.moc" diff --git a/tests/auto/qdbusabstractadaptor/myobject.h b/tests/auto/qdbusabstractadaptor/myobject.h new file mode 100644 index 0000000..7353fa6 --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/myobject.h @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MYOBJECT_H +#define MYOBJECT_H + +#include <QtCore/QObject> +#include <QtDBus/QtDBus> + +extern const char *slotSpy; +extern QString valueSpy; + +class QDBusSignalSpy: public QObject +{ + Q_OBJECT + +public slots: + void slot(const QDBusMessage &msg) + { + ++count; + interface = msg.interface(); + name = msg.member(); + signature = msg.signature(); + path = msg.path(); + value.clear(); + if (msg.arguments().count()) + value = msg.arguments().at(0); + } + +public: + QDBusSignalSpy() : count(0) { } + + int count; + QString interface; + QString name; + QString signature; + QString path; + QVariant value; +}; + +class Interface1: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface1") +public: + Interface1(QObject *parent) : QDBusAbstractAdaptor(parent) + { } +}; + +class Interface2: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface2") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2 SCRIPTABLE true) + Q_PROPERTY(QUrl nonDBusProperty READ nonDBusProperty) +public: + Interface2(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface2::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface2::prop2() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface2::setProp2(const QString &)"; + valueSpy = value; + } + + QUrl nonDBusProperty() const + { return QUrl(); } + + void emitSignal(const QString &, const QVariant &) + { emit signal(); } + +public slots: + void method() + { + slotSpy = "void Interface2::method()"; + } + + Q_SCRIPTABLE void scriptableMethod() + { + slotSpy = "void Interface2::scriptableMethod()"; + } + +signals: + void signal(); +}; + +class Interface3: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface3") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) + Q_PROPERTY(QString interface3prop READ interface3prop) +public: + Interface3(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface3::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface3::prop2() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface3::setProp2(const QString &)"; + valueSpy = value; + } + + QString interface3prop() const + { return QLatin1String("QString Interface3::interface3prop() const"); } + + void emitSignal(const QString &name, const QVariant &value) + { + if (name == "signalVoid") + emit signalVoid(); + else if (name == "signalInt") + emit signalInt(value.toInt()); + else if (name == "signalString") + emit signalString(value.toString()); + } + +public slots: + void methodVoid() { slotSpy = "void Interface3::methodVoid()"; } + void methodInt(int) { slotSpy = "void Interface3::methodInt(int)"; } + void methodString(QString) { slotSpy = "void Interface3::methodString(QString)"; } + + int methodStringString(const QString &s, QString &out) + { + slotSpy = "int Interface3::methodStringString(const QString &, QString &)"; + out = s; + return 42; + } + +signals: + void signalVoid(); + void signalInt(int); + void signalString(const QString &); +}; + +class Interface4: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface4") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) + Q_PROPERTY(QString interface4prop READ interface4prop) +public: + Interface4(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface4::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface4::prop2() const"); } + + QString interface4prop() const + { return QLatin1String("QString Interface4::interface4prop() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface4::setProp2(const QString &)"; + valueSpy = value; + } + + void emitSignal(const QString &, const QVariant &value) + { + switch (value.type()) + { + case QVariant::Invalid: + emit signal(); + break; + case QVariant::Int: + emit signal(value.toInt()); + break; + case QVariant::String: + emit signal(value.toString()); + break; + default: + break; + } + } + +public slots: + void method() { slotSpy = "void Interface4::method()"; } + void method(int) { slotSpy = "void Interface4::method(int)"; } + void method(QString) { slotSpy = "void Interface4::method(QString)"; } + +signals: + void signal(); + void signal(int); + void signal(const QString &); +}; + +class MyObject: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.MyObject") +public: + Interface1 *if1; + Interface2 *if2; + Interface3 *if3; + Interface4 *if4; + + MyObject(int n = 4) + : if1(0), if2(0), if3(0), if4(0) + { + switch (n) + { + case 4: + if4 = new Interface4(this); + case 3: + if3 = new Interface3(this); + case 2: + if2 = new Interface2(this); + case 1: + if1 = new Interface1(this); + } + } + + void emitSignal(const QString &name, const QVariant &value) + { + if (name == "scriptableSignalVoid") + emit scriptableSignalVoid(); + else if (name == "scriptableSignalInt") + emit scriptableSignalInt(value.toInt()); + else if (name == "scriptableSignalString") + emit scriptableSignalString(value.toString()); + else if (name == "nonScriptableSignalVoid") + emit nonScriptableSignalVoid(); + } + +signals: + Q_SCRIPTABLE void scriptableSignalVoid(); + Q_SCRIPTABLE void scriptableSignalInt(int); + Q_SCRIPTABLE void scriptableSignalString(QString); + void nonScriptableSignalVoid(); +}; + +#endif // MYOBJECT_H
\ No newline at end of file diff --git a/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro index 16358c5..c3e3f7f 100644 --- a/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro +++ b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro @@ -1,10 +1,9 @@ load(qttest_p4) QT = core contains(QT_CONFIG,dbus): { - SOURCES += tst_qdbusabstractadaptor.cpp - QT += dbus + TEMPLATE = subdirs + CONFIG += ordered + SUBDIRS = qmyserver test } else { - SOURCES += ../qdbusmarshall/dummy.cpp + SOURCES += ../qdbusmarshall/dummy.cpp } - - diff --git a/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp new file mode 100644 index 0000000..238bc38 --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/QtCore> +#include <QtDBus/QtDBus> + +#include "../myobject.h" + +static const char serviceName[] = "com.trolltech.autotests.qmyserver"; +static const char objectPath[] = "/com/trolltech/qmyserver"; +//static const char *interfaceName = serviceName; + +const char *slotSpy; +QString valueSpy; + +Q_DECLARE_METATYPE(QDBusConnection::RegisterOptions) + +class MyServer : public QDBusServer +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qmyserver") + +public: + MyServer(QString addr = "unix:tmpdir=/tmp", QObject* parent = 0) + : QDBusServer(addr, parent), + m_conn("none"), + obj(NULL) + { + connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&))); + } + + ~MyServer() + { + if (obj) + obj->deleteLater(); + } + +public slots: + QString address() const + { + return QDBusServer::address(); + } + + bool isConnected() const + { + return m_conn.isConnected(); + } + + void emitSignal(const QString& interface, const QString& name, const QDBusVariant& parameter) + { + if (interface.endsWith('2')) + obj->if2->emitSignal(name, parameter.variant()); + else if (interface.endsWith('3')) + obj->if3->emitSignal(name, parameter.variant()); + else if (interface.endsWith('4')) + obj->if4->emitSignal(name, parameter.variant()); + else + obj->emitSignal(name, parameter.variant()); + } + + void emitSignal2(const QString& interface, const QString& name) + { + if (interface.endsWith('2')) + obj->if2->emitSignal(name, QVariant()); + else if (interface.endsWith('3')) + obj->if3->emitSignal(name, QVariant()); + else if (interface.endsWith('4')) + obj->if4->emitSignal(name, QVariant()); + else + obj->emitSignal(name, QVariant()); + } + + void newMyObject(int nInterfaces = 4) + { + if (obj) + obj->deleteLater(); + obj = new MyObject(nInterfaces); + } + + void registerMyObject(const QString & path, int options) + { + m_conn.registerObject(path, obj, (QDBusConnection::RegisterOptions)options); + } + + QString slotSpyServer() + { + return QLatin1String(slotSpy); + } + + QString valueSpyServer() + { + return valueSpy; + } + + void clearValueSpy() + { + valueSpy.clear(); + } + +private slots: + void handleConnection(const QDBusConnection& con) + { + m_conn = con; + } + +private: + QDBusConnection m_conn; + MyObject* obj; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QDBusConnection con = QDBusConnection::sessionBus(); + if (!con.isConnected()) + exit(1); + + if (!con.registerService(serviceName)) + exit(2); + + MyServer server; + con.registerObject(objectPath, &server, QDBusConnection::ExportAllSlots); + + printf("ready.\n"); + + return app.exec(); +} + +#include "qmyserver.moc"
\ No newline at end of file diff --git a/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro new file mode 100644 index 0000000..f4fe02c --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro @@ -0,0 +1,5 @@ +SOURCES = qmyserver.cpp +HEADERS = ../myobject.h +TARGET = qmyserver +QT += dbus +QT -= gui diff --git a/tests/auto/qdbusabstractadaptor/test/test.pro b/tests/auto/qdbusabstractadaptor/test/test.pro new file mode 100644 index 0000000..014a9e8 --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/test/test.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +SOURCES += ../tst_qdbusabstractadaptor.cpp +HEADERS += ../myobject.h +TARGET = ../tst_qdbusabstractadaptor + +QT = core +QT += dbus diff --git a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp index a64b3d2..9250350 100644 --- a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp +++ b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -46,6 +46,11 @@ #include <QtDBus> #include "../qdbusmarshall/common.h" +#include "myobject.h" + +static const char serviceName[] = "com.trolltech.autotests.qmyserver"; +static const char objectPath[] = "/com/trolltech/qmyserver"; +static const char *interfaceName = serviceName; const char *slotSpy; QString valueSpy; @@ -73,273 +78,6 @@ namespace QTest { } QT_END_NAMESPACE -class tst_QDBusAbstractAdaptor: public QObject -{ - Q_OBJECT - -private slots: - void initTestCase() { commonInit(); } - void methodCalls_data(); - void methodCalls(); - void methodCallScriptable(); - void signalEmissions_data(); - void signalEmissions(); - void sameSignalDifferentPaths(); - void sameObjectDifferentPaths(); - void scriptableSignalOrNot(); - void overloadedSignalEmission_data(); - void overloadedSignalEmission(); - void readProperties(); - void readPropertiesInvalidInterface(); - void readPropertiesEmptyInterface_data(); - void readPropertiesEmptyInterface(); - void readAllProperties(); - void readAllPropertiesInvalidInterface(); - void readAllPropertiesEmptyInterface_data(); - void readAllPropertiesEmptyInterface(); - void writeProperties(); - - void typeMatching_data(); - void typeMatching(); - - void methodWithMoreThanOneReturnValue(); -}; - -class QDBusSignalSpy: public QObject -{ - Q_OBJECT - -public slots: - void slot(const QDBusMessage &msg) - { - ++count; - interface = msg.interface(); - name = msg.member(); - signature = msg.signature(); - path = msg.path(); - value.clear(); - if (msg.arguments().count()) - value = msg.arguments().at(0); - } - -public: - QDBusSignalSpy() : count(0) { } - - int count; - QString interface; - QString name; - QString signature; - QString path; - QVariant value; -}; - -class Interface1: public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.Interface1") -public: - Interface1(QObject *parent) : QDBusAbstractAdaptor(parent) - { } -}; - -class Interface2: public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.Interface2") - Q_PROPERTY(QString prop1 READ prop1) - Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2 SCRIPTABLE true) - Q_PROPERTY(QUrl nonDBusProperty READ nonDBusProperty) -public: - Interface2(QObject *parent) : QDBusAbstractAdaptor(parent) - { setAutoRelaySignals(true); } - - QString prop1() const - { return QLatin1String("QString Interface2::prop1() const"); } - - QString prop2() const - { return QLatin1String("QString Interface2::prop2() const"); } - - void setProp2(const QString &value) - { - slotSpy = "void Interface2::setProp2(const QString &)"; - valueSpy = value; - } - - QUrl nonDBusProperty() const - { return QUrl(); } - - void emitSignal(const QString &, const QVariant &) - { emit signal(); } - -public slots: - void method() - { - slotSpy = "void Interface2::method()"; - } - - Q_SCRIPTABLE void scriptableMethod() - { - slotSpy = "void Interface2::scriptableMethod()"; - } - -signals: - void signal(); -}; - -class Interface3: public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.Interface3") - Q_PROPERTY(QString prop1 READ prop1) - Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) - Q_PROPERTY(QString interface3prop READ interface3prop) -public: - Interface3(QObject *parent) : QDBusAbstractAdaptor(parent) - { setAutoRelaySignals(true); } - - QString prop1() const - { return QLatin1String("QString Interface3::prop1() const"); } - - QString prop2() const - { return QLatin1String("QString Interface3::prop2() const"); } - - void setProp2(const QString &value) - { - slotSpy = "void Interface3::setProp2(const QString &)"; - valueSpy = value; - } - - QString interface3prop() const - { return QLatin1String("QString Interface3::interface3prop() const"); } - - void emitSignal(const QString &name, const QVariant &value) - { - if (name == "signalVoid") - emit signalVoid(); - else if (name == "signalInt") - emit signalInt(value.toInt()); - else if (name == "signalString") - emit signalString(value.toString()); - } - -public slots: - void methodVoid() { slotSpy = "void Interface3::methodVoid()"; } - void methodInt(int) { slotSpy = "void Interface3::methodInt(int)"; } - void methodString(QString) { slotSpy = "void Interface3::methodString(QString)"; } - - int methodStringString(const QString &s, QString &out) - { - slotSpy = "int Interface3::methodStringString(const QString &, QString &)"; - out = s; - return 42; - } - -signals: - void signalVoid(); - void signalInt(int); - void signalString(const QString &); -}; - -class Interface4: public QDBusAbstractAdaptor -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.Interface4") - Q_PROPERTY(QString prop1 READ prop1) - Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) - Q_PROPERTY(QString interface4prop READ interface4prop) -public: - Interface4(QObject *parent) : QDBusAbstractAdaptor(parent) - { setAutoRelaySignals(true); } - - QString prop1() const - { return QLatin1String("QString Interface4::prop1() const"); } - - QString prop2() const - { return QLatin1String("QString Interface4::prop2() const"); } - - QString interface4prop() const - { return QLatin1String("QString Interface4::interface4prop() const"); } - - void setProp2(const QString &value) - { - slotSpy = "void Interface4::setProp2(const QString &)"; - valueSpy = value; - } - - void emitSignal(const QString &, const QVariant &value) - { - switch (value.type()) - { - case QVariant::Invalid: - emit signal(); - break; - case QVariant::Int: - emit signal(value.toInt()); - break; - case QVariant::String: - emit signal(value.toString()); - break; - default: - break; - } - } - -public slots: - void method() { slotSpy = "void Interface4::method()"; } - void method(int) { slotSpy = "void Interface4::method(int)"; } - void method(QString) { slotSpy = "void Interface4::method(QString)"; } - -signals: - void signal(); - void signal(int); - void signal(const QString &); -}; - -class MyObject: public QObject -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.MyObject") -public: - Interface1 *if1; - Interface2 *if2; - Interface3 *if3; - Interface4 *if4; - - MyObject(int n = 4) - : if1(0), if2(0), if3(0), if4(0) - { - switch (n) - { - case 4: - if4 = new Interface4(this); - case 3: - if3 = new Interface3(this); - case 2: - if2 = new Interface2(this); - case 1: - if1 = new Interface1(this); - } - } - - void emitSignal(const QString &name, const QVariant &value) - { - if (name == "scriptableSignalVoid") - emit scriptableSignalVoid(); - else if (name == "scriptableSignalInt") - emit scriptableSignalInt(value.toInt()); - else if (name == "scriptableSignalString") - emit scriptableSignalString(value.toString()); - else if (name == "nonScriptableSignalVoid") - emit nonScriptableSignalVoid(); - } - -signals: - Q_SCRIPTABLE void scriptableSignalVoid(); - Q_SCRIPTABLE void scriptableSignalInt(int); - Q_SCRIPTABLE void scriptableSignalString(QString); - void nonScriptableSignalVoid(); -}; - class TypesInterface: public QDBusAbstractAdaptor { Q_OBJECT @@ -593,6 +331,191 @@ public slots: } }; +void newMyObjectPeer(int nInterfaces = 4) +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "newMyObject"); + req << nInterfaces; + QDBusMessage reply = QDBusConnection::sessionBus().call(req); +} + +void registerMyObjectPeer(const QString & path, QDBusConnection::RegisterOptions options = QDBusConnection::ExportAdaptors) +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "registerMyObject"); + req << path; + req << (int)options; + QDBusMessage reply = QDBusConnection::sessionBus().call(req); +} + +void emitSignalPeer(const QString &interface, const QString &name, const QVariant ¶meter) +{ + if (parameter.isValid()) + { + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal"); + req << interface; + req << name; + req << QVariant::fromValue(QDBusVariant(parameter)); + QDBusConnection::sessionBus().send(req); + } + else + { + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal2"); + req << interface; + req << name; + QDBusConnection::sessionBus().send(req); + } + + QTest::qWait(1000); +} + +const char* slotSpyPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "slotSpyServer"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return reply.arguments().at(0).toString().toLatin1().data(); +} + +QString valueSpyPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "valueSpyServer"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return reply.arguments().at(0).toString(); +} + +void clearValueSpyPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "clearValueSpy"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); +} + +class tst_QDBusAbstractAdaptor: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void methodCalls_data(); + void methodCalls(); + void methodCallScriptable(); + void signalEmissions_data(); + void signalEmissions(); + void sameSignalDifferentPaths(); + void sameObjectDifferentPaths(); + void scriptableSignalOrNot(); + void overloadedSignalEmission_data(); + void overloadedSignalEmission(); + void readProperties(); + void readPropertiesInvalidInterface(); + void readPropertiesEmptyInterface_data(); + void readPropertiesEmptyInterface(); + void readAllProperties(); + void readAllPropertiesInvalidInterface(); + void readAllPropertiesEmptyInterface_data(); + void readAllPropertiesEmptyInterface(); + void writeProperties(); + + void methodCallsPeer_data(); + void methodCallsPeer(); + void methodCallScriptablePeer(); + void signalEmissionsPeer_data(); + void signalEmissionsPeer(); + void sameSignalDifferentPathsPeer(); + void sameObjectDifferentPathsPeer(); + void scriptableSignalOrNotPeer(); + void overloadedSignalEmissionPeer_data(); + void overloadedSignalEmissionPeer(); + void readPropertiesPeer(); + void readPropertiesInvalidInterfacePeer(); + void readPropertiesEmptyInterfacePeer_data(); + void readPropertiesEmptyInterfacePeer(); + void readAllPropertiesPeer(); + void readAllPropertiesInvalidInterfacePeer(); + void readAllPropertiesEmptyInterfacePeer_data(); + void readAllPropertiesEmptyInterfacePeer(); + void writePropertiesPeer(); + + void typeMatching_data(); + void typeMatching(); + + void methodWithMoreThanOneReturnValue(); + void methodWithMoreThanOneReturnValuePeer(); +private: + QProcess proc; +}; + +class WaitForQMyServer: public QObject +{ + Q_OBJECT +public: + WaitForQMyServer(); + bool ok(); +public Q_SLOTS: + void ownerChange(const QString &name) + { + if (name == serviceName) + loop.quit(); + } + +private: + QEventLoop loop; +}; + +WaitForQMyServer::WaitForQMyServer() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + if (!ok()) { + connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), + SLOT(ownerChange(QString))); + QTimer::singleShot(2000, &loop, SLOT(quit())); + loop.exec(); + } +} + +bool WaitForQMyServer::ok() +{ + return QDBusConnection::sessionBus().isConnected() && + QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName); +} + +void tst_QDBusAbstractAdaptor::initTestCase() +{ + commonInit(); + + // start peer server + #ifdef Q_OS_WIN + proc.start("qmyserver"); + #else + proc.start("./qmyserver/qmyserver"); + #endif + QVERIFY(proc.waitForStarted()); + + WaitForQMyServer w; + QVERIFY(w.ok()); + //QTest::qWait(2000); + + // get peer server address + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "address"); + QDBusMessage rpl = QDBusConnection::sessionBus().call(req); + QVERIFY(rpl.type() == QDBusMessage::ReplyMessage); + QString address = rpl.arguments().at(0).toString(); + + // connect to peer server + QDBusConnection peercon = QDBusConnection::connectToPeer(address, "peer"); + QVERIFY(peercon.isConnected()); + + QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "isConnected"); + QDBusMessage rpl2 = QDBusConnection::sessionBus().call(req2); + QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage); + QVERIFY(rpl2.arguments().at(0).toBool()); +} + +void tst_QDBusAbstractAdaptor::cleanupTestCase() +{ + proc.close(); + proc.kill(); +} + void tst_QDBusAbstractAdaptor::methodCalls_data() { QTest::addColumn<int>("nInterfaces"); @@ -1151,6 +1074,512 @@ void tst_QDBusAbstractAdaptor::writeProperties() } } +void tst_QDBusAbstractAdaptor::methodCallsPeer_data() +{ + methodCalls_data(); +} + +void tst_QDBusAbstractAdaptor::methodCallsPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + { + // must fail: no object + QDBusInterface if1(QString(), "/", "local.Interface1", con); + QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + } + + QFETCH(int, nInterfaces); + newMyObjectPeer(nInterfaces); + registerMyObjectPeer("/"); + + QDBusInterface if1(QString(), "/", "local.Interface1", con); + QDBusInterface if2(QString(), "/", "local.Interface2", con); + QDBusInterface if3(QString(), "/", "local.Interface3", con); + QDBusInterface if4(QString(), "/", "local.Interface4", con); + + // must fail: no such method + QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + if (!nInterfaces--) + return; + if (!nInterfaces--) + return; + + // simple call: one such method exists + QCOMPARE(if2.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface2::method()"); + if (!nInterfaces--) + return; + + // multiple methods in multiple interfaces, no name overlap + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage); + + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface3::methodVoid()"); + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodInt", 42).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface3::methodInt(int)"); + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodString", QString("")).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface3::methodString(QString)"); + + if (!nInterfaces--) + return; + + // method overloading: different interfaces + QCOMPARE(if4.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface4::method()"); + + // method overloading: different parameters + QCOMPARE(if4.call(QDBus::BlockWithGui, "method.i", 42).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface4::method(int)"); + QCOMPARE(if4.call(QDBus::BlockWithGui, "method.s", QString()).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface4::method(QString)"); +} + +void tst_QDBusAbstractAdaptor::methodCallScriptablePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(2); + registerMyObjectPeer("/"); + + QDBusInterface if2(QString(), "/", "local.Interface2", con); + + QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpyPeer(), "void Interface2::scriptableMethod()"); +} + +void tst_QDBusAbstractAdaptor::signalEmissionsPeer_data() +{ + signalEmissions_data(); +} + +void tst_QDBusAbstractAdaptor::signalEmissionsPeer() +{ + QFETCH(QString, interface); + QFETCH(QString, name); + QFETCH(QVariant, parameter); + + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(3); + registerMyObjectPeer("/", QDBusConnection::ExportAdaptors + | QDBusConnection::ExportScriptableSignals); + + // connect all signals and emit only one + { + QDBusSignalSpy spy; + con.connect(QString(), "/", "local.Interface2", "signal", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.Interface3", "signalVoid", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.Interface3", "signalInt", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.Interface3", "signalString", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.MyObject", "scriptableSignalVoid", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.MyObject", "scriptableSignalInt", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.MyObject", "scriptableSignalString", + &spy, SLOT(slot(QDBusMessage))); + + emitSignalPeer(interface, name, parameter); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } + + // connect one signal and emit them all + { + QDBusSignalSpy spy; + con.connect(QString(), "/", interface, name, &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.Interface2", "signal", QVariant()); + emitSignalPeer("local.Interface3", "signalVoid", QVariant()); + emitSignalPeer("local.Interface3", "signalInt", QVariant(1)); + emitSignalPeer("local.Interface3", "signalString", QVariant("foo")); + emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant()); + emitSignalPeer("local.MyObject", "scriptableSignalInt", QVariant(1)); + emitSignalPeer("local.MyObject", "scriptableSignalString", QVariant("foo")); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } +} + +void tst_QDBusAbstractAdaptor::sameSignalDifferentPathsPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(2); + + registerMyObjectPeer("/p1"); + registerMyObjectPeer("/p2"); + + QDBusSignalSpy spy; + con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.Interface2", QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, QString("local.Interface2")); + QCOMPARE(spy.name, QString("signal")); + QVERIFY(spy.signature.isEmpty()); + + // now connect the other one + spy.count = 0; + con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.Interface2", QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 2); +} + +void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(2); + + registerMyObjectPeer("/p1"); + registerMyObjectPeer("/p2", 0); // don't export anything + + QDBusSignalSpy spy; + con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.Interface2", QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, QString("local.Interface2")); + QCOMPARE(spy.name, QString("signal")); + QVERIFY(spy.signature.isEmpty()); +} + +void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() +{ + QDBusConnection con("peer");; + QVERIFY(con.isConnected()); + + { + newMyObjectPeer(0); + + registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals); + registerMyObjectPeer("/p2", 0); // don't export anything + + QDBusSignalSpy spy; + con.connect(QString(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant()); + emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); // only /p1 must have emitted + QCOMPARE(spy.interface, QString("local.MyObject")); + QCOMPARE(spy.name, QString("scriptableSignalVoid")); + QCOMPARE(spy.path, QString("/p1")); + QVERIFY(spy.signature.isEmpty()); + } + + { + newMyObjectPeer(0); + + registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals); + registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals + | QDBusConnection::ExportNonScriptableSignals); + + QDBusSignalSpy spy; + con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); // only /p2 must have emitted now + QCOMPARE(spy.interface, QString("local.MyObject")); + QCOMPARE(spy.name, QString("nonScriptableSignalVoid")); + QCOMPARE(spy.path, QString("/p2")); + QVERIFY(spy.signature.isEmpty()); + } + + { + QDBusSignalSpy spy; + con.connect(QString(), "/p1", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/p2", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage))); + + { + newMyObjectPeer(0); + + registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals); + registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals + | QDBusConnection::ExportNonScriptableSignals); + } // <--- QObject emits the destroyed(QObject*) signal at this point + + QTest::qWait(200); + + QCOMPARE(spy.count, 0); + } +} + +void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer_data() +{ + overloadedSignalEmission_data(); +} + +void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QString interface = "local.Interface4"; + QString name = "signal"; + QFETCH(QVariant, parameter); + //QDBusInterface *if4 = new QDBusInterface(QString(), "/", interface, con); + + // connect all signals and emit only one + { + QDBusSignalSpy spy; + con.connect(QString(), "/", "local.Interface4", "signal", "", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.Interface4", "signal", "i", + &spy, SLOT(slot(QDBusMessage))); + con.connect(QString(), "/", "local.Interface4", "signal", "s", + &spy, SLOT(slot(QDBusMessage))); + + emitSignalPeer(interface, name, parameter); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } + + QFETCH(QString, signature); + // connect one signal and emit them all + { + QDBusSignalSpy spy; + con.connect(QString(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage))); + emitSignalPeer("local.Interface4", "signal", QVariant()); + emitSignalPeer("local.Interface4", "signal", QVariant(1)); + emitSignalPeer("local.Interface4", "signal", QVariant("foo")); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } +} + +void tst_QDBusAbstractAdaptor::readPropertiesPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + + for (int j = 1; j <= 2; ++j) { + QString propname = QString("prop%1").arg(j); + QDBusReply<QVariant> reply = + properties.call(QDBus::BlockWithGui, "Get", "local." + name, propname); + QVariant value = reply; + + QCOMPARE(value.userType(), int(QVariant::String)); + QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname)); + } + } +} + +void tst_QDBusAbstractAdaptor::readPropertiesInvalidInterfacePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + + // test an invalid interface: + QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "local.DoesntExist", "prop1"); + QVERIFY(!reply.isValid()); +} + +void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer_data() +{ + readPropertiesEmptyInterface_data(); +} + +void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + + QFETCH(QVariantMap, expectedProperties); + QFETCH(bool, existing); + + QVariantMap::ConstIterator it = expectedProperties.constBegin(); + for ( ; it != expectedProperties.constEnd(); ++it) { + QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "", it.key()); + + if (existing) { + QVERIFY2(reply.isValid(), qPrintable(it.key())); + } else { + QVERIFY2(!reply.isValid(), qPrintable(it.key())); + continue; + } + + QCOMPARE(int(reply.value().type()), int(QVariant::String)); + if (it.value().isValid()) + QCOMPARE(reply.value().toString(), it.value().toString()); + } +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + QDBusReply<QVariantMap> reply = + properties.call(QDBus::BlockWithGui, "GetAll", "local." + name); + + for (int j = 1; j <= 2; ++j) { + QString propname = QString("prop%1").arg(j); + QVERIFY2(reply.value().contains(propname), + qPrintable(propname + " on " + name)); + QVariant value = reply.value().value(propname); + + QCOMPARE(value.userType(), int(QVariant::String)); + QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname)); + } + } +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesInvalidInterfacePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + + // test an invalid interface: + QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "local.DoesntExist"); + QVERIFY(!reply.isValid()); +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer_data() +{ + readAllPropertiesEmptyInterface_data(); +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + + QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", ""); + QVERIFY(reply.isValid()); + + QVariantMap allprops = reply; + + QFETCH(QVariantMap, expectedProperties); + QFETCH(bool, existing); + + QVariantMap::ConstIterator it = expectedProperties.constBegin(); + if (existing) { + for ( ; it != expectedProperties.constEnd(); ++it) { + QVERIFY2(allprops.contains(it.key()), qPrintable(it.key())); + + QVariant propvalue = allprops.value(it.key()); + QVERIFY2(!propvalue.isNull(), qPrintable(it.key())); + QVERIFY2(propvalue.isValid(), qPrintable(it.key())); + + QString stringvalue = propvalue.toString(); + QVERIFY2(!stringvalue.isEmpty(), qPrintable(it.key())); + + if (it.value().isValid()) + QCOMPARE(stringvalue, it.value().toString()); + + // remove this property from the map + allprops.remove(it.key()); + } + + QVERIFY2(allprops.isEmpty(), + qPrintable(QStringList(allprops.keys()).join(" "))); + } else { + for ( ; it != expectedProperties.constEnd(); ++it) + QVERIFY2(!allprops.contains(it.key()), qPrintable(it.key())); + } +} + +void tst_QDBusAbstractAdaptor::writePropertiesPeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + + clearValueSpyPeer(); + properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop1"), + qVariantFromValue(QDBusVariant(name))); + QVERIFY(valueSpyPeer().isEmpty()); // call mustn't have succeeded + + properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop2"), + qVariantFromValue(QDBusVariant(name))); + QCOMPARE(valueSpyPeer(), name); + QCOMPARE(QString(slotSpyPeer()), QString("void %1::setProp2(const QString &)").arg(name)); + } +} + #if 0 void tst_QDBusAbstractAdaptor::adaptorIntrospection_data() { @@ -1438,6 +1867,28 @@ void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValue() QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString); } +void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValuePeer() +{ + QDBusConnection con("peer"); + QVERIFY(con.isConnected()); + + newMyObjectPeer(); + registerMyObjectPeer("/"); + + QString testString = "This is a test string."; + + QDBusInterface remote(QString(), "/", "local.Interface3", con); + QDBusMessage reply = remote.call(QDBus::BlockWithGui, "methodStringString", testString); + QVERIFY(reply.arguments().count() == 2); + + QDBusReply<int> intreply = reply; + QVERIFY(intreply.isValid()); + QCOMPARE(intreply.value(), 42); + + QCOMPARE(reply.arguments().at(1).userType(), int(QVariant::String)); + QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString); +} + QTEST_MAIN(tst_QDBusAbstractAdaptor) #include "tst_qdbusabstractadaptor.moc" diff --git a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml index fb2aab8..1667591 100644 --- a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml +++ b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml @@ -24,7 +24,7 @@ </method> <method name="multiOutMethod"> <arg type="s" direction="out"/> - <arg type="i" direction="out"/ + <arg type="i" direction="out"/> </method> </interface> </node> diff --git a/tests/auto/qdbusabstractinterface/interface.h b/tests/auto/qdbusabstractinterface/interface.h index 9a14222..62f81af 100644 --- a/tests/auto/qdbusabstractinterface/interface.h +++ b/tests/auto/qdbusabstractinterface/interface.h @@ -84,6 +84,7 @@ class Interface: public QObject Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp SCRIPTABLE true) friend class tst_QDBusAbstractInterface; + friend class PingerServer; QString m_stringProp; QDBusVariant m_variantProp; RegisteredType m_complexProp; diff --git a/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro index a4853b8..f9077b9 100644 --- a/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro +++ b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro @@ -1,15 +1,10 @@ load(qttest_p4) -QT = core -contains(QT_CONFIG,dbus): { - SOURCES += tst_qdbusabstractinterface.cpp interface.cpp - HEADERS += interface.h - QT += dbus - - # These are generated sources - # To regenerate, see the command-line at the top of the files - SOURCES += pinger.cpp - HEADERS += pinger.h +contains(QT_CONFIG,dbus): { + TEMPLATE = subdirs + CONFIG += ordered + SUBDIRS = qpinger test +} else { + SOURCES += ../qdbusmarshall/dummy.cpp } -else:SOURCES += ../qdbusmarshall/dummy.cpp OTHER_FILES += com.trolltech.QtDBus.Pinger.xml diff --git a/tests/auto/qdbusperformance/server/server.cpp b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp index 3bd5efc..3b605c8 100644 --- a/tests/auto/qdbusperformance/server/server.cpp +++ b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp @@ -40,16 +40,79 @@ ****************************************************************************/ #include <QtCore/QtCore> #include <QtDBus/QtDBus> +#include "../interface.h" -#include "../serverobject.h" +static const char serviceName[] = "com.trolltech.autotests.qpinger"; +static const char objectPath[] = "/com/trolltech/qpinger"; +//static const char *interfaceName = serviceName; -static const char serviceName[] = "com.trolltech.autotests.performance"; -static const char objectPath[] = "/"; +class PingerServer : public QDBusServer +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qpinger") +public: + PingerServer(QString addr = "unix:tmpdir=/tmp", QObject* parent = 0) + : QDBusServer(addr, parent), + m_conn("none") + { + connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&))); + reset(); + } + +public slots: + QString address() const + { + return QDBusServer::address(); + } + + bool isConnected() const + { + return m_conn.isConnected(); + } + + void reset() + { + targetObj.m_stringProp = "This is a test"; + targetObj.m_variantProp = QDBusVariant(QVariant(42)); + targetObj.m_complexProp = RegisteredType("This is a test"); + } + + void voidSignal() + { + emit targetObj.voidSignal(); + } + + void stringSignal(const QString& value) + { + emit targetObj.stringSignal(value); + } + + void complexSignal(const QString& value) + { + RegisteredType reg(value); + emit targetObj.complexSignal(reg); + } + +private slots: + void handleConnection(const QDBusConnection& con) + { + m_conn = con; + m_conn.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents); + } + +private: + Interface targetObj; + QDBusConnection m_conn; +}; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); + // register the meta types + qDBusRegisterMetaType<RegisteredType>(); + qRegisterMetaType<UnregisteredType>(); + QDBusConnection con = QDBusConnection::sessionBus(); if (!con.isConnected()) exit(1); @@ -57,8 +120,12 @@ int main(int argc, char *argv[]) if (!con.registerService(serviceName)) exit(2); - ServerObject obj(objectPath, con); + PingerServer server; + con.registerObject(objectPath, &server, QDBusConnection::ExportAllSlots); + printf("ready.\n"); + return app.exec(); } +#include "qpinger.moc" diff --git a/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro b/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro new file mode 100644 index 0000000..27545bb --- /dev/null +++ b/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro @@ -0,0 +1,5 @@ +SOURCES = qpinger.cpp ../interface.cpp +HEADERS = ../interface.h +TARGET = qpinger +QT += dbus +QT -= gui diff --git a/tests/auto/qdbusabstractinterface/test/test.pro b/tests/auto/qdbusabstractinterface/test/test.pro new file mode 100644 index 0000000..98bcaa7 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/test/test.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +SOURCES += ../tst_qdbusabstractinterface.cpp ../interface.cpp +HEADERS += ../interface.h + +# These are generated sources +# To regenerate, see the command-line at the top of the files +SOURCES += ../pinger.cpp +HEADERS += ../pinger.h + +TARGET = ../tst_qdbusabstractinterface + +QT = core +QT += dbus diff --git a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp index e8ce1f9..6f93d8a 100644 --- a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp +++ b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp @@ -49,6 +49,10 @@ #include "interface.h" #include "pinger.h" +static const char serviceName[] = "com.trolltech.autotests.qpinger"; +static const char objectPath[] = "/com/trolltech/qpinger"; +static const char *interfaceName = serviceName; + typedef QSharedPointer<com::trolltech::QtDBus::Pinger> Pinger; class tst_QDBusAbstractInterface: public QObject @@ -66,22 +70,47 @@ class tst_QDBusAbstractInterface: public QObject return Pinger(new com::trolltech::QtDBus::Pinger(service, path, con)); } + Pinger getPingerPeer(const QString &path = "/") + { + QDBusConnection con = QDBusConnection("peer"); + if (!con.isConnected()) + return Pinger(); + return Pinger(new com::trolltech::QtDBus::Pinger("", path, con)); + } + + void resetServer() + { + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "reset"); + QDBusConnection::sessionBus().send(req); + } + public: tst_QDBusAbstractInterface(); private slots: void initTestCase(); + void cleanupTestCase(); void makeVoidCall(); void makeStringCall(); void makeComplexCall(); void makeMultiOutCall(); + void makeVoidCallPeer(); + void makeStringCallPeer(); + void makeComplexCallPeer(); + void makeMultiOutCallPeer(); + void makeAsyncVoidCall(); void makeAsyncStringCall(); void makeAsyncComplexCall(); void makeAsyncMultiOutCall(); + void makeAsyncVoidCallPeer(); + void makeAsyncStringCallPeer(); + void makeAsyncComplexCallPeer(); + void makeAsyncMultiOutCallPeer(); + void stringPropRead(); void stringPropWrite(); void variantPropRead(); @@ -89,6 +118,13 @@ private slots: void complexPropRead(); void complexPropWrite(); + void stringPropReadPeer(); + void stringPropWritePeer(); + void variantPropReadPeer(); + void variantPropWritePeer(); + void complexPropReadPeer(); + void complexPropWritePeer(); + void stringPropDirectRead(); void stringPropDirectWrite(); void variantPropDirectRead(); @@ -96,6 +132,13 @@ private slots: void complexPropDirectRead(); void complexPropDirectWrite(); + void stringPropDirectReadPeer(); + void stringPropDirectWritePeer(); + void variantPropDirectReadPeer(); + void variantPropDirectWritePeer(); + void complexPropDirectReadPeer(); + void complexPropDirectWritePeer(); + void getVoidSignal_data(); void getVoidSignal(); void getStringSignal_data(); @@ -103,16 +146,31 @@ private slots: void getComplexSignal_data(); void getComplexSignal(); + void getVoidSignalPeer_data(); + void getVoidSignalPeer(); + void getStringSignalPeer_data(); + void getStringSignalPeer(); + void getComplexSignalPeer_data(); + void getComplexSignalPeer(); + void followSignal(); void createErrors_data(); void createErrors(); + void createErrorsPeer_data(); + void createErrorsPeer(); + void callErrors_data(); void callErrors(); void asyncCallErrors_data(); void asyncCallErrors(); + void callErrorsPeer_data(); + void callErrorsPeer(); + void asyncCallErrorsPeer_data(); + void asyncCallErrorsPeer(); + void propertyReadErrors_data(); void propertyReadErrors(); void propertyWriteErrors_data(); @@ -121,8 +179,53 @@ private slots: void directPropertyReadErrors(); void directPropertyWriteErrors_data(); void directPropertyWriteErrors(); + + void propertyReadErrorsPeer_data(); + void propertyReadErrorsPeer(); + void propertyWriteErrorsPeer_data(); + void propertyWriteErrorsPeer(); + void directPropertyReadErrorsPeer_data(); + void directPropertyReadErrorsPeer(); + void directPropertyWriteErrorsPeer_data(); + void directPropertyWriteErrorsPeer(); +private: + QProcess proc; +}; + +class WaitForQPinger: public QObject +{ + Q_OBJECT +public: + WaitForQPinger(); + bool ok(); +public Q_SLOTS: + void ownerChange(const QString &name) + { + if (name == serviceName) + loop.quit(); + } + +private: + QEventLoop loop; }; +WaitForQPinger::WaitForQPinger() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + if (!ok()) { + connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), + SLOT(ownerChange(QString))); + QTimer::singleShot(2000, &loop, SLOT(quit())); + loop.exec(); + } +} + +bool WaitForQPinger::ok() +{ + return QDBusConnection::sessionBus().isConnected() && + QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName); +} + tst_QDBusAbstractInterface::tst_QDBusAbstractInterface() { // register the meta types @@ -139,6 +242,39 @@ void tst_QDBusAbstractInterface::initTestCase() QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); con.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents); + + // start peer server + #ifdef Q_OS_WIN + proc.start("qpinger"); + #else + proc.start("./qpinger/qpinger"); + #endif + QVERIFY(proc.waitForStarted()); + + WaitForQPinger w; + QVERIFY(w.ok()); + //QTest::qWait(2000); + + // get peer server address + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "address"); + QDBusMessage rpl = con.call(req); + QVERIFY(rpl.type() == QDBusMessage::ReplyMessage); + QString address = rpl.arguments().at(0).toString(); + + // connect to peer server + QDBusConnection peercon = QDBusConnection::connectToPeer(address, "peer"); + QVERIFY(peercon.isConnected()); + + QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "isConnected"); + QDBusMessage rpl2 = con.call(req2); + QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage); + QVERIFY(rpl2.arguments().at(0).toBool()); +} + +void tst_QDBusAbstractInterface::cleanupTestCase() +{ + proc.close(); + proc.kill(); } void tst_QDBusAbstractInterface::makeVoidCall() @@ -184,6 +320,49 @@ void tst_QDBusAbstractInterface::makeMultiOutCall() QCOMPARE(value, expectedValue); } +void tst_QDBusAbstractInterface::makeVoidCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply<void> r = p->voidMethod(); + QVERIFY(r.isValid()); +} + +void tst_QDBusAbstractInterface::makeStringCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply<QString> r = p->stringMethod(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.stringMethod()); +} + +void tst_QDBusAbstractInterface::makeComplexCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply<RegisteredType> r = p->complexMethod(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.complexMethod()); +} + +void tst_QDBusAbstractInterface::makeMultiOutCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + int value; + QDBusReply<QString> r = p->multiOutMethod(value); + QVERIFY(r.isValid()); + + int expectedValue; + QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); + QCOMPARE(value, expectedValue); +} + void tst_QDBusAbstractInterface::makeAsyncVoidCall() { Pinger p = getPinger(); @@ -230,6 +409,55 @@ void tst_QDBusAbstractInterface::makeAsyncMultiOutCall() QCOMPARE(r.argumentAt<1>(), expectedValue); } +void tst_QDBusAbstractInterface::makeAsyncVoidCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply<void> r = p->voidMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); +} +void tst_QDBusAbstractInterface::makeAsyncStringCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusMessage reply = p->call(QDBus::BlockWithGui, QLatin1String("voidMethod")); + QVERIFY(reply.type() == QDBusMessage::ReplyMessage); + + QDBusPendingReply<QString> r = p->stringMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.stringMethod()); +} + +void tst_QDBusAbstractInterface::makeAsyncComplexCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply<RegisteredType> r = p->complexMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.complexMethod()); +} + +void tst_QDBusAbstractInterface::makeAsyncMultiOutCallPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply<QString, int> r = p->multiOutMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + + int expectedValue; + QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); + QCOMPARE(r.argumentAt<1>(), expectedValue); + QCoreApplication::instance()->processEvents(); +} + void tst_QDBusAbstractInterface::stringPropRead() { Pinger p = getPinger(); @@ -295,6 +523,77 @@ void tst_QDBusAbstractInterface::complexPropWrite() QCOMPARE(targetObj.m_complexProp, expectedValue); } +void tst_QDBusAbstractInterface::stringPropReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QString expectedValue = "This is a test"; + QVariant v = p->property("stringProp"); + QVERIFY(v.isValid()); + QCOMPARE(v.toString(), expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QString expectedValue = "This is a value"; + QVERIFY(p->setProperty("stringProp", expectedValue)); + QCOMPARE(targetObj.m_stringProp, expectedValue); +} + +void tst_QDBusAbstractInterface::variantPropReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QDBusVariant expectedValue = QDBusVariant(QVariant(42)); + QVariant v = p->property("variantProp"); + QVERIFY(v.isValid()); + QDBusVariant value = v.value<QDBusVariant>(); + QCOMPARE(value.variant().userType(), expectedValue.variant().userType()); + QCOMPARE(value.variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::variantPropWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47)); + QVERIFY(p->setProperty("variantProp", qVariantFromValue(expectedValue))); + QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::complexPropReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + RegisteredType expectedValue = RegisteredType("This is a test"); + QVariant v = p->property("complexProp"); + QVERIFY(v.userType() == qMetaTypeId<RegisteredType>()); + QCOMPARE(v.value<RegisteredType>(), expectedValue); +} + +void tst_QDBusAbstractInterface::complexPropWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + RegisteredType expectedValue = RegisteredType("This is a value"); + QVERIFY(p->setProperty("complexProp", qVariantFromValue(expectedValue))); + QCOMPARE(targetObj.m_complexProp, expectedValue); +} + void tst_QDBusAbstractInterface::stringPropDirectRead() { Pinger p = getPinger(); @@ -353,6 +652,70 @@ void tst_QDBusAbstractInterface::complexPropDirectWrite() QCOMPARE(targetObj.m_complexProp, expectedValue); } +void tst_QDBusAbstractInterface::stringPropDirectReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QString expectedValue = "This is a test"; + QCOMPARE(p->stringProp(), expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropDirectWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QString expectedValue = "This is a value"; + p->setStringProp(expectedValue); + QCOMPARE(targetObj.m_stringProp, expectedValue); +} + +void tst_QDBusAbstractInterface::variantPropDirectReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QDBusVariant expectedValue = QDBusVariant(42); + QCOMPARE(p->variantProp().variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::variantPropDirectWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47)); + p->setVariantProp(expectedValue); + QCOMPARE(targetObj.m_variantProp.variant().userType(), expectedValue.variant().userType()); + QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::complexPropDirectReadPeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + RegisteredType expectedValue = RegisteredType("This is a test"); + QCOMPARE(p->complexProp(), expectedValue); +} + +void tst_QDBusAbstractInterface::complexPropDirectWritePeer() +{ + Pinger p = getPingerPeer(); + QVERIFY2(p, "Not connected to D-Bus"); + resetServer(); + + RegisteredType expectedValue = RegisteredType("This is a value"); + p->setComplexProp(expectedValue); + QCOMPARE(targetObj.m_complexProp, expectedValue); +} + void tst_QDBusAbstractInterface::getVoidSignal_data() { QTest::addColumn<QString>("service"); @@ -437,6 +800,89 @@ void tst_QDBusAbstractInterface::getComplexSignal() QCOMPARE(s[0][0].value<RegisteredType>(), expectedValue); } +void tst_QDBusAbstractInterface::getVoidSignalPeer_data() +{ + QTest::addColumn<QString>("path"); + + QTest::newRow("specific") << "/"; + QTest::newRow("wildcard") << QString(); +} + +void tst_QDBusAbstractInterface::getVoidSignalPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(voidSignal())); + + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "voidSignal"); + QVERIFY(QDBusConnection::sessionBus().send(req)); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s.at(0).size() == 0); +} + +void tst_QDBusAbstractInterface::getStringSignalPeer_data() +{ + getVoidSignalPeer_data(); +} + +void tst_QDBusAbstractInterface::getStringSignalPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(stringSignal(QString)), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(stringSignal(QString))); + + QString expectedValue = "Good morning"; + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "stringSignal"); + req << expectedValue; + QVERIFY(QDBusConnection::sessionBus().send(req)); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s[0].size() == 1); + QCOMPARE(s[0][0].userType(), int(QVariant::String)); + QCOMPARE(s[0][0].toString(), expectedValue); +} + +void tst_QDBusAbstractInterface::getComplexSignalPeer_data() +{ + getVoidSignalPeer_data(); +} + +void tst_QDBusAbstractInterface::getComplexSignalPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(complexSignal(RegisteredType)), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(complexSignal(RegisteredType))); + + RegisteredType expectedValue("Good evening"); + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "complexSignal"); + req << "Good evening"; + QVERIFY(QDBusConnection::sessionBus().send(req)); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s[0].size() == 1); + QCOMPARE(s[0][0].userType(), qMetaTypeId<RegisteredType>()); + QCOMPARE(s[0][0].value<RegisteredType>(), expectedValue); +} + void tst_QDBusAbstractInterface::followSignal() { const QString serviceToFollow = "com.trolltech.tst_qdbusabstractinterface.FollowMe"; @@ -514,6 +960,24 @@ void tst_QDBusAbstractInterface::createErrors() QTEST(p->lastError().name(), "errorName"); } +void tst_QDBusAbstractInterface::createErrorsPeer_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<QString>("errorName"); + + QTest::newRow("invalid-path") << "this isn't valid" << "com.trolltech.QtDBus.Error.InvalidObjectPath"; +} + +void tst_QDBusAbstractInterface::createErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + QVERIFY(!p->isValid()); + QTEST(p->lastError().name(), "errorName"); +} + void tst_QDBusAbstractInterface::callErrors_data() { createErrors_data(); @@ -556,6 +1020,43 @@ void tst_QDBusAbstractInterface::asyncCallErrors() QCOMPARE(p->lastError().name(), r.error().name()); } +void tst_QDBusAbstractInterface::callErrorsPeer_data() +{ + createErrorsPeer_data(); + QTest::newRow("path-wildcard") << QString() << "com.trolltech.QtDBus.Error.InvalidObjectPath"; +} + +void tst_QDBusAbstractInterface::callErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to make this call: + QDBusReply<QString> r = p->stringMethod(); + QVERIFY(!r.isValid()); + QTEST(r.error().name(), "errorName"); + QCOMPARE(p->lastError().name(), r.error().name()); +} + +void tst_QDBusAbstractInterface::asyncCallErrorsPeer_data() +{ + callErrorsPeer_data(); +} + +void tst_QDBusAbstractInterface::asyncCallErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to make this call: + QDBusPendingReply<QString> r = p->stringMethod(); + QVERIFY(r.isError()); + QTEST(r.error().name(), "errorName"); + QCOMPARE(p->lastError().name(), r.error().name()); +} + void tst_QDBusAbstractInterface::propertyReadErrors_data() { callErrors_data(); @@ -632,5 +1133,77 @@ void tst_QDBusAbstractInterface::directPropertyWriteErrors() QTEST(p->lastError().name(), "errorName"); } +void tst_QDBusAbstractInterface::propertyReadErrorsPeer_data() +{ + callErrorsPeer_data(); +} + +void tst_QDBusAbstractInterface::propertyReadErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + QVariant v = p->property("stringProp"); + QVERIFY(v.isNull()); + QVERIFY(!v.isValid()); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::propertyWriteErrorsPeer_data() +{ + callErrorsPeer_data(); +} + +void tst_QDBusAbstractInterface::propertyWriteErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + if (p->isValid()) + QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError)); + QVERIFY(!p->setProperty("stringProp", "")); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::directPropertyReadErrorsPeer_data() +{ + callErrorsPeer_data(); +} + +void tst_QDBusAbstractInterface::directPropertyReadErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + QString v = p->stringProp(); + QVERIFY(v.isNull()); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::directPropertyWriteErrorsPeer_data() +{ + callErrorsPeer_data(); +} + +void tst_QDBusAbstractInterface::directPropertyWriteErrorsPeer() +{ + QFETCH(QString, path); + Pinger p = getPingerPeer(path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + // but there's no direct way of verifying that the setting failed + if (p->isValid()) + QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError)); + p->setStringProp(""); + QTEST(p->lastError().name(), "errorName"); +} + QTEST_MAIN(tst_QDBusAbstractInterface) #include "tst_qdbusabstractinterface.moc" diff --git a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp index 8e3a44b..d4a9dab 100644 --- a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp @@ -86,6 +86,7 @@ public slots: private slots: void noConnection(); void connectToBus(); + void connectToPeer(); void connect(); void send(); void sendWithGui(); @@ -94,9 +95,13 @@ private slots: void registerObject_data(); void registerObject(); + void registerObjectPeer_data(); + void registerObjectPeer(); void registerObject2(); + void registerObjectPeer2(); void registerQObjectChildren(); + void registerQObjectChildrenPeer(); void callSelf(); void callSelfByAnotherName_data(); @@ -111,6 +116,7 @@ private slots: public: QString serviceName() const { return "com.trolltech.Qt.Autotests.QDBusConnection"; } bool callMethod(const QDBusConnection &conn, const QString &path); + bool callMethodPeer(const QDBusConnection &conn, const QString &path); }; class QDBusSpy: public QObject @@ -259,6 +265,14 @@ void tst_QDBusConnection::connectToBus() QVERIFY(!con.lastError().isValid()); } + QDBusConnection::disconnectFromPeer("bubu"); + + { + QDBusConnection con("bubu"); + QVERIFY(con.isConnected()); + QVERIFY(!con.lastError().isValid()); + } + QDBusConnection::disconnectFromBus("bubu"); { @@ -277,6 +291,65 @@ void tst_QDBusConnection::connectToBus() } } +void tst_QDBusConnection::connectToPeer() +{ + { + QDBusConnection con = QDBusConnection::connectToPeer( + "", "newconn"); + QVERIFY(!con.isConnected()); + QVERIFY(con.lastError().isValid()); + } + + QDBusServer server("unix:tmpdir=/tmp", 0); + + { + QDBusConnection con = QDBusConnection::connectToPeer( + "unix:abstract=/tmp/dbus-XXXXXXXXXX,guid=00000000000000000000000000000000", "newconn2"); + QVERIFY(!con.isConnected()); + QVERIFY(con.lastError().isValid()); + } + + { + QDBusConnection con = QDBusConnection::connectToPeer( + server.address(), "bubu"); + + QVERIFY(con.isConnected()); + QVERIFY(!con.lastError().isValid()); + + QDBusConnection con2("foo"); + QVERIFY(!con2.isConnected()); + QVERIFY(!con2.lastError().isValid()); + + con2 = con; + QVERIFY(con.isConnected()); + QVERIFY(con2.isConnected()); + QVERIFY(!con.lastError().isValid()); + QVERIFY(!con2.lastError().isValid()); + } + + { + QDBusConnection con("bubu"); + QVERIFY(con.isConnected()); + QVERIFY(!con.lastError().isValid()); + } + + QDBusConnection::disconnectFromBus("bubu"); + + { + QDBusConnection con("bubu"); + QVERIFY(con.isConnected()); + QVERIFY(!con.lastError().isValid()); + } + + QDBusConnection::disconnectFromPeer("bubu"); + + { + QDBusConnection con("bubu"); + QVERIFY(!con.isConnected()); + QVERIFY(!con.lastError().isValid()); + } +} + void tst_QDBusConnection::registerObject_data() { QTest::addColumn<QString>("path"); @@ -308,6 +381,106 @@ void tst_QDBusConnection::registerObject() QVERIFY(!callMethod(con, path)); } +class MyServer : public QDBusServer +{ + Q_OBJECT +public: + MyServer(QString path, QString addr, QObject* parent) : QDBusServer(addr, parent), + m_path(path), + m_conn("none") + { + connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&))); + } + + bool registerObject() + { + if( !m_conn.registerObject(m_path, &m_obj, QDBusConnection::ExportAllSlots) ) + return false; + if(! (m_conn.objectRegisteredAt(m_path) == &m_obj)) + return false; + return true; + } + + void unregisterObject() + { + m_conn.unregisterObject(m_path); + } + +public slots: + void handleConnection(const QDBusConnection& c) + { + m_conn = c; + QVERIFY(isConnected()); + QVERIFY(m_conn.isConnected()); + QVERIFY(registerObject()); + } + +private: + MyObject m_obj; + QString m_path; + QDBusConnection m_conn; +}; + + +void tst_QDBusConnection::registerObjectPeer_data() +{ + QTest::addColumn<QString>("path"); + + QTest::newRow("/") << "/"; + QTest::newRow("/p1") << "/p1"; + QTest::newRow("/p2") << "/p2"; + QTest::newRow("/p1/q") << "/p1/q"; + QTest::newRow("/p1/q/r") << "/p1/q/r"; +} + +void tst_QDBusConnection::registerObjectPeer() +{ + QFETCH(QString, path); + + MyServer server(path, "unix:tmpdir=/tmp", 0); + + { + QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo"); + + QCoreApplication::processEvents(); + QVERIFY(con.isConnected()); + + MyObject obj; + QVERIFY(callMethodPeer(con, path)); + QCOMPARE(obj.path, path); + } + + { + QDBusConnection con("foo"); + QVERIFY(con.isConnected()); + QVERIFY(callMethodPeer(con, path)); + } + + server.unregisterObject(); + + { + QDBusConnection con("foo"); + QVERIFY(con.isConnected()); + QVERIFY(!callMethodPeer(con, path)); + } + + server.registerObject(); + + { + QDBusConnection con("foo"); + QVERIFY(con.isConnected()); + QVERIFY(callMethodPeer(con, path)); + } + + QDBusConnection::disconnectFromPeer("foo"); + + { + QDBusConnection con("foo"); + QVERIFY(!con.isConnected()); + QVERIFY(!callMethodPeer(con, path)); + } +} + void tst_QDBusConnection::registerObject2() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -401,6 +574,134 @@ void tst_QDBusConnection::registerObject2() } } +class MyServer2 : public QDBusServer +{ + Q_OBJECT +public: + MyServer2(QString addr, QObject* parent) : QDBusServer(addr, parent), + m_conn("none") + { + connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&))); + } + + QDBusConnection connection() + { + return m_conn; + } + +public slots: + void handleConnection(const QDBusConnection& c) + { + m_conn = c; + QVERIFY(isConnected()); + QVERIFY(m_conn.isConnected()); + } + +private: + MyObject m_obj; + QDBusConnection m_conn; +}; + +void tst_QDBusConnection::registerObjectPeer2() +{ + MyServer2 server("unix:tmpdir=/tmp", 0); + QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo"); + QCoreApplication::processEvents(); + QVERIFY(con.isConnected()); + + QDBusConnection srv_con = server.connection(); + + // make sure nothing is using our paths: + QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY(!callMethodPeer(srv_con, "/p2")); + QVERIFY(!callMethodPeer(srv_con, "/p1/q")); + QVERIFY(!callMethodPeer(srv_con, "/p1/q/r")); + + { + // register one object at root: + MyObject obj; + QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(callMethodPeer(srv_con, "/")); + qDebug() << obj.path; + QCOMPARE(obj.path, QString("/")); + } + // make sure it's gone + QVERIFY(!callMethodPeer(srv_con, "/")); + + { + // register one at an element: + MyObject obj; + QVERIFY(con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY(callMethodPeer(srv_con, "/p1")); + qDebug() << obj.path; + QCOMPARE(obj.path, QString("/p1")); + + // re-register it somewhere else + QVERIFY(con.registerObject("/p2", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(callMethodPeer(srv_con, "/p1")); + QCOMPARE(obj.path, QString("/p1")); + QVERIFY(callMethodPeer(srv_con, "/p2")); + QCOMPARE(obj.path, QString("/p2")); + } + // make sure it's gone + QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY(!callMethodPeer(srv_con, "/p2")); + + { + // register at a deep path + MyObject obj; + QVERIFY(con.registerObject("/p1/q/r", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(!callMethodPeer(srv_con, "/")); + QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY(!callMethodPeer(srv_con, "/p1/q")); + QVERIFY(callMethodPeer(srv_con, "/p1/q/r")); + QCOMPARE(obj.path, QString("/p1/q/r")); + } + // make sure it's gone + QVERIFY(!callMethodPeer(srv_con, "/p1/q/r")); + + { + MyObject obj; + QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); + QCOMPARE(obj.path, QString("/p1/q2")); + + // try unregistering + con.unregisterObject("/p1/q2"); + QVERIFY(!callMethodPeer(srv_con, "/p1/q2")); + + // register it again + QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots)); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); + QCOMPARE(obj.path, QString("/p1/q2")); + + // now try removing things around it: + con.unregisterObject("/p2"); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unrelated object shouldn't affect + + con.unregisterObject("/p1"); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering just the parent shouldn't affect it + + con.unregisterObject("/p1/q2/r"); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering non-existing child shouldn't affect it either + + con.unregisterObject("/p1/q"); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (before) shouldn't affect + + con.unregisterObject("/p1/r"); + QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (after) shouldn't affect + + // now remove it: + con.unregisterObject("/p1", QDBusConnection::UnregisterTree); + QVERIFY(!callMethodPeer(srv_con, "/p1/q2")); // we removed the full tree + } + + QDBusConnection::disconnectFromPeer("foo"); +} + + void tst_QDBusConnection::registerQObjectChildren() { // make sure no one is there @@ -456,6 +757,68 @@ void tst_QDBusConnection::registerQObjectChildren() QVERIFY(!callMethod(con, "/p1/c/cc")); } +void tst_QDBusConnection::registerQObjectChildrenPeer() +{ + MyServer2 server("unix:tmpdir=/tmp", 0); + QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo"); + QCoreApplication::processEvents(); + QVERIFY(con.isConnected()); + + QDBusConnection srv_con = server.connection(); + + QVERIFY(!callMethodPeer(srv_con, "/p1")); + + { + MyObject obj, *a, *b, *c, *cc; + + a = new MyObject(&obj); + a->setObjectName("a"); + + b = new MyObject(&obj); + b->setObjectName("b"); + + c = new MyObject(&obj); + c->setObjectName("c"); + + cc = new MyObject(c); + cc->setObjectName("cc"); + + con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots | + QDBusConnection::ExportChildObjects); + + // make calls + QVERIFY(callMethodPeer(srv_con, "/p1")); + QCOMPARE(obj.callCount, 1); + QVERIFY(callMethodPeer(srv_con, "/p1/a")); + QCOMPARE(a->callCount, 1); + QVERIFY(callMethodPeer(srv_con, "/p1/b")); + QCOMPARE(b->callCount, 1); + QVERIFY(callMethodPeer(srv_con, "/p1/c")); + QCOMPARE(c->callCount, 1); + QVERIFY(callMethodPeer(srv_con, "/p1/c/cc")); + QCOMPARE(cc->callCount, 1); + + QVERIFY(!callMethodPeer(srv_con, "/p1/d")); + QVERIFY(!callMethodPeer(srv_con, "/p1/c/abc")); + + // pull an object, see if it goes away: + delete b; + QVERIFY(!callMethodPeer(srv_con, "/p1/b")); + + delete c; + QVERIFY(!callMethodPeer(srv_con, "/p1/c")); + QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc")); + } + + QVERIFY(!callMethodPeer(srv_con, "/p1")); + QVERIFY(!callMethodPeer(srv_con, "/p1/a")); + QVERIFY(!callMethodPeer(srv_con, "/p1/b")); + QVERIFY(!callMethodPeer(srv_con, "/p1/c")); + QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc")); + + QDBusConnection::disconnectFromPeer("foo"); +} + bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString &path) { QDBusMessage msg = QDBusMessage::createMethodCall(conn.baseService(), path, "", "method"); @@ -475,6 +838,25 @@ bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString return true; } +bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QString &path) +{ + QDBusMessage msg = QDBusMessage::createMethodCall("", path, "", "method"); + QDBusMessage reply = conn.call(msg, QDBus::BlockWithGui); + + if (reply.type() != QDBusMessage::ReplyMessage) + return false; + if (MyObject::path == path) { + QTest::compare_helper(true, "COMPARE()", __FILE__, __LINE__); + } else { + QTest::compare_helper(false, "Compared values are not the same", + QTest::toString(MyObject::path), QTest::toString(path), + "MyObject::path", "path", __FILE__, __LINE__); + return false; + } + + return true; +} + class TestObject : public QObject { Q_OBJECT diff --git a/tests/auto/qdbusinterface/myobject.h b/tests/auto/qdbusinterface/myobject.h new file mode 100644 index 0000000..68b8d1a --- /dev/null +++ b/tests/auto/qdbusinterface/myobject.h @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MYOBJECT_H +#define MYOBJECT_H + +#include <QtCore/QObject> +#include <QtDBus/QtDBus> + +Q_DECLARE_METATYPE(QVariantList) + +class MyObject: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject") + Q_CLASSINFO("D-Bus Introspection", "" +" <interface name=\"com.trolltech.QtDBus.MyObject\" >\n" +" <property access=\"readwrite\" type=\"i\" name=\"prop1\" />\n" +" <property name=\"complexProp\" type=\"ai\" access=\"readwrite\">\n" +" <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"QList<int>\"/>\n" +" </property>\n" +" <signal name=\"somethingHappened\" >\n" +" <arg direction=\"out\" type=\"s\" />\n" +" </signal>\n" +" <method name=\"ping\" >\n" +" <arg direction=\"in\" type=\"v\" name=\"ping\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"ping\" />\n" +" </method>\n" +" <method name=\"ping_invokable\" >\n" +" <arg direction=\"in\" type=\"v\" name=\"ping_invokable\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"ping_invokable\" />\n" +" </method>\n" +" <method name=\"ping\" >\n" +" <arg direction=\"in\" type=\"v\" name=\"ping1\" />\n" +" <arg direction=\"in\" type=\"v\" name=\"ping2\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"pong1\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"pong2\" />\n" +" </method>\n" +" <method name=\"ping_invokable\" >\n" +" <arg direction=\"in\" type=\"v\" name=\"ping1_invokable\" />\n" +" <arg direction=\"in\" type=\"v\" name=\"ping2_invokable\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"pong1_invokable\" />\n" +" <arg direction=\"out\" type=\"v\" name=\"pong2_invokable\" />\n" +" </method>\n" +" <method name=\"ping\" >\n" +" <arg direction=\"in\" type=\"ai\" name=\"ping\" />\n" +" <arg direction=\"out\" type=\"ai\" name=\"ping\" />\n" +" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList<int>\"/>\n" +" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList<int>\"/>\n" +" </method>\n" +" <method name=\"ping_invokable\" >\n" +" <arg direction=\"in\" type=\"ai\" name=\"ping_invokable\" />\n" +" <arg direction=\"out\" type=\"ai\" name=\"ping_invokable\" />\n" +" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList<int>\"/>\n" +" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList<int>\"/>\n" +" </method>\n" +" </interface>\n" + "") + Q_PROPERTY(int prop1 READ prop1 WRITE setProp1) + Q_PROPERTY(QList<int> complexProp READ complexProp WRITE setComplexProp) + +public: + static int callCount; + static QVariantList callArgs; + MyObject() + { + QObject *subObject = new QObject(this); + subObject->setObjectName("subObject"); + } + + int m_prop1; + int prop1() const + { + ++callCount; + return m_prop1; + } + void setProp1(int value) + { + ++callCount; + m_prop1 = value; + } + + QList<int> m_complexProp; + QList<int> complexProp() const + { + ++callCount; + return m_complexProp; + } + void setComplexProp(const QList<int> &value) + { + ++callCount; + m_complexProp = value; + } + + Q_INVOKABLE void ping_invokable(QDBusMessage msg) + { + QDBusConnection sender = QDBusConnection::sender(); + if (!sender.isConnected()) + exit(1); + + ++callCount; + callArgs = msg.arguments(); + + msg.setDelayedReply(true); + if (!sender.send(msg.createReply(callArgs))) + exit(1); + } + +public slots: + + void ping(QDBusMessage msg) + { + QDBusConnection sender = QDBusConnection::sender(); + if (!sender.isConnected()) + exit(1); + + ++callCount; + callArgs = msg.arguments(); + + msg.setDelayedReply(true); + if (!sender.send(msg.createReply(callArgs))) + exit(1); + } +}; + +#endif // INTERFACE_H diff --git a/tests/auto/qdbusinterface/qdbusinterface.pro b/tests/auto/qdbusinterface/qdbusinterface.pro index ac14ab7..0aca06c 100644 --- a/tests/auto/qdbusinterface/qdbusinterface.pro +++ b/tests/auto/qdbusinterface/qdbusinterface.pro @@ -1,10 +1,11 @@ load(qttest_p4) QT = core contains(QT_CONFIG,dbus): { - SOURCES += tst_qdbusinterface.cpp - QT += dbus + TEMPLATE = subdirs + CONFIG += ordered + SUBDIRS = qmyserver test } else { - SOURCES += ../qdbusmarshall/dummy.cpp + SOURCES += ../qdbusmarshall/dummy.cpp } diff --git a/tests/auto/qdbusinterface/qmyserver/qmyserver.cpp b/tests/auto/qdbusinterface/qmyserver/qmyserver.cpp new file mode 100644 index 0000000..c68f7bf --- /dev/null +++ b/tests/auto/qdbusinterface/qmyserver/qmyserver.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/QtCore> +#include <QtDBus/QtDBus> + +#include "../myobject.h" + +static const char serviceName[] = "com.trolltech.autotests.qmyserver"; +static const char objectPath[] = "/com/trolltech/qmyserver"; +//static const char *interfaceName = serviceName; + +int MyObject::callCount = 0; +QVariantList MyObject::callArgs; + +class MyServer : public QDBusServer +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qmyserver") + +public: + MyServer(QString addr = "unix:tmpdir=/tmp", QObject* parent = 0) + : QDBusServer(addr, parent), + m_conn("none") + { + connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&))); + } + +public slots: + QString address() const + { + return QDBusServer::address(); + } + + bool isConnected() const + { + return m_conn.isConnected(); + } + + void emitSignal(const QString &interface, const QString &name, const QString &arg) + { + QDBusMessage msg = QDBusMessage::createSignal("/", interface, name); + msg << arg; + m_conn.send(msg); + } + + void reset() + { + MyObject::callCount = 0; + obj.m_complexProp.clear(); + } + + int callCount() + { + return MyObject::callCount; + } + + QVariantList callArgs() + { + qDebug() << "callArgs" << MyObject::callArgs.count(); + return MyObject::callArgs; + } + + void setProp1(int val) + { + obj.m_prop1 = val; + } + + int prop1() + { + return obj.m_prop1; + } + + void setComplexProp(QList<int> val) + { + obj.m_complexProp = val; + } + + QList<int> complexProp() + { + return obj.m_complexProp; + } + + +private slots: + void handleConnection(const QDBusConnection& con) + { + m_conn = con; + m_conn.registerObject("/", &obj, QDBusConnection::ExportAllProperties + | QDBusConnection::ExportAllSlots + | QDBusConnection::ExportAllInvokables); + } + +private: + QDBusConnection m_conn; + MyObject obj; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + QDBusConnection con = QDBusConnection::sessionBus(); + if (!con.isConnected()) + exit(1); + + if (!con.registerService(serviceName)) + exit(2); + + MyServer server; + con.registerObject(objectPath, &server, QDBusConnection::ExportAllSlots); + + printf("ready.\n"); + + return app.exec(); +} + +#include "qmyserver.moc"
\ No newline at end of file diff --git a/tests/auto/qdbusinterface/qmyserver/qmyserver.pro b/tests/auto/qdbusinterface/qmyserver/qmyserver.pro new file mode 100644 index 0000000..f4fe02c --- /dev/null +++ b/tests/auto/qdbusinterface/qmyserver/qmyserver.pro @@ -0,0 +1,5 @@ +SOURCES = qmyserver.cpp +HEADERS = ../myobject.h +TARGET = qmyserver +QT += dbus +QT -= gui diff --git a/tests/auto/qdbusinterface/test/test.pro b/tests/auto/qdbusinterface/test/test.pro new file mode 100644 index 0000000..3252188 --- /dev/null +++ b/tests/auto/qdbusinterface/test/test.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +SOURCES += ../tst_qdbusinterface.cpp +HEADERS += ../myobject.h +TARGET = ../tst_qdbusinterface + +QT = core +QT += dbus diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index 39f0677..04b3d72 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ /* -*- C++ -*- */ + #include <qcoreapplication.h> #include <qmetatype.h> #include <QtTest/QtTest> @@ -47,125 +48,15 @@ #include <QtDBus/QtDBus> #include "../qdbusmarshall/common.h" - -Q_DECLARE_METATYPE(QVariantList) +#include "myobject.h" #define TEST_INTERFACE_NAME "com.trolltech.QtDBus.MyObject" #define TEST_SIGNAL_NAME "somethingHappened" -class MyObject: public QObject -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject") - Q_CLASSINFO("D-Bus Introspection", "" -" <interface name=\"com.trolltech.QtDBus.MyObject\" >\n" -" <property access=\"readwrite\" type=\"i\" name=\"prop1\" />\n" -" <property name=\"complexProp\" type=\"ai\" access=\"readwrite\">\n" -" <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"QList<int>\"/>\n" -" </property>\n" -" <signal name=\"somethingHappened\" >\n" -" <arg direction=\"out\" type=\"s\" />\n" -" </signal>\n" -" <method name=\"ping\" >\n" -" <arg direction=\"in\" type=\"v\" name=\"ping\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"ping\" />\n" -" </method>\n" -" <method name=\"ping_invokable\" >\n" -" <arg direction=\"in\" type=\"v\" name=\"ping_invokable\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"ping_invokable\" />\n" -" </method>\n" -" <method name=\"ping\" >\n" -" <arg direction=\"in\" type=\"v\" name=\"ping1\" />\n" -" <arg direction=\"in\" type=\"v\" name=\"ping2\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"pong1\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"pong2\" />\n" -" </method>\n" -" <method name=\"ping_invokable\" >\n" -" <arg direction=\"in\" type=\"v\" name=\"ping1_invokable\" />\n" -" <arg direction=\"in\" type=\"v\" name=\"ping2_invokable\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"pong1_invokable\" />\n" -" <arg direction=\"out\" type=\"v\" name=\"pong2_invokable\" />\n" -" </method>\n" -" <method name=\"ping\" >\n" -" <arg direction=\"in\" type=\"ai\" name=\"ping\" />\n" -" <arg direction=\"out\" type=\"ai\" name=\"ping\" />\n" -" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList<int>\"/>\n" -" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList<int>\"/>\n" -" </method>\n" -" <method name=\"ping_invokable\" >\n" -" <arg direction=\"in\" type=\"ai\" name=\"ping_invokable\" />\n" -" <arg direction=\"out\" type=\"ai\" name=\"ping_invokable\" />\n" -" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList<int>\"/>\n" -" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList<int>\"/>\n" -" </method>\n" -" </interface>\n" - "") - Q_PROPERTY(int prop1 READ prop1 WRITE setProp1) - Q_PROPERTY(QList<int> complexProp READ complexProp WRITE setComplexProp) - -public: - static int callCount; - static QVariantList callArgs; - MyObject() - { - QObject *subObject = new QObject(this); - subObject->setObjectName("subObject"); - } +static const char serviceName[] = "com.trolltech.autotests.qmyserver"; +static const char objectPath[] = "/com/trolltech/qmyserver"; +static const char *interfaceName = serviceName; - int m_prop1; - int prop1() const - { - ++callCount; - return m_prop1; - } - void setProp1(int value) - { - ++callCount; - m_prop1 = value; - } - - QList<int> m_complexProp; - QList<int> complexProp() const - { - ++callCount; - return m_complexProp; - } - void setComplexProp(const QList<int> &value) - { - ++callCount; - m_complexProp = value; - } - - Q_INVOKABLE void ping_invokable(QDBusMessage msg) - { - QDBusConnection sender = QDBusConnection::sender(); - if (!sender.isConnected()) - exit(1); - - ++callCount; - callArgs = msg.arguments(); - - msg.setDelayedReply(true); - if (!sender.send(msg.createReply(callArgs))) - exit(1); - } - -public slots: - - void ping(QDBusMessage msg) - { - QDBusConnection sender = QDBusConnection::sender(); - if (!sender.isConnected()) - exit(1); - - ++callCount; - callArgs = msg.arguments(); - - msg.setDelayedReply(true); - if (!sender.send(msg.createReply(callArgs))) - exit(1); - } -}; int MyObject::callCount = 0; QVariantList MyObject::callArgs; @@ -228,10 +119,70 @@ void emitSignal(const QString &interface, const QString &name, const QString &ar QTest::qWait(1000); } +void emitSignalPeer(const QString &interface, const QString &name, const QString &arg) +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal"); + req << interface; + req << name; + req << arg; + QDBusConnection::sessionBus().send(req); + + QTest::qWait(1000); +} + +int callCountPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "callCount"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return reply.arguments().at(0).toInt(); +} + +QVariantList callArgsPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "callArgs"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return qdbus_cast<QVariantList>(reply.arguments().at(0)); +} + +void setProp1Peer(int val) +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "setProp1"); + req << val; + QDBusMessage reply = QDBusConnection::sessionBus().call(req); +} + +int prop1Peer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "prop1"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return reply.arguments().at(0).toInt(); +} + +void setComplexPropPeer(QList<int> val) +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "setComplexProp"); + req << qVariantFromValue(val); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); +} + +QList<int> complexPropPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "complexProp"); + QDBusMessage reply = QDBusConnection::sessionBus().call(req); + return qdbus_cast<QList<int> >(reply.arguments().at(0)); +} + +void resetPeer() +{ + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "reset"); + QDBusConnection::sessionBus().call(req); +} + class tst_QDBusInterface: public QObject { Q_OBJECT MyObject obj; + public slots: void testServiceOwnerChanged(const QString &service) { @@ -241,6 +192,7 @@ public slots: private slots: void initTestCase(); + void cleanupTestCase(); void notConnected(); void notValid(); @@ -254,14 +206,63 @@ private slots: void invokeMethodWithMultiReturn(); void invokeMethodWithComplexReturn(); + void introspectPeer(); + void callMethodPeer(); + void invokeMethodPeer(); + void invokeMethodWithReturnPeer(); + void invokeMethodWithMultiReturnPeer(); + void invokeMethodWithComplexReturnPeer(); + void signal(); + void signalPeer(); void propertyRead(); void propertyWrite(); void complexPropertyRead(); void complexPropertyWrite(); + + void propertyReadPeer(); + void propertyWritePeer(); + void complexPropertyReadPeer(); + void complexPropertyWritePeer(); +private: + QProcess proc; }; +class WaitForQMyServer: public QObject +{ + Q_OBJECT +public: + WaitForQMyServer(); + bool ok(); +public Q_SLOTS: + void ownerChange(const QString &name) + { + if (name == serviceName) + loop.quit(); + } + +private: + QEventLoop loop; +}; + +WaitForQMyServer::WaitForQMyServer() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + if (!ok()) { + connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), + SLOT(ownerChange(QString))); + QTimer::singleShot(2000, &loop, SLOT(quit())); + loop.exec(); + } +} + +bool WaitForQMyServer::ok() +{ + return QDBusConnection::sessionBus().isConnected() && + QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName); +} + void tst_QDBusInterface::initTestCase() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -271,6 +272,39 @@ void tst_QDBusInterface::initTestCase() con.registerObject("/", &obj, QDBusConnection::ExportAllProperties | QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllInvokables); + + // start peer server + #ifdef Q_OS_WIN + proc.start("qmyserver"); + #else + proc.start("./qmyserver/qmyserver"); + #endif + QVERIFY(proc.waitForStarted()); + + WaitForQMyServer w; + QVERIFY(w.ok()); + //QTest::qWait(2000); + + // get peer server address + QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "address"); + QDBusMessage rpl = con.call(req); + QVERIFY(rpl.type() == QDBusMessage::ReplyMessage); + QString address = rpl.arguments().at(0).toString(); + + // connect to peer server + QDBusConnection peercon = QDBusConnection::connectToPeer(address, "peer"); + QVERIFY(peercon.isConnected()); + + QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "isConnected"); + QDBusMessage rpl2 = con.call(req2); + QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage); + QVERIFY(rpl2.arguments().at(0).toBool()); +} + +void tst_QDBusInterface::cleanupTestCase() +{ + proc.close(); + proc.kill(); } void tst_QDBusInterface::notConnected() @@ -369,7 +403,7 @@ void tst_QDBusInterface::callMethod() TEST_INTERFACE_NAME); MyObject::callCount = 0; - + // call a SLOT method QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo"))); QCOMPARE(MyObject::callCount, 1); @@ -388,7 +422,7 @@ void tst_QDBusInterface::callMethod() dv = qdbus_cast<QDBusVariant>(v); QCOMPARE(dv.variant().type(), QVariant::String); QCOMPARE(dv.variant().toString(), QString("foo")); - + // call an INVOKABLE method reply = iface.call("ping_invokable", qVariantFromValue(QDBusVariant("bar"))); QCOMPARE(MyObject::callCount, 2); @@ -416,7 +450,7 @@ void tst_QDBusInterface::invokeMethod() TEST_INTERFACE_NAME); MyObject::callCount = 0; - + // make the SLOT call without a return type QDBusVariant arg("foo"); QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg))); @@ -428,7 +462,7 @@ void tst_QDBusInterface::invokeMethod() QDBusVariant dv = qdbus_cast<QDBusVariant>(v); QCOMPARE(dv.variant().type(), QVariant::String); QCOMPARE(dv.variant().toString(), QString("foo")); - + // make the INVOKABLE call without a return type QDBusVariant arg2("bar"); QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2))); @@ -465,7 +499,7 @@ void tst_QDBusInterface::invokeMethodWithReturn() // verify that we got the reply as expected QCOMPARE(retArg.variant(), arg.variant()); - + // make the INVOKABLE call without a return type QDBusVariant arg2("bar"); QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2))); @@ -490,7 +524,7 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn() MyObject::callCount = 0; QDBusVariant retArg, retArg2; - + // make the SLOT call without a return type QDBusVariant arg("foo"), arg2("bar"); QVERIFY(QMetaObject::invokeMethod(&iface, "ping", @@ -515,7 +549,7 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn() // verify that we got the replies as expected QCOMPARE(retArg.variant(), arg.variant()); QCOMPARE(retArg2.variant(), arg2.variant()); - + // make the INVOKABLE call without a return type QDBusVariant arg3("hello"), arg4("world"); QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", @@ -550,7 +584,7 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn() MyObject::callCount = 0; QList<int> retArg; - + // make the SLOT call without a return type QList<int> arg = QList<int>() << 42 << -47; QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg))); @@ -564,7 +598,7 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn() // verify that we got the reply as expected QCOMPARE(retArg, arg); - + // make the INVOKABLE call without a return type QList<int> arg2 = QList<int>() << 24 << -74; QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2))); @@ -580,6 +614,250 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn() QCOMPARE(retArg, arg2); } +void tst_QDBusInterface::introspectPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + const QMetaObject *mo = iface.metaObject(); + + QCOMPARE(mo->methodCount() - mo->methodOffset(), 7); + QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1); + + QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2); + QVERIFY(mo->indexOfProperty("prop1") != -1); + QVERIFY(mo->indexOfProperty("complexProp") != -1); +} + +void tst_QDBusInterface::callMethodPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + + // call a SLOT method + QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo"))); + QCOMPARE(callCountPeer(), 1); + QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); + + // verify what the callee received + QVariantList callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + QVariant v = callArgs.at(0); + QDBusVariant dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("foo")); + + // verify reply + QCOMPARE(reply.arguments().count(), 1); + v = reply.arguments().at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("foo")); + + // call an INVOKABLE method + reply = iface.call("ping_invokable", qVariantFromValue(QDBusVariant("bar"))); + QCOMPARE(callCountPeer(), 2); + QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); + + // verify what the callee received + callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + v = callArgs.at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("bar")); + + // verify reply + QCOMPARE(reply.arguments().count(), 1); + v = reply.arguments().at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("bar")); +} + +void tst_QDBusInterface::invokeMethodPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + + // make the SLOT call without a return type + QDBusVariant arg("foo"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg))); + QCOMPARE(callCountPeer(), 1); + + // verify what the callee received + QVariantList callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + QVariant v = callArgs.at(0); + QDBusVariant dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("foo")); + + // make the INVOKABLE call without a return type + QDBusVariant arg2("bar"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2))); + QCOMPARE(callCountPeer(), 2); + + // verify what the callee received + callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + v = callArgs.at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), QString("bar")); +} + +void tst_QDBusInterface::invokeMethodWithReturnPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + QDBusVariant retArg; + + // make the SLOT call without a return type + QDBusVariant arg("foo"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg))); + QCOMPARE(callCountPeer(), 1); + + // verify what the callee received + QVariantList callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + QVariant v = callArgs.at(0); + QDBusVariant dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg.variant().toString()); + + // verify that we got the reply as expected + QCOMPARE(retArg.variant(), arg.variant()); + + // make the INVOKABLE call without a return type + QDBusVariant arg2("bar"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2))); + QCOMPARE(callCountPeer(), 2); + + // verify what the callee received + callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + v = callArgs.at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg2.variant().toString()); + + // verify that we got the reply as expected + QCOMPARE(retArg.variant(), arg2.variant()); +} + +void tst_QDBusInterface::invokeMethodWithMultiReturnPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + QDBusVariant retArg, retArg2; + + // make the SLOT call without a return type + QDBusVariant arg("foo"), arg2("bar"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", + Q_RETURN_ARG(QDBusVariant, retArg), + Q_ARG(QDBusVariant, arg), + Q_ARG(QDBusVariant, arg2), + Q_ARG(QDBusVariant&, retArg2))); + QCOMPARE(callCountPeer(), 1); + + // verify what the callee received + QVariantList callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 2); + QVariant v = callArgs.at(0); + QDBusVariant dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg.variant().toString()); + + v = callArgs.at(1); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg2.variant().toString()); + + // verify that we got the replies as expected + QCOMPARE(retArg.variant(), arg.variant()); + QCOMPARE(retArg2.variant(), arg2.variant()); + + // make the INVOKABLE call without a return type + QDBusVariant arg3("hello"), arg4("world"); + QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", + Q_RETURN_ARG(QDBusVariant, retArg), + Q_ARG(QDBusVariant, arg3), + Q_ARG(QDBusVariant, arg4), + Q_ARG(QDBusVariant&, retArg2))); + QCOMPARE(callCountPeer(), 2); + + // verify what the callee received + callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 2); + v = callArgs.at(0); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg3.variant().toString()); + + v = callArgs.at(1); + dv = qdbus_cast<QDBusVariant>(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg4.variant().toString()); + + // verify that we got the replies as expected + QCOMPARE(retArg.variant(), arg3.variant()); + QCOMPARE(retArg2.variant(), arg4.variant()); +} + +void tst_QDBusInterface::invokeMethodWithComplexReturnPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + QList<int> retArg; + + // make the SLOT call without a return type + QList<int> arg = QList<int>() << 42 << -47; + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg))); + QCOMPARE(callCountPeer(), 1); + + // verify what the callee received + QVariantList callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + QVariant v = callArgs.at(0); + QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>()); + QCOMPARE(qdbus_cast<QList<int> >(v), arg); + + // verify that we got the reply as expected + QCOMPARE(retArg, arg); + + // make the INVOKABLE call without a return type + QList<int> arg2 = QList<int>() << 24 << -74; + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2))); + QCOMPARE(callCountPeer(), 2); + + // verify what the callee received + callArgs = callArgsPeer(); + QCOMPARE(callArgs.count(), 1); + v = callArgs.at(0); + QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>()); + QCOMPARE(qdbus_cast<QList<int> >(v), arg2); + + // verify that we got the reply as expected + QCOMPARE(retArg, arg2); +} + void tst_QDBusInterface::signal() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -621,6 +899,47 @@ void tst_QDBusInterface::signal() } } +void tst_QDBusInterface::signalPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + QString arg = "So long and thanks for all the fish"; + { + Spy spy; + spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString))); + + emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg); + QCOMPARE(spy.count, 1); + QCOMPARE(spy.received, arg); + } + + QDBusInterface iface2(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + { + Spy spy; + spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString))); + spy.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString))); + + emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg); + QCOMPARE(spy.count, 2); + QCOMPARE(spy.received, arg); + } + + { + Spy spy, spy2; + spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString))); + spy2.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString))); + + emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg); + QCOMPARE(spy.count, 1); + QCOMPARE(spy.received, arg); + QCOMPARE(spy2.count, 1); + QCOMPARE(spy2.received, arg); + } +} + void tst_QDBusInterface::propertyRead() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -683,7 +1002,69 @@ void tst_QDBusInterface::complexPropertyWrite() QCOMPARE(obj.m_complexProp, arg); } +void tst_QDBusInterface::propertyReadPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + int arg = 42; + setProp1Peer(42); + + QVariant v = iface.property("prop1"); + QVERIFY(v.isValid()); + QCOMPARE(v.userType(), int(QVariant::Int)); + QCOMPARE(v.toInt(), arg); + QCOMPARE(callCountPeer(), 1); +} + +void tst_QDBusInterface::propertyWritePeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + int arg = 42; + setProp1Peer(0); + + QVERIFY(iface.setProperty("prop1", arg)); + QCOMPARE(callCountPeer(), 1); + QCOMPARE(prop1Peer(), arg); +} + +void tst_QDBusInterface::complexPropertyReadPeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + QList<int> arg = QList<int>() << 42 << -47; + setComplexPropPeer(arg); + + QVariant v = iface.property("complexProp"); + QVERIFY(v.isValid()); + QCOMPARE(v.userType(), qMetaTypeId<QList<int> >()); + QCOMPARE(v.value<QList<int> >(), arg); + QCOMPARE(callCountPeer(), 1); +} + +void tst_QDBusInterface::complexPropertyWritePeer() +{ + QDBusConnection con("peer"); + QDBusInterface iface(QString(), QLatin1String("/"), + TEST_INTERFACE_NAME, con); + + resetPeer(); + QList<int> arg = QList<int>() << -47 << 42; + + QVERIFY(iface.setProperty("complexProp", qVariantFromValue(arg))); + QCOMPARE(callCountPeer(), 1); + QCOMPARE(complexPropPeer(), arg); +} + QTEST_MAIN(tst_QDBusInterface) #include "tst_qdbusinterface.moc" - diff --git a/tests/auto/qdbusmarshall/common.h b/tests/auto/qdbusmarshall/common.h index 532394a..8f7f3c3 100644 --- a/tests/auto/qdbusmarshall/common.h +++ b/tests/auto/qdbusmarshall/common.h @@ -39,6 +39,22 @@ ** ****************************************************************************/ #include <math.h> // isnan +#include <qvariant.h> + +#ifdef Q_OS_UNIX +# include <private/qcore_unix_p.h> + +static bool compareFileDescriptors(int fd1, int fd2) +{ + QT_STATBUF st1, st2; + if (QT_FSTAT(fd1, &st1) == -1 || QT_FSTAT(fd2, &st2) == -1) { + perror("fstat"); + return false; + } + + return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino); +} +#endif Q_DECLARE_METATYPE(QVariant) Q_DECLARE_METATYPE(QList<bool>) @@ -77,6 +93,22 @@ Q_DECLARE_METATYPE(ObjectPathStringMap) Q_DECLARE_METATYPE(LLDateTimeMap) Q_DECLARE_METATYPE(SignatureStringMap) +static bool compare(const QDBusUnixFileDescriptor &t1, const QDBusUnixFileDescriptor &t2) +{ + int fd1 = t1.fileDescriptor(); + int fd2 = t2.fileDescriptor(); + if ((fd1 == -1 || fd2 == -1) && fd1 != fd2) { + // one is valid, the other isn't + return false; + } + +#ifdef Q_OS_UNIX + return compareFileDescriptors(fd1, fd2); +#else + return true; +#endif +} + struct MyStruct { int i; @@ -130,6 +162,32 @@ const QDBusArgument &operator>>(const QDBusArgument &arg, MyVariantMapStruct &ms return arg; } +struct MyFileDescriptorStruct +{ + QDBusUnixFileDescriptor fd; + + inline bool operator==(const MyFileDescriptorStruct &other) const + { return compare(fd, other.fd); } +}; +Q_DECLARE_METATYPE(MyFileDescriptorStruct) +Q_DECLARE_METATYPE(QList<MyFileDescriptorStruct>) + +QDBusArgument &operator<<(QDBusArgument &arg, const MyFileDescriptorStruct &ms) +{ + arg.beginStructure(); + arg << ms.fd; + arg.endStructure(); + return arg; +} + +const QDBusArgument &operator>>(const QDBusArgument &arg, MyFileDescriptorStruct &ms) +{ + arg.beginStructure(); + arg >> ms.fd; + arg.endStructure(); + return arg; +} + void commonInit() { @@ -157,6 +215,8 @@ void commonInit() qDBusRegisterMetaType<MyStruct>(); qDBusRegisterMetaType<MyVariantMapStruct>(); qDBusRegisterMetaType<QList<MyVariantMapStruct> >(); + qDBusRegisterMetaType<MyFileDescriptorStruct>(); + qDBusRegisterMetaType<QList<MyFileDescriptorStruct> >(); } #ifdef USE_PRIVATE_CODE #include "private/qdbusintrospection_p.h" @@ -467,6 +527,8 @@ bool compareToArgument(const QDBusArgument &arg, const QVariant &v2) return compare<QList<QDBusObjectPath> >(arg, v2); else if (id == qMetaTypeId<QList<QDBusSignature> >()) return compare<QList<QDBusSignature> >(arg, v2); + else if (id == qMetaTypeId<QList<QDBusUnixFileDescriptor> >()) + return compare<QList<QDBusUnixFileDescriptor> >(arg, v2); else if (id == qMetaTypeId<QList<QDateTime> >()) return compare<QList<QDateTime> >(arg, v2); @@ -511,6 +573,10 @@ bool compareToArgument(const QDBusArgument &arg, const QVariant &v2) return compare<MyVariantMapStruct>(arg, v2); else if (id == qMetaTypeId<QList<MyVariantMapStruct> >()) return compare<QList<MyVariantMapStruct> >(arg, v2); + else if (id == qMetaTypeId<MyFileDescriptorStruct>()) + return compare<MyFileDescriptorStruct>(arg, v2); + else if (id == qMetaTypeId<QList<MyFileDescriptorStruct> >()) + return compare<QList<MyFileDescriptorStruct> >(arg, v2); } qWarning() << "Unexpected QVariant type" << v2.userType() @@ -563,6 +629,9 @@ template<> bool compare(const QVariant &v1, const QVariant &v2) else if (id == qMetaTypeId<QDBusSignature>()) return qvariant_cast<QDBusSignature>(v1).signature() == qvariant_cast<QDBusSignature>(v2).signature(); + else if (id == qMetaTypeId<QDBusUnixFileDescriptor>()) + return compare(qvariant_cast<QDBusUnixFileDescriptor>(v1), qvariant_cast<QDBusUnixFileDescriptor>(v2)); + else if (id == qMetaTypeId<QDBusVariant>()) return compare(qvariant_cast<QDBusVariant>(v1).variant(), qvariant_cast<QDBusVariant>(v2).variant()); diff --git a/tests/auto/qdbusmarshall/qdbusmarshall.pro b/tests/auto/qdbusmarshall/qdbusmarshall.pro index f8e0875..ad40c0d 100644 --- a/tests/auto/qdbusmarshall/qdbusmarshall.pro +++ b/tests/auto/qdbusmarshall/qdbusmarshall.pro @@ -3,6 +3,8 @@ contains(QT_CONFIG,dbus): { TEMPLATE = subdirs CONFIG += ordered SUBDIRS = qpong test + + requires(contains(QT_CONFIG,private_tests)) } else { SOURCES += dummy.cpp } diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index 9bae6af..737f0cf 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -42,6 +42,7 @@ #include <QtTest/QtTest> #include <QtDBus/QtDBus> #include <QtDBus/private/qdbusutil_p.h> +#include <QtDBus/private/qdbusconnection_p.h> #include "common.h" #include <limits> @@ -93,7 +94,11 @@ private slots: void receiveUnknownType(); private: + int fileDescriptorForTest(); + QProcess proc; + QTemporaryFile tempFile; + bool fileDescriptorPassing; }; class QDBusMessageSpy: public QObject @@ -116,6 +121,7 @@ void tst_QDBusMarshall::initTestCase() { commonInit(); QDBusConnection con = QDBusConnection::sessionBus(); + fileDescriptorPassing = con.connectionCapabilities() & QDBusConnection::UnixFileDescriptorPassing; #ifdef Q_OS_WIN proc.start("qpong"); #else @@ -144,6 +150,15 @@ void tst_QDBusMarshall::cleanupTestCase() proc.waitForFinished(200); } +int tst_QDBusMarshall::fileDescriptorForTest() +{ + if (!tempFile.isOpen()) { + tempFile.setFileTemplate(QDir::tempPath() + "/qdbusmarshalltestXXXXXX.tmp"); + tempFile.open(); + } + return tempFile.handle(); +} + void tst_QDBusMarshall::sendBasic_data() { QTest::addColumn<QVariant>("value"); @@ -167,6 +182,9 @@ void tst_QDBusMarshall::sendBasic_data() QTest::newRow("signature") << qVariantFromValue(QDBusSignature("g")) << "g" << "[Signature: g]"; QTest::newRow("emptystring") << QVariant("") << "s" << "\"\""; QTest::newRow("nullstring") << QVariant(QString()) << "s" << "\"\""; + + if (fileDescriptorPassing) + QTest::newRow("file-descriptor") << qVariantFromValue(QDBusUnixFileDescriptor(fileDescriptorForTest())) << "h" << "[Unix FD: valid]"; #endif } @@ -255,6 +273,18 @@ void tst_QDBusMarshall::sendArrays_data() << std::numeric_limits<double>::quiet_NaN(); QTest::newRow("doublelist") << qVariantFromValue(doubles) << "ad" << "[Argument: ad {1.2, 2.2, 4.4, -inf, inf, nan}]"; + QList<QDBusObjectPath> objectPaths; + QTest::newRow("emptyobjectpathlist") << qVariantFromValue(objectPaths) << "ao" << "[Argument: ao {}]"; + objectPaths << QDBusObjectPath("/") << QDBusObjectPath("/foo"); + QTest::newRow("objectpathlist") << qVariantFromValue(objectPaths) << "ao" << "[Argument: ao {[ObjectPath: /], [ObjectPath: /foo]}]"; + + if (fileDescriptorPassing) { + QList<QDBusUnixFileDescriptor> fileDescriptors; + QTest::newRow("emptyfiledescriptorlist") << qVariantFromValue(fileDescriptors) << "ah" << "[Argument: ah {}]"; + fileDescriptors << QDBusUnixFileDescriptor(fileDescriptorForTest()) << QDBusUnixFileDescriptor(1); + QTest::newRow("filedescriptorlist") << qVariantFromValue(fileDescriptors) << "ah" << "[Argument: ah {[Unix FD: valid], [Unix FD: valid]}]"; + } + QVariantList variants; QTest::newRow("emptyvariantlist") << QVariant(variants) << "av" << "[Argument: av {}]"; variants << QString("Hello") << QByteArray("World") << 42 << -43.0 << 44U << Q_INT64_C(-45) @@ -456,6 +486,12 @@ void tst_QDBusMarshall::sendMaps_data() QTest::newRow("gs-map") << qVariantFromValue(gsmap) << "a{gs}" << "[Argument: a{gs} {[Signature: a{gs}] = \"array of dict_entry of (signature, string)\", [Signature: i] = \"int32\", [Signature: s] = \"string\"}]"; + if (fileDescriptorPassing) { + svmap["zzfiledescriptor"] = qVariantFromValue(QDBusUnixFileDescriptor(fileDescriptorForTest())); + QTest::newRow("sv-map1-fd") << qVariantFromValue(svmap) << "a{sv}" + << "[Argument: a{sv} {\"a\" = [Variant(int): 1], \"b\" = [Variant(QByteArray): {99}], \"c\" = [Variant(QString): \"b\"], \"d\" = [Variant(uint): 42], \"e\" = [Variant(short): -47], \"f\" = [Variant: [Variant(int): 0]], \"zzfiledescriptor\" = [Variant(QDBusUnixFileDescriptor): [Unix FD: valid]]}]"; + } + svmap.clear(); svmap["ismap"] = qVariantFromValue(ismap); svmap["ssmap"] = qVariantFromValue(ssmap); @@ -509,6 +545,18 @@ void tst_QDBusMarshall::sendStructs_data() QTest::newRow("empty-list-of-string-variantmap") << qVariantFromValue(list) << "a(sa{sv})" << "[Argument: a(sa{sv}) {}]"; list << mvms; QTest::newRow("list-of-string-variantmap") << qVariantFromValue(list) << "a(sa{sv})" << "[Argument: a(sa{sv}) {[Argument: (sa{sv}) \"Hello, World\", [Argument: a{sv} {\"bytearray\" = [Variant(QByteArray): {72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100}], \"int\" = [Variant(int): 42], \"short\" = [Variant(short): -47], \"uint\" = [Variant(uint): 42]}]]}]"; + + if (fileDescriptorPassing) { + MyFileDescriptorStruct fds; + fds.fd = QDBusUnixFileDescriptor(fileDescriptorForTest()); + QTest::newRow("fdstruct") << qVariantFromValue(fds) << "(h)" << "[Argument: (h) [Unix FD: valid]]"; + + QList<MyFileDescriptorStruct> fdlist; + QTest::newRow("empty-list-of-fdstruct") << qVariantFromValue(fdlist) << "a(h)" << "[Argument: a(h) {}]"; + + fdlist << fds; + QTest::newRow("list-of-fdstruct") << qVariantFromValue(fdlist) << "a(h)" << "[Argument: a(h) {[Argument: (h) [Unix FD: valid]]}]"; + } } void tst_QDBusMarshall::sendComplex_data() @@ -642,6 +690,12 @@ void tst_QDBusMarshall::sendArgument_data() arg << QString(); QTest::newRow("nullstring") << qVariantFromValue(arg) << "s" << int(QDBusArgument::BasicType); + if (fileDescriptorPassing) { + arg = QDBusArgument(); + arg << QDBusUnixFileDescriptor(fileDescriptorForTest()); + QTest::newRow("filedescriptor") << qVariantFromValue(arg) << "h" << int(QDBusArgument::BasicType); + } + arg = QDBusArgument(); arg << QDBusVariant(1); QTest::newRow("variant") << qVariantFromValue(arg) << "v" << int(QDBusArgument::VariantType); @@ -902,6 +956,27 @@ void tst_QDBusMarshall::sendCallErrors_data() << "Marshalling failed: Unregistered type UnregisteredType passed in arguments" << QString("QDBusMarshaller: type `UnregisteredType' (%1) is not registered with D-BUS. Use qDBusRegisterMetaType to register it") .arg(qMetaTypeId<UnregisteredType>()); + + QTest::newRow("invalid-object-path-arg") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusObjectPath())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid object path passed in arguments" + << ""; + + QTest::newRow("invalid-signature-arg") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusSignature())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid signature passed in arguments" + << ""; + + // invalid file descriptor + if (fileDescriptorPassing) { + QTest::newRow("invalid-file-descriptor") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusUnixFileDescriptor(-1))) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Invalid file descriptor passed in arguments" + << ""; + } } void tst_QDBusMarshall::sendCallErrors() @@ -967,6 +1042,21 @@ typedef QScopedPointer<DBusConnection, DisconnectRawDBus> ScopedDBusConnection; typedef QScopedPointer<DBusMessage, GenericUnref<DBusMessage, dbus_message_unref> > ScopedDBusMessage; typedef QScopedPointer<DBusPendingCall, GenericUnref<DBusPendingCall, dbus_pending_call_unref> > ScopedDBusPendingCall; +template <typename T> struct SetResetValue +{ + const T oldValue; + T &value; +public: + SetResetValue(T &v, T newValue) : oldValue(v), value(v) + { + value = newValue; + } + ~SetResetValue() + { + value = oldValue; + } +}; + void tst_QDBusMarshall::receiveUnknownType() { #ifndef DBUS_TYPE_UNIX_FD @@ -986,6 +1076,10 @@ void tst_QDBusMarshall::receiveUnknownType() if (!dbus_connection_can_send_type(rawcon.data(), DBUS_TYPE_UNIX_FD)) QSKIP("Your session bus does not allow sending Unix file descriptors", SkipAll); + // make sure this QDBusConnection won't handle Unix file descriptors + QDBusConnection::ConnectionCapabilities &capabRef = QDBusConnectionPrivate::d(con)->capabilities; + SetResetValue<QDBusConnection::ConnectionCapabilities> resetter(capabRef, capabRef & ~QDBusConnection::UnixFileDescriptorPassing); + if (qstrcmp(QTest::currentDataTag(), "in-call") == 0) { // create a call back to us containing a file descriptor QDBusMessageSpy spy; diff --git a/tests/auto/qdbusperformance/.gitignore b/tests/auto/qdbusperformance/.gitignore deleted file mode 100644 index 4cd8399..0000000 --- a/tests/auto/qdbusperformance/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tst_qdbusperformance -server/server diff --git a/tests/auto/qdbusperformance/qdbusperformance.pro b/tests/auto/qdbusperformance/qdbusperformance.pro deleted file mode 100644 index 6880518..0000000 --- a/tests/auto/qdbusperformance/qdbusperformance.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,dbus): { - TEMPLATE = subdirs - CONFIG += ordered - SUBDIRS = server test -} else { - SOURCES += ../qdbusmarshall/dummy.cpp -} diff --git a/tests/auto/qdbusperformance/server/server.pro b/tests/auto/qdbusperformance/server/server.pro deleted file mode 100644 index 30f81dd..0000000 --- a/tests/auto/qdbusperformance/server/server.pro +++ /dev/null @@ -1,5 +0,0 @@ -SOURCES = server.cpp -HEADERS = ../serverobject.h -TARGET = server -CONFIG += qdbus -QT -= gui diff --git a/tests/auto/qdbusperformance/serverobject.h b/tests/auto/qdbusperformance/serverobject.h deleted file mode 100644 index 6f85bb4..0000000 --- a/tests/auto/qdbusperformance/serverobject.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef SERVEROBJECT_H -#define SERVEROBJECT_H - -#include <QObject> -#include <QtDBus/QtDBus> - -class ServerObject: public QObject -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.Performance") -public: - ServerObject(const QString &objectPath, QDBusConnection conn, QObject *parent = 0) - : QObject(parent) - { - conn.registerObject(objectPath, this, QDBusConnection::ExportAllSlots); - } - -public slots: - Q_NOREPLY void noReply(const QByteArray &) - { - // black hole - } - Q_NOREPLY void noReply(const QString &) - { - // black hole - } - Q_NOREPLY void noReply(const QDBusVariant &) - { - // black hole - } - - int size(const QByteArray &data) - { - return data.size(); - } - int size(const QString &data) - { - return data.size(); - } - int size(const QDBusVariant &data) - { - QVariant v = data.variant(); - switch (v.type()) - { - case QVariant::ByteArray: - return v.toByteArray().size(); - case QVariant::StringList: - return v.toStringList().size(); - case QVariant::String: - default: - return v.toString().size(); - } - } - - QByteArray echo(const QByteArray &data) - { - return data; - } - QString echo(const QString &data) - { - return data; - } - QDBusVariant echo(const QDBusVariant &data) - { - return data; - } - - void nothing() - { - } -}; - -#endif diff --git a/tests/auto/qdbusperformance/test/test.pro b/tests/auto/qdbusperformance/test/test.pro deleted file mode 100644 index 9f5712e..0000000 --- a/tests/auto/qdbusperformance/test/test.pro +++ /dev/null @@ -1,7 +0,0 @@ -load(qttest_p4) -SOURCES += ../tst_qdbusperformance.cpp -HEADERS += ../serverobject.h -TARGET = ../tst_qdbusperformance - -QT = core -CONFIG += qdbus diff --git a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp b/tests/auto/qdbusperformance/tst_qdbusperformance.cpp deleted file mode 100644 index a5b4b98..0000000 --- a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <QtCore/QtCore> -#include <QtTest/QtTest> -#include <QtDBus/QtDBus> - -#include "./serverobject.h" - -static const char serviceName[] = "com.trolltech.autotests.performance"; -static const int runTime = 500; - -class tst_QDBusPerformance: public QObject -{ - Q_OBJECT - QProcess proc; - QDBusInterface *target; - - QDBusInterface *remote; - QDBusInterface *local; - - bool executeTest(const char *funcname, int size, const QVariant &data); - -public slots: - void initTestCase_data(); - void initTestCase(); - void init(); - -private slots: - void callSpeed(); - - void oneWay_data(); - void oneWay(); - void oneWayVariant_data(); - void oneWayVariant(); - - void roundTrip_data(); - void roundTrip(); - void roundTripVariant_data(); - void roundTripVariant(); -}; -Q_DECLARE_METATYPE(QVariant) - -void tst_QDBusPerformance::initTestCase() -{ - QDBusConnection con = QDBusConnection::sessionBus(); - QVERIFY(con.isConnected()); - - QDBusServiceWatcher watcher(serviceName, con, - QDBusServiceWatcher::WatchForRegistration); - connect(&watcher, SIGNAL(serviceRegistered(QString)), - &QTestEventLoop::instance(), SLOT(exitLoop())); - -#ifdef Q_OS_WIN - proc.start("server"); -#else - proc.start("./server/server"); -#endif - QVERIFY(proc.waitForStarted()); - - QTestEventLoop::instance().enterLoop(5); - QVERIFY(con.interface()->isServiceRegistered(serviceName)); - - remote = new QDBusInterface(serviceName, "/", "com.trolltech.autotests.Performance", con, this); - QVERIFY(remote->isValid()); - - new ServerObject("/", con, this); - local = new QDBusInterface(con.baseService(), "/", "com.trolltech.autotests.Performance", con, this); - QVERIFY(local->isValid()); -} - -void tst_QDBusPerformance::initTestCase_data() -{ - QTest::addColumn<bool>("loopback"); - - QTest::newRow("normal") << false; - QTest::newRow("loopback") << true; -} - -void tst_QDBusPerformance::init() -{ - QFETCH_GLOBAL(bool, loopback); - if (loopback) - target = local; - else - target = remote; -} - -void tst_QDBusPerformance::callSpeed() -{ - QElapsedTimer timer; - - int callCount = 0; - timer.start(); - while (timer.elapsed() < runTime) { - QDBusReply<void> reply = target->call("nothing"); - QVERIFY(reply.isValid()); - - ++callCount; - } - qDebug() << callCount << "calls in" << timer.elapsed() << "ms:" - << (callCount * 1000.0 / timer.elapsed()) << "calls/sec"; -} - -bool tst_QDBusPerformance::executeTest(const char *funcname, int size, const QVariant &data) -{ - QElapsedTimer timer; - - int callCount = 0; - qint64 transferred = 0; - timer.start(); - while (timer.elapsed() < runTime) { - QDBusMessage reply = target->call(funcname, data); - if (reply.type() != QDBusMessage::ReplyMessage) - return false; - - transferred += size; - ++callCount; - } - qDebug() << transferred << "bytes in" << timer.elapsed() << "ms" - << "(in" << callCount << "calls):" - << (transferred * 1000.0 / timer.elapsed() / 1024 / 1024) << "MB/s"; - - return true; -} - -void tst_QDBusPerformance::oneWay_data() -{ - QTest::addColumn<QVariant>("data"); - QTest::addColumn<int>("size"); - - QByteArray ba(256, 'a'); - while (ba.size() < 8193) { - QTest::newRow(QString("%1-byteArray").arg(ba.size()).toAscii()) << qVariantFromValue(ba) << ba.size(); - ba += ba; - } - - QString s(256, QLatin1Char('a')); - while (s.size() < 8193) { - QTest::newRow(QString("%1-string").arg(s.size()).toAscii()) << qVariantFromValue(s) << s.size(); - s += s; - } -} - -void tst_QDBusPerformance::oneWay() -{ - QFETCH(QVariant, data); - QFETCH(int, size); - - QVERIFY(executeTest("size", size, data)); -} - -void tst_QDBusPerformance::oneWayVariant_data() -{ - oneWay_data(); -} - -void tst_QDBusPerformance::oneWayVariant() -{ - QFETCH(QVariant, data); - QFETCH(int, size); - - QVERIFY(executeTest("size", size, qVariantFromValue(QDBusVariant(data)))); -} - -void tst_QDBusPerformance::roundTrip_data() -{ - oneWay_data(); -} - -void tst_QDBusPerformance::roundTrip() -{ - QFETCH(QVariant, data); - QFETCH(int, size); - - QVERIFY(executeTest("echo", size, data)); -} - -void tst_QDBusPerformance::roundTripVariant_data() -{ - oneWay_data(); -} - -void tst_QDBusPerformance::roundTripVariant() -{ - QFETCH(QVariant, data); - QFETCH(int, size); - - QVERIFY(executeTest("echo", size, qVariantFromValue(QDBusVariant(data)))); -} - -QTEST_MAIN(tst_QDBusPerformance) -#include "tst_qdbusperformance.moc" diff --git a/tests/auto/qdbustype/qdbustype.pro b/tests/auto/qdbustype/qdbustype.pro new file mode 100644 index 0000000..e2f0c90 --- /dev/null +++ b/tests/auto/qdbustype/qdbustype.pro @@ -0,0 +1,10 @@ +load(qttest_p4) +QT = core +contains(QT_CONFIG,dbus): { + SOURCES += tst_qdbustype.cpp + QT += dbus + QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS + LIBS_PRIVATE += $$QT_LIBS_DBUS +} else { + SOURCES += ../qdbusmarshall/dummy.cpp +} diff --git a/tests/auto/qdbustype/tst_qdbustype.cpp b/tests/auto/qdbustype/tst_qdbustype.cpp new file mode 100644 index 0000000..676a904 --- /dev/null +++ b/tests/auto/qdbustype/tst_qdbustype.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QtCore/QCoreApplication> + +#include <QtDBus/private/qdbusutil_p.h> + +#include <dbus/dbus.h> + +class tst_QDBusType : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void isValidFixedType_data(); + void isValidFixedType(); + void isValidBasicType_data(); + void isValidBasicType(); + void isValidSingleSignature_data(); + void isValidSingleSignature(); + void isValidArray_data(); + void isValidArray(); + void isValidSignature_data(); + void isValidSignature(); +}; + +enum { Invalid = false, Valid = true }; + +static void addColumns() +{ + // All tests use these two columns only + QTest::addColumn<QString>("data"); + QTest::addColumn<bool>("result"); + QTest::addColumn<bool>("isValid"); +} + +// ---- type adds --- +static void addFixedTypes() +{ + QTest::newRow("bool") << DBUS_TYPE_BOOLEAN_AS_STRING << true << true; + QTest::newRow("byte") << DBUS_TYPE_BYTE_AS_STRING << true << true; + QTest::newRow("int16") << DBUS_TYPE_INT16_AS_STRING << true << true; + QTest::newRow("uint16") << DBUS_TYPE_UINT16_AS_STRING << true << true; + QTest::newRow("int32") << DBUS_TYPE_INT32_AS_STRING << true << true; + QTest::newRow("uint32") << DBUS_TYPE_UINT32_AS_STRING << true << true; + QTest::newRow("int64") << DBUS_TYPE_INT64_AS_STRING << true << true; + QTest::newRow("uint64") << DBUS_TYPE_UINT64_AS_STRING << true << true; + QTest::newRow("double") << DBUS_TYPE_DOUBLE_AS_STRING << true << true; +#ifdef DBUS_TYPE_UNIX_FD_AS_STRING + QTest::newRow("unixfd") << DBUS_TYPE_UNIX_FD_AS_STRING << true << true; +#endif +} + +static void addInvalidSingleLetterTypes() +{ + QChar nulString[] = { 0 }; + QTest::newRow("nul") << QString(nulString, 1) << false << false; + QTest::newRow("tilde") << "~" << false << false; + QTest::newRow("struct-begin") << "(" << false << false; + QTest::newRow("struct-end") << ")" << false << false; + QTest::newRow("dict-entry-begin") << "{" << false << false; + QTest::newRow("dict-entry-end") << "}" << false << false; + QTest::newRow("array-no-element") << "a" << false << false; +} + +static void addBasicTypes(bool basicsAreValid) +{ + addFixedTypes(); + QTest::newRow("string") << DBUS_TYPE_STRING_AS_STRING << basicsAreValid << true; + QTest::newRow("object-path") << DBUS_TYPE_OBJECT_PATH_AS_STRING << basicsAreValid << true; + QTest::newRow("signature") << DBUS_TYPE_SIGNATURE_AS_STRING << basicsAreValid << true; +} + +static void addVariant(bool variantIsValid) +{ + QTest::newRow("variant") << "v" << variantIsValid << true; +} + +static void addSingleSignatures() +{ + addBasicTypes(Valid); + addVariant(Valid); + QTest::newRow("struct-1") << "(y)" << true; + QTest::newRow("struct-2") << "(yy)" << true; + QTest::newRow("struct-3") << "(yyv)" << true; + + QTest::newRow("struct-nested-1") << "((y))" << true; + QTest::newRow("struct-nested-2") << "((yy))" << true; + QTest::newRow("struct-nested-3") << "(y(y))" << true; + QTest::newRow("struct-nested-4") << "((y)y)" << true; + QTest::newRow("struct-nested-5") << "(y(y)y)" << true; + QTest::newRow("struct-nested-6") << "((y)(y))" << true; + + QTest::newRow("array-1") << "as" << true; + QTest::newRow("struct-array-1") << "(as)" << true; + QTest::newRow("struct-array-2") << "(yas)" << true; + QTest::newRow("struct-array-3") << "(asy)" << true; + QTest::newRow("struct-array-4") << "(yasy)" << true; + + QTest::newRow("dict-1") << "a{sy}" << true; + QTest::newRow("dict-2") << "a{sv}" << true; + QTest::newRow("dict-struct-1") << "a{s(y)}" << true; + QTest::newRow("dict-struct-2") << "a{s(yyyy)}" << true; + QTest::newRow("dict-struct-array") << "a{s(ay)}" << true; + QTest::newRow("dict-array") << "a{sas}" << true; + QTest::newRow("dict-array-struct") << "a{sa(y)}" << true; + + addInvalidSingleLetterTypes(); + QTest::newRow("naked-dict-empty") << "{}" << false; + QTest::newRow("naked-dict-missing-value") << "{i}" << false; + + QTest::newRow("dict-empty") << "a{}" << false; + QTest::newRow("dict-missing-value") << "a{i}" << false; + QTest::newRow("dict-non-basic-key") << "a{vi}" << false; + QTest::newRow("dict-struct-key") << "a{(y)y}" << false; + QTest::newRow("dict-missing-close") << "a{sv" << false; + QTest::newRow("dict-mismatched-close") << "a{sv)" << false; + QTest::newRow("dict-missing-value-close") << "a{s" << false; + + QTest::newRow("empty-struct") << "()" << false; + QTest::newRow("struct-missing-close") << "(s" << false; + QTest::newRow("struct-nested-missing-close-1") << "((s)" << false; + QTest::newRow("struct-nested-missing-close-2") << "((s" << false; + + QTest::newRow("struct-ending-array-no-element") << "(a)" << false; +} + +static void addNakedDictEntry() +{ + QTest::newRow("naked-dict-entry") << "{sv}" << false; +} + +// ---- tests ---- + +void tst_QDBusType::isValidFixedType_data() +{ + addColumns(); + addFixedTypes(); + addBasicTypes(Invalid); + addVariant(Invalid); + addInvalidSingleLetterTypes(); +} + +void tst_QDBusType::isValidFixedType() +{ + QFETCH(QString, data); + QFETCH(bool, result); + QFETCH(bool, isValid); + Q_ASSERT_X(data.length() == 1, "tst_QDBusType", "Test is malformed, this function must test only one-letter types"); + Q_ASSERT(isValid || (!isValid && !result)); + + int type = data.at(0).unicode(); + if (isValid) + QCOMPARE(bool(dbus_type_is_fixed(type)), result); + QCOMPARE(QDBusUtil::isValidFixedType(type), result); +} + +void tst_QDBusType::isValidBasicType_data() +{ + addColumns(); + addBasicTypes(Valid); + addVariant(Invalid); + addInvalidSingleLetterTypes(); +} + +void tst_QDBusType::isValidBasicType() +{ + QFETCH(QString, data); + QFETCH(bool, result); + QFETCH(bool, isValid); + Q_ASSERT_X(data.length() == 1, "tst_QDBusType", "Test is malformed, this function must test only one-letter types"); + Q_ASSERT(isValid || (!isValid && !result)); + + int type = data.at(0).unicode(); + if (isValid) + QCOMPARE(bool(dbus_type_is_basic(type)), result); + QCOMPARE(QDBusUtil::isValidBasicType(type), result); +} + +void tst_QDBusType::isValidSingleSignature_data() +{ + addColumns(); + addSingleSignatures(); + addNakedDictEntry(); +} + +void tst_QDBusType::isValidSingleSignature() +{ + QFETCH(QString, data); + QFETCH(bool, result); + + QCOMPARE(bool(dbus_signature_validate_single(data.toLatin1(), 0)), result); + QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); +} + +void tst_QDBusType::isValidArray_data() +{ + addColumns(); + addSingleSignatures(); +} + +void tst_QDBusType::isValidArray() +{ + QFETCH(QString, data); + QFETCH(bool, result); + + data.prepend("a"); + QCOMPARE(bool(dbus_signature_validate_single(data.toLatin1(), 0)), result); + QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); + + data.prepend("a"); + QCOMPARE(bool(dbus_signature_validate_single(data.toLatin1(), 0)), result); + QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); +} + +void tst_QDBusType::isValidSignature_data() +{ + isValidSingleSignature_data(); +} + +void tst_QDBusType::isValidSignature() +{ + QFETCH(QString, data); + QFETCH(bool, result); + + data.append(data); + if (data.at(0).unicode()) + QCOMPARE(bool(dbus_signature_validate(data.toLatin1(), 0)), result); + QCOMPARE(QDBusUtil::isValidSignature(data), result); +} + +QTEST_MAIN(tst_QDBusType) + +#include "tst_qdbustype.moc" diff --git a/tests/auto/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp index 327b6f3..f10d35b 100644 --- a/tests/auto/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp @@ -42,10 +42,6 @@ #include <QtTest/QtTest> -#if QT_VERSION < 0x040200 -QTEST_NOOP_MAIN -#else - #include <qeasingcurve.h> //TESTED_CLASS= @@ -578,5 +574,3 @@ void tst_QEasingCurve::metaTypes() QTEST_MAIN(tst_QEasingCurve) #include "tst_qeasingcurve.moc" - -#endif //QT_VERSION diff --git a/tests/auto/qglyphs/tst_qglyphs.cpp b/tests/auto/qglyphs/tst_qglyphs.cpp index 1c0aa9e..ffa0d00 100644 --- a/tests/auto/qglyphs/tst_qglyphs.cpp +++ b/tests/auto/qglyphs/tst_qglyphs.cpp @@ -52,6 +52,7 @@ class tst_QGlyphs: public QObject { Q_OBJECT +#if !defined(QT_NO_RAWFONT) private slots: void initTestCase(); void cleanupTestCase(); @@ -75,8 +76,12 @@ private slots: private: int m_testFontId; QFont m_testFont; +#endif // QT_NO_RAWFONT + }; +#if !defined(QT_NO_RAWFONT) + Q_DECLARE_METATYPE(QGlyphs); void tst_QGlyphs::initTestCase() @@ -116,7 +121,7 @@ static QGlyphs make_dummy_indexes() positions.append(QPointF(3, 4)); positions.append(QPointF(5, 6)); - glyphs.setFont(font); + glyphs.setFont(QRawFont::fromFont(font)); glyphs.setGlyphIndexes(glyphIndexes); glyphs.setPositions(positions); @@ -141,7 +146,7 @@ void tst_QGlyphs::copyConstructor() positions.append(QPointF(3, 4)); positions.append(QPointF(5, 6)); - glyphs.setFont(font); + glyphs.setFont(QRawFont::fromFont(font)); glyphs.setGlyphIndexes(glyphIndexes); glyphs.setPositions(positions); } @@ -180,14 +185,16 @@ void tst_QGlyphs::equalsOperator_data() positions[2] += QPointF(1, 1); busted.setPositions(positions); + QTest::newRow("Different positions") << one << busted << false; } { QGlyphs busted(two); - QFont font = busted.font(); - font.setPointSize(font.pointSize() * 2); - busted.setFont(font); + + QFont font; + font.setPixelSize(busted.font().pixelSize() * 2); + busted.setFont(QRawFont::fromFont(font)); QTest::newRow("Different fonts") << one << busted << false; } @@ -288,7 +295,7 @@ void tst_QGlyphs::drawNonExistentGlyphs() QGlyphs glyphs; glyphs.setGlyphIndexes(glyphIndexes); glyphs.setPositions(glyphPositions); - glyphs.setFont(m_testFont); + glyphs.setFont(QRawFont::fromFont(m_testFont)); QPixmap image(1000, 1000); image.fill(Qt::white); @@ -568,6 +575,8 @@ void tst_QGlyphs::drawRightToLeft() } +#endif // QT_NO_RAWFONT + QTEST_MAIN(tst_QGlyphs) #include "tst_qglyphs.moc" diff --git a/tests/auto/qrawfont/qrawfont.pro b/tests/auto/qrawfont/qrawfont.pro new file mode 100644 index 0000000..ccdccfb --- /dev/null +++ b/tests/auto/qrawfont/qrawfont.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +QT = core gui + +SOURCES += \ + tst_qrawfont.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src + +wince*|symbian*: { + DEFINES += SRCDIR=\\\"\\\" +} else { + DEFINES += SRCDIR=\\\"$$PWD/\\\" +} diff --git a/tests/auto/qrawfont/testfont.ttf b/tests/auto/qrawfont/testfont.ttf Binary files differnew file mode 100644 index 0000000..d6042d2 --- /dev/null +++ b/tests/auto/qrawfont/testfont.ttf diff --git a/tests/auto/qrawfont/testfont_bold_italic.ttf b/tests/auto/qrawfont/testfont_bold_italic.ttf Binary files differnew file mode 100644 index 0000000..9f65ac8 --- /dev/null +++ b/tests/auto/qrawfont/testfont_bold_italic.ttf diff --git a/tests/auto/qrawfont/tst_qrawfont.cpp b/tests/auto/qrawfont/tst_qrawfont.cpp new file mode 100644 index 0000000..3aa4006 --- /dev/null +++ b/tests/auto/qrawfont/tst_qrawfont.cpp @@ -0,0 +1,814 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <qrawfont.h> +#include <private/qrawfont_p.h> + +class tst_QRawFont: public QObject +{ + Q_OBJECT + +#if !defined(QT_NO_RAWFONT) +private slots: + void invalidRawFont(); + + void explicitRawFontNotLoadedInDatabase_data(); + void explicitRawFontNotLoadedInDatabase(); + + void explicitRawFontNotAvailableInSystem_data(); + void explicitRawFontNotAvailableInSystem(); + + void correctFontData_data(); + void correctFontData(); + + void glyphIndices(); + + void advances_data(); + void advances(); + + void textLayout(); + + void fontTable_data(); + void fontTable(); + + void supportedWritingSystems_data(); + void supportedWritingSystems(); + + void supportsCharacter_data(); + void supportsCharacter(); + + void supportsUcs4Character_data(); + void supportsUcs4Character(); + + void fromFont_data(); + void fromFont(); + + void copyConstructor_data(); + void copyConstructor(); + + void detach_data(); + void detach(); + + void unsupportedWritingSystem_data(); + void unsupportedWritingSystem(); +#endif // QT_NO_RAWFONT +}; + +#if !defined(QT_NO_RAWFONT) +Q_DECLARE_METATYPE(QFont::HintingPreference) +Q_DECLARE_METATYPE(QFont::Style) +Q_DECLARE_METATYPE(QFont::Weight) +Q_DECLARE_METATYPE(QFontDatabase::WritingSystem) + +void tst_QRawFont::invalidRawFont() +{ + QRawFont font; + QVERIFY(!font.isValid()); + QCOMPARE(font.pixelSize(), -1); + QVERIFY(font.familyName().isEmpty()); + QCOMPARE(font.style(), QFont::StyleNormal); + QCOMPARE(font.weight(), -1); + QCOMPARE(font.ascent(), 0.0); + QCOMPARE(font.descent(), 0.0); + QVERIFY(font.glyphIndexesForString(QLatin1String("Test")).isEmpty()); +} + +void tst_QRawFont::explicitRawFontNotLoadedInDatabase_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting") << QFont::PreferFullHinting; +} + +void tst_QRawFont::explicitRawFontNotLoadedInDatabase() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference); + QVERIFY(font.isValid()); + + QVERIFY(!QFontDatabase().families().contains(font.familyName())); +} + +void tst_QRawFont::explicitRawFontNotAvailableInSystem_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting") << QFont::PreferFullHinting; +} + +void tst_QRawFont::explicitRawFontNotAvailableInSystem() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + QRawFont rawfont(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference); + + { + QFont font(rawfont.familyName(), 10); + + QVERIFY(!font.exactMatch()); + QVERIFY(font.family() != QFontInfo(font).family()); + } +} + +void tst_QRawFont::correctFontData_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QString>("expectedFamilyName"); + QTest::addColumn<QFont::Style>("style"); + QTest::addColumn<QFont::Weight>("weight"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + QTest::addColumn<qreal>("unitsPerEm"); + QTest::addColumn<int>("pixelSize"); + + int hintingPreferences[] = { + int(QFont::PreferDefaultHinting), + int(QFont::PreferNoHinting), + int(QFont::PreferVerticalHinting), + int(QFont::PreferFullHinting), + -1 + }; + int *hintingPreference = hintingPreferences; + + while (*hintingPreference >= 0) { + QString fileName = QLatin1String(SRCDIR "testfont.ttf"); + QString title = fileName + + QLatin1String(": hintingPreference=") + + QString::number(*hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QString::fromLatin1("QtBidiTestFont") + << QFont::StyleNormal + << QFont::Normal + << QFont::HintingPreference(*hintingPreference) + << 1000.0 + << 10; + + fileName = QLatin1String(SRCDIR "testfont_bold_italic.ttf"); + title = fileName + + QLatin1String(": hintingPreference=") + + QString::number(*hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QString::fromLatin1("QtBidiTestFont") + << QFont::StyleItalic + << QFont::Bold + << QFont::HintingPreference(*hintingPreference) + << 1000.0 + << 10; + + ++hintingPreference; + } +} + +void tst_QRawFont::correctFontData() +{ + QFETCH(QString, fileName); + QFETCH(QString, expectedFamilyName); + QFETCH(QFont::Style, style); + QFETCH(QFont::Weight, weight); + QFETCH(QFont::HintingPreference, hintingPreference); + QFETCH(qreal, unitsPerEm); + QFETCH(int, pixelSize); + + QRawFont font(fileName, 10, hintingPreference); + QVERIFY(font.isValid()); + + QCOMPARE(font.familyName(), expectedFamilyName); + QCOMPARE(font.style(), style); + QCOMPARE(font.weight(), int(weight)); + QCOMPARE(font.hintingPreference(), hintingPreference); + QCOMPARE(font.unitsPerEm(), unitsPerEm); + QCOMPARE(font.pixelSize(), pixelSize); +} + +void tst_QRawFont::glyphIndices() +{ + QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10); + QVERIFY(font.isValid()); + + QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("Foobar")); + QVector<quint32> expectedGlyphIndices; + expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; + + QCOMPARE(glyphIndices, expectedGlyphIndices); +} + +void tst_QRawFont::advances_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting") << QFont::PreferFullHinting; +} + +void tst_QRawFont::advances() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + QRawFont font(QLatin1String(SRCDIR "testfont.ttf"), 10, hintingPreference); + QVERIFY(font.isValid()); + + QRawFontPrivate *font_d = QRawFontPrivate::get(font); + QVERIFY(font_d->fontEngine != 0); + + QVector<quint32> glyphIndices; + glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar" + + bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions(); + QVector<QPointF> advances = font.advancesForGlyphIndexes(glyphIndices); + for (int i=0; i<glyphIndices.size(); ++i) { + QVERIFY(qFuzzyCompare(qRound(advances.at(i).x()), 8.0)); + if (supportsSubPixelPositions) + QVERIFY(advances.at(i).x() > 8.0); + + QVERIFY(qFuzzyIsNull(advances.at(i).y())); + } +} + +void tst_QRawFont::textLayout() +{ + QFontDatabase fontDatabase; + int id = fontDatabase.addApplicationFont(SRCDIR "testfont.ttf"); + QVERIFY(id >= 0); + + QString familyName = QString::fromLatin1("QtBidiTestFont"); + QFont font(familyName); + font.setPixelSize(18); + QCOMPARE(QFontInfo(font).family(), familyName); + + QTextLayout layout(QLatin1String("Foobar")); + layout.setFont(font); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList<QGlyphs> glyphss = layout.glyphs(); + QCOMPARE(glyphss.size(), 1); + + QGlyphs glyphs = glyphss.at(0); + + QRawFont rawFont = glyphs.font(); + QVERIFY(rawFont.isValid()); + QCOMPARE(rawFont.familyName(), familyName); + QCOMPARE(rawFont.pixelSize(), 18); + + QVector<quint32> expectedGlyphIndices; + expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; + + QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices); + + QVERIFY(fontDatabase.removeApplicationFont(id)); +} + +void tst_QRawFont::fontTable_data() +{ + QTest::addColumn<QByteArray>("tagName"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + QTest::addColumn<int>("offset"); + QTest::addColumn<quint32>("expectedValue"); + + QTest::newRow("Head table, magic number, default hinting") + << QByteArray("head") + << QFont::PreferDefaultHinting + << 12 + << (QSysInfo::ByteOrder == QSysInfo::BigEndian + ? 0x5F0F3CF5 + : 0xF53C0F5F); + + QTest::newRow("Head table, magic number, no hinting") + << QByteArray("head") + << QFont::PreferNoHinting + << 12 + << (QSysInfo::ByteOrder == QSysInfo::BigEndian + ? 0x5F0F3CF5 + : 0xF53C0F5F); + + QTest::newRow("Head table, magic number, vertical hinting") + << QByteArray("head") + << QFont::PreferVerticalHinting + << 12 + << (QSysInfo::ByteOrder == QSysInfo::BigEndian + ? 0x5F0F3CF5 + : 0xF53C0F5F); + + QTest::newRow("Head table, magic number, full hinting") + << QByteArray("head") + << QFont::PreferFullHinting + << 12 + << (QSysInfo::ByteOrder == QSysInfo::BigEndian + ? 0x5F0F3CF5 + : 0xF53C0F5F); +} + +void tst_QRawFont::fontTable() +{ + QFETCH(QByteArray, tagName); + QFETCH(QFont::HintingPreference, hintingPreference); + QFETCH(int, offset); + QFETCH(quint32, expectedValue); + + QRawFont font(QString::fromLatin1(SRCDIR "testfont.ttf"), 10, hintingPreference); + QVERIFY(font.isValid()); + + QByteArray table = font.fontTable(tagName); + QVERIFY(!table.isEmpty()); + + const quint32 *value = reinterpret_cast<const quint32 *>(table.constData() + offset); + QCOMPARE(*value, expectedValue); +} + +typedef QList<QFontDatabase::WritingSystem> WritingSystemList; +Q_DECLARE_METATYPE(WritingSystemList) + +void tst_QRawFont::supportedWritingSystems_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<WritingSystemList>("writingSystems"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + for (int hintingPreference=QFont::PreferDefaultHinting; + hintingPreference<=QFont::PreferFullHinting; + ++hintingPreference) { + + QTest::newRow(qPrintable(QString::fromLatin1("testfont.ttf, hintingPreference=%1") + .arg(hintingPreference))) + << QString::fromLatin1(SRCDIR "testfont.ttf") + << (QList<QFontDatabase::WritingSystem>() + << QFontDatabase::Latin + << QFontDatabase::Hebrew + << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin + << QFont::HintingPreference(hintingPreference); + + QTest::newRow(qPrintable(QString::fromLatin1("testfont_bold_italic.ttf, hintingPreference=%1") + .arg(hintingPreference))) + << QString::fromLatin1(SRCDIR "testfont_bold_italic.ttf") + << (QList<QFontDatabase::WritingSystem>() + << QFontDatabase::Latin + << QFontDatabase::Hebrew + << QFontDatabase::Devanagari + << QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin + << QFont::HintingPreference(hintingPreference); + } +} + +void tst_QRawFont::supportedWritingSystems() +{ + QFETCH(QString, fileName); + QFETCH(WritingSystemList, writingSystems); + QFETCH(QFont::HintingPreference, hintingPreference); + + QRawFont font(fileName, 10, hintingPreference); + QVERIFY(font.isValid()); + + WritingSystemList actualWritingSystems = font.supportedWritingSystems(); + QCOMPARE(actualWritingSystems.size(), writingSystems.size()); + + foreach (QFontDatabase::WritingSystem writingSystem, writingSystems) + QVERIFY(actualWritingSystems.contains(writingSystem)); +} + +void tst_QRawFont::supportsCharacter_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + QTest::addColumn<QChar>("character"); + QTest::addColumn<bool>("shouldBeSupported"); + + const char *fileNames[2] = { + SRCDIR "testfont.ttf", + SRCDIR "testfont_bold_italic.ttf" + }; + + for (int hintingPreference=QFont::PreferDefaultHinting; + hintingPreference<=QFont::PreferFullHinting; + ++hintingPreference) { + + for (int i=0; i<2; ++i) { + QString fileName = QLatin1String(fileNames[i]); + + // Latin text + for (char ch='!'; ch<='~'; ++ch) { + QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3") + .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(hintingPreference) + << QChar::fromLatin1(ch) + << true; + } + + // Hebrew text + for (quint16 ch=0x05D0; ch<=0x05EA; ++ch) { + QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3") + .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(hintingPreference) + << QChar(ch) + << true; + } + + QTest::newRow(qPrintable(QString::fromLatin1("Missing character, %1, hintingPreference=%2") + .arg(fileName).arg(hintingPreference))) + << fileName + << QFont::HintingPreference(hintingPreference) + << QChar(0xD8) + << false; + } + } +} + +void tst_QRawFont::supportsCharacter() +{ + QFETCH(QString, fileName); + QFETCH(QFont::HintingPreference, hintingPreference); + QFETCH(QChar, character); + QFETCH(bool, shouldBeSupported); + + QRawFont font(fileName, 10, hintingPreference); + QVERIFY(font.isValid()); + + QCOMPARE(font.supportsCharacter(character), shouldBeSupported); +} + +void tst_QRawFont::supportsUcs4Character_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + QTest::addColumn<quint32>("ucs4"); + QTest::addColumn<bool>("shouldBeSupported"); + + // Gothic text + for (int hintingPreference=QFont::PreferDefaultHinting; + hintingPreference<=QFont::PreferFullHinting; + ++hintingPreference) { + for (quint32 ch=0x10330; ch<=0x1034A; ++ch) { + { + QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf"); + QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3") + .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(hintingPreference) + << ch + << true; + } + + { + QString fileName = QString::fromLatin1(SRCDIR "testfont_bold_italic.ttf"); + QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3") + .arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference); + + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(hintingPreference) + << ch + << false; + } + } + } +} + +void tst_QRawFont::supportsUcs4Character() +{ + QFETCH(QString, fileName); + QFETCH(QFont::HintingPreference, hintingPreference); + QFETCH(quint32, ucs4); + QFETCH(bool, shouldBeSupported); + + QRawFont font(fileName, 10, hintingPreference); + QVERIFY(font.isValid()); + + QCOMPARE(font.supportsCharacter(ucs4), shouldBeSupported); +} + +void tst_QRawFont::fromFont_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + QTest::addColumn<QString>("familyName"); + QTest::addColumn<QFontDatabase::WritingSystem>("writingSystem"); + + for (int i=QFont::PreferDefaultHinting; i<=QFont::PreferFullHinting; ++i) { + QString titleBase = QString::fromLatin1("%2, hintingPreference=%1, writingSystem=%3") + .arg(i); + { + QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf"); + QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any; + + QString title = titleBase.arg(fileName).arg(writingSystem); + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(i) + << "QtBidiTestFont" + << writingSystem; + } + + { + QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf"); + QFontDatabase::WritingSystem writingSystem = QFontDatabase::Hebrew; + + QString title = titleBase.arg(fileName).arg(writingSystem); + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(i) + << "QtBidiTestFont" + << writingSystem; + } + + { + QString fileName = QString::fromLatin1(SRCDIR "testfont.ttf"); + QFontDatabase::WritingSystem writingSystem = QFontDatabase::Latin; + + QString title = titleBase.arg(fileName).arg(writingSystem); + QTest::newRow(qPrintable(title)) + << fileName + << QFont::HintingPreference(i) + << "QtBidiTestFont" + << writingSystem; + } + } +} + +void tst_QRawFont::fromFont() +{ + QFETCH(QString, fileName); + QFETCH(QFont::HintingPreference, hintingPreference); + QFETCH(QString, familyName); + QFETCH(QFontDatabase::WritingSystem, writingSystem); + + QFontDatabase fontDatabase; + int id = fontDatabase.addApplicationFont(fileName); + QVERIFY(id >= 0); + + QFont font(familyName); + font.setHintingPreference(hintingPreference); + font.setPixelSize(26); + + QRawFont rawFont = QRawFont::fromFont(font, writingSystem); + QVERIFY(rawFont.isValid()); + QCOMPARE(rawFont.familyName(), familyName); + QCOMPARE(rawFont.pixelSize(), 26); + + QVERIFY(fontDatabase.removeApplicationFont(id)); +} + +void tst_QRawFont::copyConstructor_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting preference") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting preference") << QFont::PreferFullHinting; +} + +void tst_QRawFont::copyConstructor() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + { + QString rawFontFamilyName; + int rawFontPixelSize; + qreal rawFontAscent; + qreal rawFontDescent; + int rawFontTableSize; + + QRawFont outerRawFont; + { + QRawFont rawFont(QString::fromLatin1(SRCDIR "testfont.ttf"), 11, hintingPreference); + QVERIFY(rawFont.isValid()); + + rawFontFamilyName = rawFont.familyName(); + rawFontPixelSize = rawFont.pixelSize(); + rawFontAscent = rawFont.ascent(); + rawFontDescent = rawFont.descent(); + rawFontTableSize = rawFont.fontTable("glyf").size(); + QVERIFY(rawFontTableSize > 0); + + { + QRawFont otherRawFont(rawFont); + QVERIFY(otherRawFont.isValid()); + QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); + QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); + QCOMPARE(otherRawFont.ascent(), rawFontAscent); + QCOMPARE(otherRawFont.descent(), rawFontDescent); + QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize); + } + + { + QRawFont otherRawFont = rawFont; + QVERIFY(otherRawFont.isValid()); + QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); + QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); + QCOMPARE(otherRawFont.ascent(), rawFontAscent); + QCOMPARE(otherRawFont.descent(), rawFontDescent); + QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize); + } + + outerRawFont = rawFont; + } + + QVERIFY(outerRawFont.isValid()); + QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(outerRawFont.familyName(), rawFontFamilyName); + QCOMPARE(outerRawFont.hintingPreference(), hintingPreference); + QCOMPARE(outerRawFont.ascent(), rawFontAscent); + QCOMPARE(outerRawFont.descent(), rawFontDescent); + QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize); + } +} + +void tst_QRawFont::detach_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting preference") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting preference") << QFont::PreferFullHinting; +} + +void tst_QRawFont::detach() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + { + QString rawFontFamilyName; + int rawFontPixelSize; + qreal rawFontAscent; + qreal rawFontDescent; + int rawFontTableSize; + + QRawFont outerRawFont; + { + QRawFont rawFont(QString::fromLatin1(SRCDIR "testfont.ttf"), 11, hintingPreference); + QVERIFY(rawFont.isValid()); + + rawFontFamilyName = rawFont.familyName(); + rawFontPixelSize = rawFont.pixelSize(); + rawFontAscent = rawFont.ascent(); + rawFontDescent = rawFont.descent(); + rawFontTableSize = rawFont.fontTable("glyf").size(); + QVERIFY(rawFontTableSize > 0); + + { + QRawFont otherRawFont(rawFont); + + otherRawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"), + rawFontPixelSize, hintingPreference); + + QVERIFY(otherRawFont.isValid()); + QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); + QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); + QCOMPARE(otherRawFont.ascent(), rawFontAscent); + QCOMPARE(otherRawFont.descent(), rawFontDescent); + QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize); + } + + { + QRawFont otherRawFont = rawFont; + + otherRawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"), + rawFontPixelSize, hintingPreference); + + QVERIFY(otherRawFont.isValid()); + QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(otherRawFont.familyName(), rawFontFamilyName); + QCOMPARE(otherRawFont.hintingPreference(), hintingPreference); + QCOMPARE(otherRawFont.ascent(), rawFontAscent); + QCOMPARE(otherRawFont.descent(), rawFontDescent); + QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize); + } + + outerRawFont = rawFont; + + rawFont.loadFromFile(QLatin1String(SRCDIR "testfont.ttf"), rawFontPixelSize, + hintingPreference); + } + + QVERIFY(outerRawFont.isValid()); + QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize); + QCOMPARE(outerRawFont.familyName(), rawFontFamilyName); + QCOMPARE(outerRawFont.hintingPreference(), hintingPreference); + QCOMPARE(outerRawFont.ascent(), rawFontAscent); + QCOMPARE(outerRawFont.descent(), rawFontDescent); + QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize); + } +} + +void tst_QRawFont::unsupportedWritingSystem_data() +{ + QTest::addColumn<QFont::HintingPreference>("hintingPreference"); + + QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting; + QTest::newRow("No hinting preference") << QFont::PreferNoHinting; + QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting; + QTest::newRow("Full hinting preference") << QFont::PreferFullHinting; +} + +void tst_QRawFont::unsupportedWritingSystem() +{ + QFETCH(QFont::HintingPreference, hintingPreference); + + QFontDatabase fontDatabase; + int id = fontDatabase.addApplicationFont(QLatin1String(SRCDIR "testfont.ttf")); + + QFont font("QtBidiTestFont"); + font.setHintingPreference(hintingPreference); + font.setPixelSize(12); + + QRawFont rawFont = QRawFont::fromFont(font, QFontDatabase::Any); + QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont")); + QCOMPARE(rawFont.pixelSize(), 12); + + rawFont = QRawFont::fromFont(font, QFontDatabase::Hebrew); + QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont")); + QCOMPARE(rawFont.pixelSize(), 12); + + QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic); + + QTextLayout layout; + layout.setFont(font); + layout.setText(arabicText); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList<QGlyphs> glyphss = layout.glyphs(); + QCOMPARE(glyphss.size(), 1); + + QGlyphs glyphs = glyphss.at(0); + QRawFont layoutFont = glyphs.font(); + QVERIFY(layoutFont.familyName() != QString::fromLatin1("QtBidiTestFont")); + QCOMPARE(layoutFont.pixelSize(), 12); + + rawFont = QRawFont::fromFont(font, QFontDatabase::Arabic); + QCOMPARE(rawFont.familyName(), layoutFont.familyName()); + QCOMPARE(rawFont.pixelSize(), 12); + + fontDatabase.removeApplicationFont(id); +} + +#endif // QT_NO_RAWFONT + +QTEST_MAIN(tst_QRawFont) +#include "tst_qrawfont.moc" + diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index e7c8175..bb04621 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -698,7 +698,7 @@ void tst_QSharedPointer::noSharedPointerFromWeakQObject() QSharedPointer<QObject> strong = weak.toStrongRef(); QVERIFY(strong.isNull()); - // is something went wrong, we'll probably crash here + // if something went wrong, we'll probably crash here } void tst_QSharedPointer::weakQObjectFromSharedPointer() @@ -1747,7 +1747,6 @@ void tst_QSharedPointer::invalidConstructs_data() "QSharedPointer<Data> b;\n" "if (a + b) return;"; -#if QT_VERSION >= 0x040600 // two objects with the same pointer QTest::newRow("same-pointer") << &QTest::QExternalTest::tryRunFail @@ -1761,7 +1760,6 @@ void tst_QSharedPointer::invalidConstructs_data() << "Data *aData = new Data;\n" "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);" "ptr1 = QSharedPointer<Data>(aData);"; -#endif // any type of cast for unrelated types: // (we have no reinterpret_cast) diff --git a/tests/auto/qsslkey/tst_qsslkey.cpp b/tests/auto/qsslkey/tst_qsslkey.cpp index e7b4740..86da09e 100644 --- a/tests/auto/qsslkey/tst_qsslkey.cpp +++ b/tests/auto/qsslkey/tst_qsslkey.cpp @@ -108,10 +108,8 @@ tst_QSslKey::tst_QSslKey() #ifdef Q_WS_MAC // applicationDirPath() points to a path inside the app bundle on Mac. QDir dir(qApp->applicationDirPath() + QLatin1String("/../../../keys")); -#elif defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN) - QDir dir(SRCDIR + QLatin1String("/keys")); // prefer this way to avoid ifdeffery and support shadow builds? #else - QDir dir(qApp->applicationDirPath() + QLatin1String("/keys")); + QDir dir(SRCDIR + QLatin1String("/keys")); // prefer this way to avoid ifdeffery and support shadow builds? #endif QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable); QRegExp rx(QLatin1String("^(rsa|dsa)-(pub|pri)-(\\d+)\\.(pem|der)$")); diff --git a/tests/auto/qstringbuilder1/stringbuilder.cpp b/tests/auto/qstringbuilder1/stringbuilder.cpp index 035a1f4..d7a32bf 100644 --- a/tests/auto/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/qstringbuilder1/stringbuilder.cpp @@ -190,9 +190,6 @@ void runScenario() ba2 = (ba += QLatin1String(LITERAL) + QString::fromUtf8(UTF8_LITERAL)); QCOMPARE(ba2, ba); QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); - ba = UTF8_LITERAL; - ba += QLatin1String(LITERAL) P withZero; - QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL + withZero)); #endif } diff --git a/tests/auto/qtextblock/tst_qtextblock.cpp b/tests/auto/qtextblock/tst_qtextblock.cpp index cec3a6a..748d921 100644 --- a/tests/auto/qtextblock/tst_qtextblock.cpp +++ b/tests/auto/qtextblock/tst_qtextblock.cpp @@ -76,6 +76,7 @@ private slots: void excludeParagraphSeparatorFragment(); void backwardsBlockIterator(); void previousBlock_qtbug18026(); + void removedBlock_qtbug18500(); private: QTextDocument *doc; @@ -181,5 +182,16 @@ void tst_QTextBlock::previousBlock_qtbug18026() QVERIFY(last.isValid()); } +void tst_QTextBlock::removedBlock_qtbug18500() +{ + cursor.insertText("line 1\nline 2\nline 3 \nline 4\n"); + cursor.setPosition(7); + QTextBlock block = cursor.block(); + cursor.setPosition(21, QTextCursor::KeepAnchor); + + cursor.removeSelectedText(); + QVERIFY(!block.isValid()); +} + QTEST_MAIN(tst_QTextBlock) #include "tst_qtextblock.moc" diff --git a/tests/auto/selftests/tst_selftests.cpp b/tests/auto/selftests/tst_selftests.cpp index 0d27d38..1c01c5f 100644 --- a/tests/auto/selftests/tst_selftests.cpp +++ b/tests/auto/selftests/tst_selftests.cpp @@ -515,8 +515,6 @@ BenchmarkResult BenchmarkResult::parse(QString const& line, QString* error) } bool ok; -#if QT_VERSION >= 0x040700 - // Qt 4.7 uses floating point double total = sTotal.toDouble(&ok); if (!ok) { if (error) *error = sTotal + " is not a valid number"; @@ -527,18 +525,6 @@ BenchmarkResult BenchmarkResult::parse(QString const& line, QString* error) if (error) *error = sIterations + " is not a valid number"; return out; } -#else - qlonglong total = sTotal.toLongLong(&ok); - if (!ok) { - if (error) *error = sTotal + " is not a valid integer"; - return out; - } - qlonglong iterations = sIterations.toLongLong(&ok); - if (!ok) { - if (error) *error = sIterations + " is not a valid integer"; - return out; - } -#endif out.unit = unit; out.total = total; diff --git a/tests/auto/symbols/tst_symbols.cpp b/tests/auto/symbols/tst_symbols.cpp index db1cbea..6f21c71 100644 --- a/tests/auto/symbols/tst_symbols.cpp +++ b/tests/auto/symbols/tst_symbols.cpp @@ -169,11 +169,7 @@ void tst_Symbols::globalObjects() } if (isFailed) { -#if QT_VERSION >= 0x040600 QVERIFY2(!isFailed, "Libraries contain static global objects. See Debug output above."); -#else - QSKIP("Libraries contains static global objects. See Debug output above. [These errors cannot be fixed in 4.5 in time]", SkipSingle); -#endif } } |