diff options
author | Sami Lempinen <sami.lempinen@nokia.com> | 2011-04-28 08:10:57 (GMT) |
---|---|---|
committer | Sami Lempinen <sami.lempinen@nokia.com> | 2011-04-28 08:10:57 (GMT) |
commit | 95de3f34d9dba4cd95f1f3d32b35c4a4d97e70d9 (patch) | |
tree | 7be35a9028b5c83b792190fb954127e9f558baf5 /tests | |
parent | 9d6530b9774de482b0b3a29720f7f756e986f5c7 (diff) | |
parent | 8e615d9b07f6146b5cb6b56c4cd2e32376a8b429 (diff) | |
download | Qt-95de3f34d9dba4cd95f1f3d32b35c4a4d97e70d9.zip Qt-95de3f34d9dba4cd95f1f3d32b35c4a4d97e70d9.tar.gz Qt-95de3f34d9dba4cd95f1f3d32b35c4a4d97e70d9.tar.bz2 |
Merge remote-tracking branch 'qt/4.8'
Diffstat (limited to 'tests')
193 files changed, 9943 insertions, 1609 deletions
diff --git a/tests/auto/collections/tst_collections.cpp b/tests/auto/collections/tst_collections.cpp index 9b24660..b1ea326 100644 --- a/tests/auto/collections/tst_collections.cpp +++ b/tests/auto/collections/tst_collections.cpp @@ -104,13 +104,6 @@ void foo() #include "q3cleanuphandler.h" #endif -// Do not test initialization of pods on msvc6 and msvc 2002 -// This is a known issue -#if defined Q_CC_MSVC && _MSC_VER < 1310 -# define NOPODINITIALIZATION -#endif - - template class QList<int>; //TESTED_FILES= @@ -198,10 +191,6 @@ QT_END_NAMESPACE struct Pod { int i1, i2; - -#if defined NOPODINITIALIZATION - Pod() : i1(0), i2(0) { } -#endif }; tst_Collections::tst_Collections() 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/declarative.pro b/tests/auto/declarative/declarative.pro index 08f0b9e..98e15e8 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -76,11 +76,6 @@ contains(QT_CONFIG, private_tests) { qdeclarativeworkerscript \ qdeclarativexmllistmodel \ qpacketprotocol - -contains(QT_CONFIG, webkit) { - SUBDIRS += \ - qdeclarativewebview -} } # Tests which should run in Pulse diff --git a/tests/auto/declarative/qdeclarativeanimations/data/attached.qml b/tests/auto/declarative/qdeclarativeanimations/data/attached.qml index 5da4a69..c5d5535 100644 --- a/tests/auto/declarative/qdeclarativeanimations/data/attached.qml +++ b/tests/auto/declarative/qdeclarativeanimations/data/attached.qml @@ -17,7 +17,7 @@ Rectangle { transitions: Transition { PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true } - ScriptAction { script: console.log(ListView.delayRemove ? "on" : "off") } + ScriptAction { script: console.log(wrapper.ListView.delayRemove ? "on" : "off") } } Component.onCompleted: { diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml b/tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml new file mode 100644 index 0000000..aa384c3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativebehaviors/data/delayedRegistration.qml @@ -0,0 +1,25 @@ +import QtQuick 1.0 + +Rectangle { + id: container + + width: 400; height: 400; + property Item myItem + + function doCreate() { + myItem = myComponent.createObject(container) + myItem.x = 100 + } + + Component { + id: myComponent + Rectangle { + width: 100 + height: 100 + color: "green" + Behavior on x { NumberAnimation { duration: 500 } } + } + } + + Component.onCompleted: doCreate() +} diff --git a/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp b/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp index 80ba907..4536d9e 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp +++ b/tests/auto/declarative/qdeclarativebehaviors/tst_qdeclarativebehaviors.cpp @@ -81,6 +81,7 @@ private slots: void groupedPropertyCrash(); void runningTrue(); void sameValue(); + void delayedRegistration(); }; void tst_qdeclarativebehaviors::simpleBehavior() @@ -412,6 +413,23 @@ void tst_qdeclarativebehaviors::sameValue() QTRY_VERIFY(target->x() != qreal(0) && target->x() != qreal(100)); } +//QTBUG-18362 +void tst_qdeclarativebehaviors::delayedRegistration() +{ + QDeclarativeEngine engine; + + QDeclarativeComponent c(&engine, SRCDIR "/data/delayedRegistration.qml"); + QDeclarativeRectangle *rect = qobject_cast<QDeclarativeRectangle*>(c.create()); + QVERIFY(rect != 0); + + QDeclarativeItem *innerRect = rect->property("myItem").value<QDeclarativeItem*>(); + QVERIFY(innerRect != 0); + + QCOMPARE(innerRect->property("x").toInt(), int(0)); + + QTRY_COMPARE(innerRect->property("x").toInt(), int(100)); +} + QTEST_MAIN(tst_qdeclarativebehaviors) #include "tst_qdeclarativebehaviors.moc" diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index 6bcb4eb..de4ddcc 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -66,7 +66,6 @@ Q_DECLARE_METATYPE(QDeclarativeDebugWatch::State) - class tst_QDeclarativeDebug : public QObject { Q_OBJECT @@ -119,6 +118,18 @@ private slots: void setBindingInStates(); }; +class NonScriptProperty : public QObject { + Q_OBJECT + Q_PROPERTY(int nonScriptProp READ nonScriptProp WRITE setNonScriptProp NOTIFY nonScriptPropChanged SCRIPTABLE false) +public: + int nonScriptProp() const { return 0; } + void setNonScriptProp(int) {} +signals: + void nonScriptPropChanged(); +}; +QML_DECLARE_TYPE(NonScriptProperty) + + QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context, bool recursive) { QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); @@ -283,6 +294,7 @@ void tst_QDeclarativeDebug::compareProperties(const QDeclarativeDebugPropertyRef void tst_QDeclarativeDebug::initTestCase() { qRegisterMetaType<QDeclarativeDebugWatch::State>(); + qmlRegisterType<NonScriptProperty>("Test", 1, 0, "NonScriptPropertyElement"); QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); QDeclarativeDebugHelper::enableDebugging(); @@ -292,7 +304,8 @@ void tst_QDeclarativeDebug::initTestCase() QList<QByteArray> qml; qml << "import QtQuick 1.0\n" - "Item {" + "import Test 1.0\n" + "Item {" "id: root\n" "width: 10; height: 20; scale: blueRect.scale;" "Rectangle { id: blueRect; width: 500; height: 600; color: \"blue\"; }" @@ -308,6 +321,8 @@ void tst_QDeclarativeDebug::initTestCase() "list[0] = blueRect;\n" "varObjList = list;\n" "}\n" + "NonScriptPropertyElement {\n" + "}\n" "}"; // add second component to test multiple root contexts @@ -726,7 +741,7 @@ void tst_QDeclarativeDebug::queryObject() // check source as defined in main() QDeclarativeDebugFileReference source = obj.source(); QCOMPARE(source.url(), QUrl::fromLocalFile("")); - QCOMPARE(source.lineNumber(), 2); + QCOMPARE(source.lineNumber(), 3); QCOMPARE(source.columnNumber(), 1); // generically test all properties, children and childrens' properties diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.2.qml new file mode 100644 index 0000000..a7184c9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/attachedProperty.2.qml @@ -0,0 +1,22 @@ +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +MyQmlObject { + property alias a: me.a + property alias b: me.a + property alias c: me.a + property alias d: me.a + + property MyQmlObject obj + obj: MyQmlObject { + MyQmlObject.value2: 13 + + id: me + property int a: MyQmlObject.value2 * 2 + property int b: Namespace.MyQmlObject.value2 * 2 + property int c: me.Namespace.MyQmlObject.value * 2 + property int d: me.Namespace.MyQmlObject.value * 2 + } +} + + 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..ad38d27 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -60,17 +60,18 @@ class MyQmlAttachedObject : public QObject { Q_OBJECT Q_PROPERTY(int value READ value CONSTANT) - Q_PROPERTY(int value2 READ value2 WRITE setValue2) + Q_PROPERTY(int value2 READ value2 WRITE setValue2 NOTIFY value2Changed) public: MyQmlAttachedObject(QObject *parent) : QObject(parent), m_value2(0) {} int value() const { return 19; } int value2() const { return m_value2; } - void setValue2(int v) { m_value2 = v; } + void setValue2(int v) { if (m_value2 == v) return; m_value2 = v; emit value2Changed(); } void emitMySignal() { emit mySignal(); } signals: + void value2Changed(); void mySignal(); private: @@ -159,7 +160,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..1ec12fe 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")); } } @@ -650,6 +650,16 @@ void tst_qdeclarativeecmascript::attachedProperties() } { + QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("a").toInt(), 26); + QCOMPARE(object->property("b").toInt(), 26); + QCOMPARE(object->property("c").toInt(), 26); + QCOMPARE(object->property("d").toInt(), 26); + } + + { QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml")); QObject *object = component.create(); QVERIFY(object != 0); @@ -870,7 +880,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 +905,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 +1151,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 +1952,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 +1965,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 +1978,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 +1991,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 +2004,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 +2017,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 +2033,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 +2052,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 +2071,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 +2089,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/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index c183934..c8e7817 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -97,6 +97,7 @@ private slots: void onRemove_data(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void contentPosJump(); private: QDeclarativeView *createView(); @@ -2077,6 +2078,56 @@ void tst_QDeclarativeGridView::testQtQuick11Attributes_data() << ""; } +void tst_QDeclarativeGridView::contentPosJump() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 100; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid"); + QVERIFY(gridview != 0); + + QDeclarativeItem *contentItem = gridview->contentItem(); + QVERIFY(contentItem != 0); + + // Test jumping more than a page of items. + gridview->setContentY(500); + + // Confirm items positioned correctly + int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 24; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); + QVERIFY(item->x() == (i%3)*80); + QVERIFY(item->y() == (i/3)*60); + } + + gridview->setContentY(-100); + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + QVERIFY(itemCount < 15); + // Confirm items positioned correctly + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QVERIFY(item); + QVERIFY(item->x() == (i%3)*80); + QVERIFY(item->y() == (i/3)*60); + } + + delete canvas; +} + QDeclarativeView *tst_QDeclarativeGridView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); 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/declarative/qdeclarativelistview/data/orientchange.qml b/tests/auto/declarative/qdeclarativelistview/data/orientchange.qml new file mode 100644 index 0000000..c7aa0cd --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistview/data/orientchange.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +ListView { + width: 240; height: 320 + delegate: Rectangle { objectName: "wrapper"; width: 80; height: 80 } + model: 100 +} diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 2267a89..0c96587 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -119,6 +119,8 @@ private slots: void testQtQuick11Attributes_data(); void rightToLeft(); void test_mirroring(); + void orientationChange(); + void contentPosJump(); private: template <class T> void items(); @@ -2583,6 +2585,107 @@ void tst_QDeclarativeListView::test_mirroring() delete canvasB; } +void tst_QDeclarativeListView::orientationChange() +{ + QDeclarativeView *canvas = createView(); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/orientchange.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject()); + QVERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + + listview->positionViewAtIndex(50, QDeclarativeListView::Beginning); + + // Confirm items positioned correctly + for (int i = 50; i < 54; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + QVERIFY(item); + QCOMPARE(item->y(), i*80.0); + } + + listview->setOrientation(QDeclarativeListView::Horizontal); + QCOMPARE(listview->contentY(), 0.); + + // Confirm items positioned correctly + for (int i = 0; i < 3; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + QVERIFY(item); + QCOMPARE(item->x(), i*80.0); + } + + listview->positionViewAtIndex(50, QDeclarativeListView::Beginning); + listview->setOrientation(QDeclarativeListView::Vertical); + QCOMPARE(listview->contentX(), 0.); + // + // Confirm items positioned correctly + for (int i = 0; i < 4; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + QVERIFY(item); + QCOMPARE(item->y(), i*80.0); + } + + delete canvas; +} + +void tst_QDeclarativeListView::contentPosJump() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 50; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // Confirm items positioned correctly + int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_VERIFY(item->y() == i*20); + } + + // Test jumping more than a page of items. + listview->setContentY(500); + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 25; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_VERIFY(item->y() == i*20); + } + + listview->setContentY(-100); + itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + QVERIFY(itemCount < 20); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_VERIFY(item->y() == i*20); + } + + delete canvas; +} + void tst_QDeclarativeListView::qListModelInterface_items() { items<TestModel>(); diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 8000137..46c3519 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -458,6 +458,16 @@ void tst_QDeclarativePathView::dataModel() model.removeItem(model.count()-1); QCOMPARE(pathview->currentIndex(), model.count()-1); + // QTBUG-18825 + // Confirm that the target offset is adjusted when removing items + pathview->setCurrentIndex(model.count()-1); + QTRY_COMPARE(pathview->offset(), 1.); + pathview->setCurrentIndex(model.count()-5); + model.removeItem(model.count()-1); + model.removeItem(model.count()-1); + model.removeItem(model.count()-1); + QTRY_COMPARE(pathview->offset(), 2.); + delete canvas; } diff --git a/tests/auto/declarative/qdeclarativetext/data/elideimplicitwidth.qml b/tests/auto/declarative/qdeclarativetext/data/elideimplicitwidth.qml new file mode 100644 index 0000000..60ae15c --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/elideimplicitwidth.qml @@ -0,0 +1,7 @@ +import QtQuick 1.1 + +Text { + text: "Hello World" + elide: Text.ElideRight + width: 30 +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 3d6641b..557603f 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -390,6 +390,13 @@ void tst_qdeclarativetext::elide() QCOMPARE(textObject->width(), 100.); } } + + // QTBUG-18627 + QUrl qmlfile = QUrl::fromLocalFile(SRCDIR "/data/elideimplicitwidth.qml"); + QDeclarativeComponent textComponent(&engine, qmlfile); + QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(textComponent.create()); + QVERIFY(item != 0); + QVERIFY(item->implicitWidth() > item->width()); } void tst_qdeclarativetext::textFormat() diff --git a/tests/auto/declarative/qdeclarativetextedit/data/cursorTest.qml b/tests/auto/declarative/qdeclarativetextedit/data/cursorTest.qml index c7c21fc..f7fb3e7 100644 --- a/tests/auto/declarative/qdeclarativetextedit/data/cursorTest.qml +++ b/tests/auto/declarative/qdeclarativetextedit/data/cursorTest.qml @@ -2,6 +2,7 @@ import QtQuick 1.0 Rectangle { width: 300; height: 300; color: "white" TextEdit { text: "Hello world!"; id: textEditObject; objectName: "textEditObject" + anchors.fill: parent resources: [ Component { id:cursor; Item { id:cursorInstance; objectName: "cursorInstance" } } ] cursorDelegate: cursor } diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_readonly.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_readonly.qml new file mode 100644 index 0000000..4aea611 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_false_readonly.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false + readOnly: true +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_readonly.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_readonly.qml new file mode 100644 index 0000000..959e683 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselection_true_readonly.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + readOnly: true +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 8f1be6f..2fad88d 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -119,6 +119,10 @@ private slots: void moveCursorSelectionSequence(); void mouseSelection_data(); void mouseSelection(); + void deferEnableSelectByMouse_data(); + void deferEnableSelectByMouse(); + void deferDisableSelectByMouse_data(); + void deferDisableSelectByMouse(); void mouseSelectionMode_data(); void mouseSelectionMode(); void dragMouseSelection(); @@ -788,6 +792,14 @@ void tst_qdeclarativetextedit::selection() QCOMPARE(textEditObject->selectionEnd(), i); QVERIFY(textEditObject->selectedText().isNull()); } + //Test cursor follows selection + for(int i=0; i<= testStr.size(); i++) { + textEditObject->select(i,i); + QCOMPARE(textEditObject->cursorPosition(), i); + QCOMPARE(textEditObject->selectionStart(), i); + QCOMPARE(textEditObject->selectionEnd(), i); + } + textEditObject->setCursorPosition(0); QVERIFY(textEditObject->cursorPosition() == 0); @@ -812,10 +824,12 @@ void tst_qdeclarativetextedit::selection() for(int i=0; i<= testStr.size(); i++) { textEditObject->select(0,i); QCOMPARE(testStr.mid(0,i), textEditObject->selectedText()); + QCOMPARE(textEditObject->cursorPosition(), i); } for(int i=0; i<= testStr.size(); i++) { textEditObject->select(i,testStr.size()); QCOMPARE(testStr.mid(i,testStr.size()-i), textEditObject->selectedText()); + QCOMPARE(textEditObject->cursorPosition(), testStr.size()); } textEditObject->setCursorPosition(0); @@ -1350,6 +1364,86 @@ void tst_qdeclarativetextedit::mouseSelection() delete canvas; } +void tst_qdeclarativetextedit::deferEnableSelectByMouse_data() +{ + QTest::addColumn<QString>("qmlfile"); + + QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml"; + QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml"; +} + +void tst_qdeclarativetextedit::deferEnableSelectByMouse() +{ + // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed. + QFETCH(QString, qmlfile); + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + textEditObject->setSelectByMouse(true); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QVERIFY(textEditObject->selectedText().isEmpty()); + + delete canvas; +} + +void tst_qdeclarativetextedit::deferDisableSelectByMouse_data() +{ + QTest::addColumn<QString>("qmlfile"); + + QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml"; + QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml"; +} + +void tst_qdeclarativetextedit::deferDisableSelectByMouse() +{ + // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed. + QFETCH(QString, qmlfile); + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast<QDeclarativeTextEdit *>(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + textEditObject->setSelectByMouse(false); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QVERIFY(textEditObject->selectedText().length() > 3); + + delete canvas; +} + void tst_qdeclarativetextedit::dragMouseSelection() { QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; @@ -1536,9 +1630,31 @@ void tst_qdeclarativetextedit::cursorDelegate() QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); } + const QString preedit = "preedit"; + for (int i = 0; i <= preedit.length(); i++) { + QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>() + << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant())); + QApplication::sendEvent(view, &event); + + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + } textEditObject->setCursorPosition(0); QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + QVERIFY(textEditObject->cursorRectangle().y() >= 0); + QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->cursorRectangle().height()); + textEditObject->setVAlign(QDeclarativeTextEdit::AlignVCenter); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + QVERIFY(textEditObject->cursorRectangle().y() > (textEditObject->height() / 2) - textEditObject->cursorRectangle().height()); + QVERIFY(textEditObject->cursorRectangle().y() < (textEditObject->height() / 2) + textEditObject->cursorRectangle().height()); + textEditObject->setVAlign(QDeclarativeTextEdit::AlignBottom); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + QVERIFY(textEditObject->cursorRectangle().y() > textEditObject->height() - (textEditObject->cursorRectangle().height() * 2)); + QVERIFY(textEditObject->cursorRectangle().y() < textEditObject->height()); + //Test Delegate gets deleted textEditObject->setCursorDelegate(0); QVERIFY(!textEditObject->findChild<QDeclarativeItem*>("cursorInstance")); @@ -2227,6 +2343,8 @@ void tst_qdeclarativetextedit::preeditMicroFocus() QTest::qWaitForWindowShown(&view); QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); + QSignalSpy cursorRectangleSpy(&edit, SIGNAL(cursorRectangleChanged())); + QRect currentRect; QRect previousRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); @@ -2237,8 +2355,9 @@ void tst_qdeclarativetextedit::preeditMicroFocus() currentRect = edit.inputMethodQuery(Qt::ImMicroFocus).toRect(); QCOMPARE(currentRect, previousRect); #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) - QCOMPARE(ic.updateReceived, true); + QCOMPARE(ic.updateReceived, false); // The cursor position hasn't changed. #endif + QCOMPARE(cursorRectangleSpy.count(), 0); // Verify that the micro focus rect moves to the left as the cursor position // is incremented. @@ -2250,6 +2369,8 @@ void tst_qdeclarativetextedit::preeditMicroFocus() #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); #endif + QVERIFY(cursorRectangleSpy.count() > 0); + cursorRectangleSpy.clear(); previousRect = currentRect; } @@ -2263,6 +2384,7 @@ void tst_qdeclarativetextedit::preeditMicroFocus() #if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QCOMPARE(ic.updateReceived, true); #endif + QVERIFY(cursorRectangleSpy.count() > 0); } void tst_qdeclarativetextedit::inputContextMouseHandler() diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_default.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_default.qml new file mode 100644 index 0000000..eea83ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_default.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false.qml new file mode 100644 index 0000000..eea83ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_readonly.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_readonly.qml new file mode 100644 index 0000000..36a9563 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_readonly.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false + readOnly: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_words.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_words.qml new file mode 100644 index 0000000..eea83ed --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_false_words.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: false +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_readonly.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_readonly.qml new file mode 100644 index 0000000..678a89a --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_readonly.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + readOnly: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_words.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_words.qml new file mode 100644 index 0000000..8115ba0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true_words.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index ef32ee3..a241241 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -95,6 +95,12 @@ private slots: void moveCursorSelection(); void moveCursorSelectionSequence_data(); void moveCursorSelectionSequence(); + void mouseSelection_data(); + void mouseSelection(); + void deferEnableSelectByMouse_data(); + void deferEnableSelectByMouse(); + void deferDisableSelectByMouse_data(); + void deferDisableSelectByMouse(); void dragMouseSelection(); void mouseSelectionMode_data(); void mouseSelectionMode(); @@ -375,6 +381,13 @@ void tst_qdeclarativetextinput::selection() QCOMPARE(textinputObject->selectionEnd(), i); QVERIFY(textinputObject->selectedText().isNull()); } + //Test cursor follows selection + for(int i=0; i<= testStr.size(); i++) { + textinputObject->select(i,i); + QCOMPARE(textinputObject->cursorPosition(), i); + QCOMPARE(textinputObject->selectionStart(), i); + QCOMPARE(textinputObject->selectionEnd(), i); + } textinputObject->setCursorPosition(0); QVERIFY(textinputObject->cursorPosition() == 0); @@ -399,10 +412,12 @@ void tst_qdeclarativetextinput::selection() for(int i=0; i<= testStr.size(); i++) { textinputObject->select(0,i); QCOMPARE(testStr.mid(0,i), textinputObject->selectedText()); + QCOMPARE(textinputObject->cursorPosition(), i); } for(int i=0; i<= testStr.size(); i++) { textinputObject->select(i,testStr.size()); QCOMPARE(testStr.mid(i,testStr.size()-i), textinputObject->selectedText()); + QCOMPARE(textinputObject->cursorPosition(), testStr.size()); } textinputObject->setCursorPosition(0); @@ -902,6 +917,141 @@ void tst_qdeclarativetextinput::moveCursorSelectionSequence() QCOMPARE(textinputObject->selectionEnd(), selection2End); } +void tst_qdeclarativetextinput::mouseSelection_data() +{ + QTest::addColumn<QString>("qmlfile"); + QTest::addColumn<bool>("expectSelection"); + + // import installed + QTest::newRow("on") << SRCDIR "/data/mouseselection_true.qml" << true; + QTest::newRow("off") << SRCDIR "/data/mouseselection_false.qml" << false; + QTest::newRow("default") << SRCDIR "/data/mouseselection_default.qml" << false; + QTest::newRow("on word selection") << SRCDIR "/data/mouseselection_true_words.qml" << true; + QTest::newRow("off word selection") << SRCDIR "/data/mouseselection_false_words.qml" << false; + QTest::newRow("on read only") << SRCDIR "/data/mouseselection_true_readonly.qml" << true; + QTest::newRow("off read only") << SRCDIR "/data/mouseselection_false_readonly.qml" << false; +} + +void tst_qdeclarativetextinput::mouseSelection() +{ + QFETCH(QString, qmlfile); + QFETCH(bool, expectSelection); + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str = textInputObject->selectedText(); + if (expectSelection) + QVERIFY(str.length() > 3); // don't reallly care *what* was selected (and it's too sensitive to platform) + else + QVERIFY(str.isEmpty()); + + // Clicking and shift to clicking between the same points should select the same text. + textInputObject->setCursorPosition(0); + QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::NoModifier, canvas->mapFromScene(QPoint(x1,y))); + QTest::mouseClick(canvas->viewport(), Qt::LeftButton, Qt::ShiftModifier, canvas->mapFromScene(QPoint(x2,y))); + QCOMPARE(textInputObject->selectedText(), str); + + delete canvas; +} + +void tst_qdeclarativetextinput::deferEnableSelectByMouse_data() +{ + QTest::addColumn<QString>("qmlfile"); + + QTest::newRow("writable") << SRCDIR "/data/mouseselection_false.qml"; + QTest::newRow("read only") << SRCDIR "/data/mouseselection_false_readonly.qml"; +} + +void tst_qdeclarativetextinput::deferEnableSelectByMouse() +{ + // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed. + QFETCH(QString, qmlfile); + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + textInputObject->setSelectByMouse(true); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QVERIFY(textInputObject->selectedText().isEmpty()); + + delete canvas; +} + +void tst_qdeclarativetextinput::deferDisableSelectByMouse_data() +{ + QTest::addColumn<QString>("qmlfile"); + + QTest::newRow("writable") << SRCDIR "/data/mouseselection_true.qml"; + QTest::newRow("read only") << SRCDIR "/data/mouseselection_true_readonly.qml"; +} + +void tst_qdeclarativetextinput::deferDisableSelectByMouse() +{ + // Verify text isn't selected if selectByMouse is enabled after the mouse button has been pressed. + QFETCH(QString, qmlfile); + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + textInputObject->setSelectByMouse(false); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QVERIFY(textInputObject->selectedText().length() > 3); + + delete canvas; +} + void tst_qdeclarativetextinput::dragMouseSelection() { QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; @@ -1364,8 +1514,10 @@ void tst_qdeclarativetextinput::inputMethods() QVERIFY(canvas->rootObject() != 0); QDeclarativeTextInput *input = qobject_cast<QDeclarativeTextInput *>(canvas->rootObject()); QVERIFY(input != 0); + QVERIFY(input->imHints() & Qt::ImhNoPredictiveText); QVERIFY(input->inputMethodHints() & Qt::ImhNoPredictiveText); - input->setInputMethodHints(Qt::ImhUppercaseOnly); + input->setIMHints(Qt::ImhUppercaseOnly); + QVERIFY(input->imHints() & Qt::ImhUppercaseOnly); QVERIFY(input->inputMethodHints() & Qt::ImhUppercaseOnly); QVERIFY(canvas->rootObject() != 0); @@ -1632,6 +1784,15 @@ void tst_qdeclarativetextinput::cursorDelegate() QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y())); } + const QString preedit = "preedit"; + for (int i = 0; i <= preedit.length(); i++) { + QInputMethodEvent event(preedit, QList<QInputMethodEvent::Attribute>() + << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, 1, QVariant())); + QApplication::sendEvent(view, &event); + + QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y())); + } textInputObject->setCursorPosition(0); QCOMPARE(textInputObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textInputObject->cursorRectangle().y(), qRound(delegateObject->y())); @@ -1805,6 +1966,7 @@ void tst_qdeclarativetextinput::echoMode() ref &= ~Qt::ImhHiddenText; ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhNone); input->setEchoMode(QDeclarativeTextInput::NoEcho); QCOMPARE(input->text(), initial); QCOMPARE(input->displayText(), QLatin1String("")); @@ -1813,6 +1975,7 @@ void tst_qdeclarativetextinput::echoMode() ref |= Qt::ImhHiddenText; ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhNone); input->setEchoMode(QDeclarativeTextInput::Password); //Password ref |= Qt::ImhHiddenText; @@ -1820,6 +1983,7 @@ void tst_qdeclarativetextinput::echoMode() QCOMPARE(input->text(), initial); QCOMPARE(input->displayText(), QLatin1String("********")); QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhNone); input->setPasswordCharacter(QChar('Q')); QCOMPARE(input->passwordCharacter(), QLatin1String("Q")); QCOMPARE(input->text(), initial); @@ -1829,6 +1993,7 @@ void tst_qdeclarativetextinput::echoMode() ref &= ~Qt::ImhHiddenText; ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhNone); QCOMPARE(input->text(), initial); QCOMPARE(input->displayText(), QLatin1String("QQQQQQQQ")); QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), QLatin1String("QQQQQQQQ")); @@ -1849,6 +2014,40 @@ void tst_qdeclarativetextinput::echoMode() QCOMPARE(input->displayText(), initial); QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial); + // Test echo mode doesn't override imHints. + input->setIMHints(Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + ref |= Qt::ImhDialableCharactersOnly; + //Normal + input->setEchoMode(QDeclarativeTextInput::Normal); + ref |= Qt::ImhHiddenText; + ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + //NoEcho + input->setEchoMode(QDeclarativeTextInput::NoEcho); + ref |= Qt::ImhHiddenText; + ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + //Password + input->setEchoMode(QDeclarativeTextInput::Password); + ref |= Qt::ImhHiddenText; + ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + //PasswordEchoOnEdit + input->setEchoMode(QDeclarativeTextInput::PasswordEchoOnEdit); + ref &= ~Qt::ImhHiddenText; + ref |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + //Normal + input->setEchoMode(QDeclarativeTextInput::Normal); + ref |= Qt::ImhHiddenText; + ref &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); + QCOMPARE(input->inputMethodHints(), ref); + QCOMPARE(input->imHints(), Qt::ImhHiddenText | Qt::ImhDialableCharactersOnly); + delete canvas; } @@ -2285,6 +2484,20 @@ void tst_qdeclarativetextinput::preeditAutoScroll() ic.sendPreeditText(preeditText.mid(0, 3), 1); QCOMPARE(input.positionAt(0), 0); QCOMPARE(input.positionAt(input.width()), 5); + + ic.sendEvent(QInputMethodEvent()); + input.setAutoScroll(true); + // Test committing pre-edit text at the start of the string. QTBUG-18789 + input.setCursorPosition(0); + ic.sendPreeditText(input.text(), 5); + QCOMPARE(input.positionAt(0), 0); + + QInputMethodEvent event; + event.setCommitString(input.text()); + ic.sendEvent(event); + + QCOMPARE(input.positionAt(0), 0); + QCOMPARE(input.positionAt(input.width()), 5); } void tst_qdeclarativetextinput::preeditMicroFocus() diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.html b/tests/auto/declarative/qdeclarativewebview/data/basic.html deleted file mode 100644 index 22e3e24..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.html +++ /dev/null @@ -1,17 +0,0 @@ -<html> -<head><title>Basic</title> -<link rel="icon" sizes="48x48" href="basic.png"> -<script type="text/javascript"> -<!-- -window.onload = function(){ window.status = "status here"; } -// --> -</script> -</head> -<body leftmargin="0" marginwidth="0"> -<table width="123"> -<tbody> -<tr><td>This is a basic test.</td></tr> -</tbody> -</table> -</body> -</html> diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.ico b/tests/auto/declarative/qdeclarativewebview/data/basic.ico Binary files differdeleted file mode 100644 index 8f3d05e..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.ico +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.png b/tests/auto/declarative/qdeclarativewebview/data/basic.png Binary files differdeleted file mode 100644 index 35717cc..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.png +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/basic.qml b/tests/auto/declarative/qdeclarativewebview/data/basic.qml deleted file mode 100644 index 73330cd..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/basic.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "basic.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/elements.html b/tests/auto/declarative/qdeclarativewebview/data/elements.html deleted file mode 100644 index 9236867..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/elements.html +++ /dev/null @@ -1,14 +0,0 @@ -<body leftmargin=0 topmargin=0> -<table width="300px" border=1 cellpadding=0 cellspacing=0> -<tr> -<td align=center width=25%%><p>A</p></td> -<td width=75% height=50px> - <table width=100% border=1 cellpadding=0 cellspacing=0> - <tr> - <td align=center width=50% height=50px><p>B</p></td> - <td align=center width=50% height=50px><p>C</p></td> - </tr> - </table> -</td> -</tr> -</table> diff --git a/tests/auto/declarative/qdeclarativewebview/data/elements.qml b/tests/auto/declarative/qdeclarativewebview/data/elements.qml deleted file mode 100644 index b86dd9d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/elements.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "elements.html" - width: 310 - height: 100 -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/forward.html b/tests/auto/declarative/qdeclarativewebview/data/forward.html deleted file mode 100644 index 62ab62d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/forward.html +++ /dev/null @@ -1,12 +0,0 @@ -<html> -<head><title>Forward</title> -<link rel="icon" sizes="32x32" href="forward.png"> -</head> -<body leftmargin="0" marginwidth="0"> -<table width="123"> -<tbody> -<tr><td>This is more.</td></tr> -</tbody> -</table> -</body> -</html> diff --git a/tests/auto/declarative/qdeclarativewebview/data/forward.png b/tests/auto/declarative/qdeclarativewebview/data/forward.png Binary files differdeleted file mode 100644 index a82533e..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/forward.png +++ /dev/null diff --git a/tests/auto/declarative/qdeclarativewebview/data/javaScript.html b/tests/auto/declarative/qdeclarativewebview/data/javaScript.html deleted file mode 100644 index 35270bc..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/javaScript.html +++ /dev/null @@ -1,11 +0,0 @@ -<html> -<head><title>JavaScript</title> -<link rel="icon" sizes="48x48" href="basic.png"> -<script type="text/javascript"> -<!-- -window.onload = function(){ window.status = "status here"; } -// --> -</script> -</head> -<body> -This is a JS test. diff --git a/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml b/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml deleted file mode 100644 index 527e3b9..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/javaScript.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "javaScript.html" - javaScriptWindowObjects: [ - QtObject { - property string qmlprop: "qmlvalue" - WebView.windowObjectName: "myjsname" - } - ] -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/loadError.qml b/tests/auto/declarative/qdeclarativewebview/data/loadError.qml deleted file mode 100644 index baab1a0..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/loadError.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - url: "does-not-exist.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/newwindows.html b/tests/auto/declarative/qdeclarativewebview/data/newwindows.html deleted file mode 100644 index dd541f9..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/newwindows.html +++ /dev/null @@ -1,16 +0,0 @@ -<html> -<head> -<script type="text/javascript"> -<!-- -function clickTheLink() -{ - var ev = document.createEvent('MouseEvents'); - ev.initEvent( "click", true, false ); - document.getElementById('thelink').dispatchEvent(ev); -} -// --> -</script> -</head> -<h1>Multiple windows...</h1> - -<a id=thelink target="_blank" href="newwindows.html">Popup!</a> diff --git a/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml b/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml deleted file mode 100644 index e66631d..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/newwindows.qml +++ /dev/null @@ -1,34 +0,0 @@ -// Demonstrates opening new WebViews from HTML - -import QtQuick 1.0 -import QtWebKit 1.0 - -Grid { - columns: 3 - id: pages - height: 300; width: 600 - property int total: 0 - - Component { - id: webViewPage - Rectangle { - width: webView.width - height: webView.height - border.color: "gray" - - WebView { - id: webView - width: 150 // force predictable for test - newWindowComponent: webViewPage - newWindowParent: pages - url: "newwindows.html" - Timer { - interval: 10; running: total<4; repeat: false; - onTriggered: { if (webView.status==WebView.Ready) { total++; webView.evaluateJavaScript("clickTheLink()") } } - } - } - } - } - - Loader { sourceComponent: webViewPage } -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html b/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html deleted file mode 100644 index 9412674..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.html +++ /dev/null @@ -1,10 +0,0 @@ -<html> -<body topmargin=0 leftmargin=0> -<table width=120 cellpadding=0 cellspacing=0> -<tr><td> -<h1>Pixel Cache</h1> -This test is for the pixel cache. Because this is a long document, -as it scrolls, more of the document will need to be rendered. -If the pixelCacheSize is small, the first parts of the document will -no longer be in the cache when it returns. -</table> diff --git a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml b/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml deleted file mode 100644 index 08e4d65..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/pixelCache.qml +++ /dev/null @@ -1,6 +0,0 @@ -import Test 1.0 - -MyWebView { - anchors.fill: parent - url: "pixelCache.html" -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml b/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml deleted file mode 100644 index db06887..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/propertychanges.qml +++ /dev/null @@ -1,34 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -Item { - width: 240 - height: 160 - Grid { - anchors.fill: parent - objectName: "newWindowParent" - id: newWindowParent - } - - Row { - anchors.fill: parent - id: oldWindowParent - objectName: "oldWindowParent" - } - - Loader { - sourceComponent: webViewComponent - } - Component { - id: webViewComponent - WebView { - id: webView - objectName: "webView" - newWindowComponent: webViewComponent - newWindowParent: oldWindowParent - url: "basic.html" - renderingEnabled: true - pressGrabTime: 200 - } - } -} diff --git a/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml b/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml deleted file mode 100644 index 7889704..0000000 --- a/tests/auto/declarative/qdeclarativewebview/data/sethtml.qml +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 1.0 -import QtWebKit 1.0 - -WebView { - html: "<p>This is a <b>string</b> set on the WebView" -} diff --git a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro b/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro deleted file mode 100644 index af13d33..0000000 --- a/tests/auto/declarative/qdeclarativewebview/qdeclarativewebview.pro +++ /dev/null @@ -1,16 +0,0 @@ -load(qttest_p4) -contains(QT_CONFIG,declarative): QT += declarative -contains(QT_CONFIG,webkit): QT += webkit -macx:CONFIG -= app_bundle - -SOURCES += tst_qdeclarativewebview.cpp - -symbian: { - importFiles.files = data - importFiles.path = . - DEPLOYMENT += importFiles -} else { - DEFINES += SRCDIR=\\\"$$PWD\\\" -} - -CONFIG += parallel_test diff --git a/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp b/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp deleted file mode 100644 index 9f99e83..0000000 --- a/tests/auto/declarative/qdeclarativewebview/tst_qdeclarativewebview.cpp +++ /dev/null @@ -1,520 +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 <qtest.h> -#include <QtTest/QSignalSpy> -#include "../../../shared/util.h" -#include <QtDeclarative/qdeclarativeengine.h> -#include <QtDeclarative/qdeclarativecomponent.h> -#include <private/qdeclarativepositioners_p.h> -#include <QtWebKit/qwebpage.h> -#include <QtWebKit/qwebframe.h> -#include <QtCore/qdir.h> -#include <QtCore/qfile.h> -#include <QtGui/qpainter.h> - -#ifdef Q_OS_SYMBIAN -// In Symbian OS test data is located in applications private dir -#define SRCDIR "." -#endif - -class tst_qdeclarativewebview : public QObject -{ - Q_OBJECT -public: - tst_qdeclarativewebview() {} - -private slots: - void initTestCase(); - void basicProperties(); - void settings(); - void historyNav(); - void multipleWindows(); - void elementAreaAt(); - void loadError(); - void setHtml(); - void javaScript(); - void cleanupTestCase(); - //void pixelCache(); - void newWindowParent(); - void newWindowComponent(); - void renderingEnabled(); - void pressGrabTime(); - -private: - void checkNoErrors(const QDeclarativeComponent& component); - QDeclarativeEngine engine; - QString tmpDir() const - { - static QString tmpd = QDir::tempPath()+"/tst_qdeclarativewebview-" - + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss")); - return tmpd; - } -}; - -void tst_qdeclarativewebview::initTestCase() -{ -} - -static QString strippedHtml(QString html) -{ - html.replace(QRegExp("\\s+"),""); - return html; -} - -static QString fileContents(const QString& filename) -{ - QFile file(filename); - file.open(QIODevice::ReadOnly); - return QString::fromUtf8(file.readAll()); -} - - -static void removeRecursive(const QString& dirname) -{ - QDir dir(dirname); - QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot)); - for (int i = 0; i < entries.count(); ++i) - if (entries[i].isDir()) - removeRecursive(entries[i].filePath()); - else - dir.remove(entries[i].fileName()); - QDir().rmdir(dirname); -} - -void tst_qdeclarativewebview::cleanupTestCase() -{ - removeRecursive(tmpDir()); -} - -void tst_qdeclarativewebview::checkNoErrors(const QDeclarativeComponent& component) -{ - // Wait until the component is ready - QTRY_VERIFY(component.isReady() || component.isError()); - - if (component.isError()) { - QList<QDeclarativeError> errors = component.errors(); - for (int ii = 0; ii < errors.count(); ++ii) { - const QDeclarativeError &error = errors.at(ii); - QByteArray errorStr = QByteArray::number(error.line()) + ":" + - QByteArray::number(error.column()) + ":" + - error.description().toUtf8(); - qWarning() << errorStr; - } - } - QVERIFY(!component.isError()); -} - -void tst_qdeclarativewebview::basicProperties() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/basic.png")); - QCOMPARE(wv->property("statusText").toString(),QString("status here")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("preferredWidth").toInt(), 0); - QCOMPARE(wv->property("preferredHeight").toInt(), 0); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - wv->setProperty("pixelCacheSize", 0); // mainly testing that it doesn't crash or anything! - QCOMPARE(wv->property("pixelCacheSize").toInt(),0); - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); -} - -void tst_qdeclarativewebview::settings() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QObject *s = QDeclarativeProperty(wv,"settings").object(); - QVERIFY(s != 0); - - // merely tests that setting gets stored (in QWebSettings) - // behavioural tests are in WebKit. - for (int b=0; b<=1; ++b) { - bool on = !!b; - - s->setProperty("autoLoadImages", on); - s->setProperty("developerExtrasEnabled", on); - s->setProperty("javaEnabled", on); - s->setProperty("javascriptCanAccessClipboard", on); - s->setProperty("javascriptCanOpenWindows", on); - s->setProperty("javascriptEnabled", on); - s->setProperty("linksIncludedInFocusChain", on); - s->setProperty("localContentCanAccessRemoteUrls", on); - s->setProperty("localStorageDatabaseEnabled", on); - s->setProperty("offlineStorageDatabaseEnabled", on); - s->setProperty("offlineWebApplicationCacheEnabled", on); - s->setProperty("pluginsEnabled", on); - s->setProperty("printElementBackgrounds", on); - s->setProperty("privateBrowsingEnabled", on); - s->setProperty("zoomTextOnly", on); - - QVERIFY(s->property("autoLoadImages") == on); - QVERIFY(s->property("developerExtrasEnabled") == on); - QVERIFY(s->property("javaEnabled") == on); - QVERIFY(s->property("javascriptCanAccessClipboard") == on); - QVERIFY(s->property("javascriptCanOpenWindows") == on); - QVERIFY(s->property("javascriptEnabled") == on); - QVERIFY(s->property("linksIncludedInFocusChain") == on); - QVERIFY(s->property("localContentCanAccessRemoteUrls") == on); - QVERIFY(s->property("localStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineWebApplicationCacheEnabled") == on); - QVERIFY(s->property("pluginsEnabled") == on); - QVERIFY(s->property("printElementBackgrounds") == on); - QVERIFY(s->property("privateBrowsingEnabled") == on); - QVERIFY(s->property("zoomTextOnly") == on); - - QVERIFY(s->property("autoLoadImages") == on); - QVERIFY(s->property("developerExtrasEnabled") == on); - QVERIFY(s->property("javaEnabled") == on); - QVERIFY(s->property("javascriptCanAccessClipboard") == on); - QVERIFY(s->property("javascriptCanOpenWindows") == on); - QVERIFY(s->property("javascriptEnabled") == on); - QVERIFY(s->property("linksIncludedInFocusChain") == on); - QVERIFY(s->property("localContentCanAccessRemoteUrls") == on); - QVERIFY(s->property("localStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineStorageDatabaseEnabled") == on); - QVERIFY(s->property("offlineWebApplicationCacheEnabled") == on); - QVERIFY(s->property("pluginsEnabled") == on); - QVERIFY(s->property("printElementBackgrounds") == on); - QVERIFY(s->property("privateBrowsingEnabled") == on); - QVERIFY(s->property("zoomTextOnly") == on); - } -} - -void tst_qdeclarativewebview::historyNav() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - for (int i=1; i<=2; ++i) { - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 48); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/basic.png")); - QCOMPARE(wv->property("statusText").toString(),QString("status here")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("preferredWidth").toDouble(), 0.0); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - } - - wv->setProperty("url", QUrl::fromLocalFile(SRCDIR "/data/forward.html")); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Forward")); - QTRY_COMPARE(qvariant_cast<QPixmap>(wv->property("icon")).width(), 32); - QCOMPARE(qvariant_cast<QPixmap>(wv->property("icon")),QPixmap(SRCDIR "/data/forward.png")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/forward.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/forward.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QCOMPARE(wv->property("statusText").toString(),QString("")); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); - - qvariant_cast<QAction*>(wv->property("back"))->trigger(); - - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("Basic")); - QCOMPARE(strippedHtml(fileContents(SRCDIR "/data/basic.html")), strippedHtml(wv->property("html").toString())); - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/basic.html")); - QCOMPARE(wv->property("status").toInt(), 1 /*QDeclarativeWebView::Ready*/); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("reload"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("back"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("back"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))); - QVERIFY(qvariant_cast<QAction*>(wv->property("forward"))->isEnabled()); - QVERIFY(qvariant_cast<QAction*>(wv->property("stop"))); - QVERIFY(!qvariant_cast<QAction*>(wv->property("stop"))->isEnabled()); -} - -void tst_qdeclarativewebview::multipleWindows() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/newwindows.qml")); - checkNoErrors(component); - - QDeclarativeGrid *grid = qobject_cast<QDeclarativeGrid*>(component.create()); - QVERIFY(grid != 0); - QTRY_COMPARE(grid->children().count(), 2+4); // Component, Loader (with 1 WebView), 4 new-window WebViews - QDeclarativeItem* popup = qobject_cast<QDeclarativeItem*>(grid->children().at(2)); // first popup after Component and Loader. - QVERIFY(popup != 0); - QTRY_COMPARE(popup->x(), 150.0); -} - -void tst_qdeclarativewebview::loadError() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/loadError.qml")); - checkNoErrors(component); - QWebSettings::enablePersistentStorage(tmpDir()); - - QObject *wv = component.create(); - QVERIFY(wv != 0); - for (int i=1; i<=2; ++i) { - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("title").toString(),QString("")); - QCOMPARE(wv->property("statusText").toString(),QString("")); // HTML 'status bar' text, not error message - QCOMPARE(wv->property("url").toUrl(), QUrl::fromLocalFile(SRCDIR "/data/does-not-exist.html")); // Unlike QWebPage, which loses url - QCOMPARE(wv->property("status").toInt(), 3 /*QDeclarativeWebView::Error*/); - - qvariant_cast<QAction*>(wv->property("reload"))->trigger(); - } -} - -void tst_qdeclarativewebview::setHtml() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/sethtml.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QCOMPARE(wv->property("html").toString(),QString("<html><head></head><body><p>This is a <b>string</b> set on the WebView</p></body></html>")); - - QSignalSpy spy(wv, SIGNAL(htmlChanged())); - wv->setProperty("html", QString("<html><head><title>Basic</title></head><body><p>text</p></body></html>")); - QCOMPARE(spy.count(),1); -} - -void tst_qdeclarativewebview::elementAreaAt() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/elements.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - /* not now it's a plugin... - QCOMPARE(wv->elementAreaAt(40,30,100,100),QRect(1,1,75,54)); // Area A in data/elements.html - QCOMPARE(wv->elementAreaAt(130,30,200,100),QRect(78,3,110,50)); // Area B - QCOMPARE(wv->elementAreaAt(40,30,400,400),QRect(0,0,310,100)); // Whole view - QCOMPARE(wv->elementAreaAt(130,30,280,280),QRect(76,1,223,54)); // Area BC - QCOMPARE(wv->elementAreaAt(130,30,400,400),QRect(0,0,310,100)); // Whole view - */ -} - -void tst_qdeclarativewebview::javaScript() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/javaScript.qml")); - checkNoErrors(component); - QObject *wv = component.create(); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - /* not now it's a plugin... - QCOMPARE(wv->evaluateJavaScript("123").toInt(), 123); - QCOMPARE(wv->evaluateJavaScript("window.status").toString(), QString("status here")); - QCOMPARE(wv->evaluateJavaScript("window.myjsname.qmlprop").toString(), QString("qmlvalue")); - */ -} - -/* -Cannot be done now that webkit is a plugin - -void tst_qdeclarativewebview::pixelCache() -{ - - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/pixelCache.qml")); - checkNoErrors(component); - MyWebView *wv = qobject_cast<MyWebView*>(component.create()); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress"), 1.0); - QPixmap pm(150,150); - QPainter p(&pm); - wv->paint(&p,0,0); - const int expected = 120*(150+128); // 120 = width of HTML page, 150=pixmap height, 128=cache extra area - QCOMPARE(wv->property("pixelsPainted"), expected); - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected); // nothing new needed to be painted - wv->setProperty("pixelCacheSize", 0); // clears the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*2); // everything needed to be painted - // Note that painted things always go into the cache (even if they don't "fit"), - // just that they will be removed if anything else needs to be painted. - wv->setProperty("pixelCacheSize", expected); // won't clear the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*2); // still there - wv->setProperty("pixelCacheSize", expected-1); // too small - will clear the cache - wv->paint(&p,0,0); - QCOMPARE(wv->property("pixelsPainted"), expected*3); // repainted -} -*/ - -void tst_qdeclarativewebview::newWindowParent() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QDeclarativeItem* oldWindowParent = rootItem->findChild<QDeclarativeItem*>("oldWindowParent"); - QCOMPARE(qvariant_cast<QDeclarativeItem*>(wv->property("newWindowParent")), oldWindowParent); - QSignalSpy newWindowParentSpy(wv, SIGNAL(newWindowParentChanged())); - - QDeclarativeItem* newWindowParent = rootItem->findChild<QDeclarativeItem*>("newWindowParent"); - wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); - QVERIFY(newWindowParent); - QVERIFY(oldWindowParent); - QVERIFY(oldWindowParent->childItems().count() == 0); - QCOMPARE(wv->property("newWindowParent"), QVariant::fromValue(newWindowParent)); - QCOMPARE(newWindowParentSpy.count(),1); - - wv->setProperty("newWindowParent", QVariant::fromValue(newWindowParent)); - QCOMPARE(newWindowParentSpy.count(),1); - - wv->setProperty("newWindowParent", QVariant::fromValue((QDeclarativeItem*)0)); - QCOMPARE(newWindowParentSpy.count(),2); -} - -void tst_qdeclarativewebview::newWindowComponent() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QDeclarativeComponent substituteComponent(&engine); - substituteComponent.setData("import QtQuick 1.0; WebView { objectName: 'newWebView'; url: 'basic.html'; }", QUrl::fromLocalFile("")); - QSignalSpy newWindowComponentSpy(wv, SIGNAL(newWindowComponentChanged())); - - wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); - QCOMPARE(wv->property("newWindowComponent"), QVariant::fromValue(&substituteComponent)); - QCOMPARE(newWindowComponentSpy.count(),1); - - wv->setProperty("newWindowComponent", QVariant::fromValue(&substituteComponent)); - QCOMPARE(newWindowComponentSpy.count(),1); - - wv->setProperty("newWindowComponent", QVariant::fromValue((QDeclarativeComponent*)0)); - QCOMPARE(newWindowComponentSpy.count(),2); -} - -void tst_qdeclarativewebview::renderingEnabled() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - - QVERIFY(wv->property("renderingEnabled").toBool()); - QSignalSpy renderingEnabledSpy(wv, SIGNAL(renderingEnabledChanged())); - - wv->setProperty("renderingEnabled", false); - QVERIFY(!wv->property("renderingEnabled").toBool()); - QCOMPARE(renderingEnabledSpy.count(),1); - - wv->setProperty("renderingEnabled", false); - QCOMPARE(renderingEnabledSpy.count(),1); - - wv->setProperty("renderingEnabled", true); - QCOMPARE(renderingEnabledSpy.count(),2); -} - -void tst_qdeclarativewebview::pressGrabTime() -{ - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml")); - checkNoErrors(component); - QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(component.create()); - QObject *wv = rootItem->findChild<QObject*>("webView"); - QVERIFY(rootItem != 0); - QVERIFY(wv != 0); - QTRY_COMPARE(wv->property("progress").toDouble(), 1.0); - QCOMPARE(wv->property("pressGrabTime").toInt(), 200); - QSignalSpy pressGrabTimeSpy(wv, SIGNAL(pressGrabTimeChanged())); - - wv->setProperty("pressGrabTime", 100); - QCOMPARE(wv->property("pressGrabTime").toInt(), 100); - QCOMPARE(pressGrabTimeSpy.count(),1); - - wv->setProperty("pressGrabTime", 100); - QCOMPARE(pressGrabTimeSpy.count(),1); - - wv->setProperty("pressGrabTime", 0); - QCOMPARE(pressGrabTimeSpy.count(),2); -} - -QTEST_MAIN(tst_qdeclarativewebview) - -#include "tst_qdeclarativewebview.moc" diff --git a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 06baed8..1b9831c 100644 --- a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -140,9 +140,9 @@ void tst_QMetaObjectBuilder::mocVersionCheck() // whenenver moc changes. Once QMetaObjectBuilder has been // updated, this test can be changed to check for the next version. int version = int(QObject::staticMetaObject.d.data[0]); - QVERIFY(version == 4 || version == 5); + QVERIFY(version == 4 || version == 5 || version == 6); version = int(staticMetaObject.d.data[0]); - QVERIFY(version == 4 || version == 5); + QVERIFY(version == 4 || version == 5 || version == 6); } void tst_QMetaObjectBuilder::create() @@ -920,9 +920,9 @@ void tst_QMetaObjectBuilder::relatedMetaObject() QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::RelatedMetaObjects)); } -static int smetacall(QMetaObject::Call, int, void **) +static void smetacall(QObject *, QMetaObject::Call, int, void **) { - return 0; + return; } void tst_QMetaObjectBuilder::staticMetacall() diff --git a/tests/auto/gui.pro b/tests/auto/gui.pro index 186f00c..0d77fff 100644 --- a/tests/auto/gui.pro +++ b/tests/auto/gui.pro @@ -114,9 +114,6 @@ SUBDIRS=\ qmovie \ qvolatileimage \ qnetworkaccessmanager_and_qprogressdialog \ - qnetworkcachemetadata \ - qnetworkdiskcache \ - qnetworkreply \ qpaintengine \ qpainterpath \ qpainterpathstroker \ @@ -139,6 +136,7 @@ SUBDIRS=\ qpushbutton \ qquaternion \ qradiobutton \ + qrawfont \ qregexpvalidator \ qregion \ qscrollarea \ @@ -169,7 +167,6 @@ SUBDIRS=\ qtabbar \ qtableview \ qtablewidget \ - qtcpserver \ qtcpsocket \ qtessellator \ qtextblock \ @@ -196,7 +193,6 @@ SUBDIRS=\ qtreeview \ qtreewidget \ qtreewidgetitemiterator \ - qudpsocket \ qundogroup \ qundostack \ qvectornd \ diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index 203f0ae..7a8f958 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -497,7 +497,7 @@ private slots: void revisions(); void warnings_data(); void warnings(); - + void privateClass(); signals: void sigWithUnsignedArg(unsigned foo); @@ -517,6 +517,7 @@ private: private: QString qtIncludePath; + class PrivateClass; }; void tst_Moc::initTestCase() @@ -1648,6 +1649,25 @@ void tst_Moc::warnings() } +class tst_Moc::PrivateClass : public QObject { + Q_PROPERTY(int someProperty READ someSlot WRITE someSlot2) +Q_OBJECT +Q_SIGNALS: + void someSignal(); +public Q_SLOTS: + int someSlot() { return 1; } + void someSlot2(int) {} +public: + Q_INVOKABLE PrivateClass() {} +}; + +void tst_Moc::privateClass() +{ + QVERIFY(PrivateClass::staticMetaObject.indexOfConstructor("PrivateClass()") == 0); + QVERIFY(PrivateClass::staticMetaObject.indexOfSignal("someSignal()") > 0); +} + + QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" diff --git a/tests/auto/network.pro b/tests/auto/network.pro index b427f1c..e4cecce 100644 --- a/tests/auto/network.pro +++ b/tests/auto/network.pro @@ -16,15 +16,18 @@ SUBDIRS=\ qhttpnetworkconnection \ qhttpnetworkreply \ qhttpsocketengine \ - qnativesocketengine \ + platformsocketengine \ qnetworkaccessmanager \ qnetworkaddressentry \ + qnetworkcachemetadata \ qnetworkconfiguration \ qnetworkconfigurationmanager \ qnetworkcookie \ qnetworkcookiejar \ + qnetworkdiskcache \ qnetworkinterface \ qnetworkproxy \ + qnetworkreply \ qnetworkrequest \ qnetworksession \ qobjectperformance \ @@ -37,13 +40,15 @@ SUBDIRS=\ qsslsocket \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ + qtcpserver \ + qudpsocket \ # qnetworkproxyfactory \ # Uses a hardcoded proxy configuration !contains(QT_CONFIG, private_tests): SUBDIRS -= \ qauthenticator \ qhttpnetworkconnection \ qhttpnetworkreply \ - qnativesocketengine \ + platformsocketengine \ qsocketnotifier \ qsocks5socketengine \ diff --git a/tests/auto/networkselftest/tst_networkselftest.cpp b/tests/auto/networkselftest/tst_networkselftest.cpp index 64de64a..f40ea3e 100644 --- a/tests/auto/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/networkselftest/tst_networkselftest.cpp @@ -44,6 +44,12 @@ #include <time.h> +#ifndef QT_NO_BEARERMANAGEMENT +#include <QtNetwork/qnetworkconfigmanager.h> +#include <QtNetwork/qnetworkconfiguration.h> +#include <QtNetwork/qnetworksession.h> +#endif + #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir // Current path (C:\private\<UID>) contains only ascii chars @@ -64,6 +70,7 @@ public: QHostAddress serverIpAddress(); private slots: + void initTestCase(); void hostTest(); void dnsResolution_data(); void dnsResolution(); @@ -91,6 +98,12 @@ private slots: // ssl supported test void supportsSsl(); +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer<QNetworkSession> networkSession; +#endif }; class Chat @@ -354,6 +367,19 @@ QHostAddress tst_NetworkSelfTest::serverIpAddress() return cachedIpAddress; } +void tst_NetworkSelfTest::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif +} + void tst_NetworkSelfTest::hostTest() { // this is a localhost self-test @@ -469,7 +495,8 @@ void tst_NetworkSelfTest::fileLineEndingTest() static QList<Chat> ftpChat(const QByteArray &userSuffix = QByteArray()) { - return QList<Chat>() << Chat::expect("220") + QList<Chat> rv; + rv << Chat::expect("220") << Chat::discardUntil("\r\n") << Chat::send("USER anonymous" + userSuffix + "\r\n") << Chat::expect("331") @@ -504,10 +531,15 @@ static QList<Chat> ftpChat(const QByteArray &userSuffix = QByteArray()) // << Chat::send("SIZE nonASCII/german_\344\366\374\304\326\334\337\r\n") // << Chat::expect("213 40\r\n") - << Chat::send("QUIT\r\n") - << Chat::expect("221") - << Chat::discardUntil("\r\n") - << Chat::RemoteDisconnect; + << Chat::send("QUIT\r\n"); +#ifdef Q_OS_SYMBIAN + if (userSuffix.length() == 0) // received but unacknowledged packets are discarded by TCP RST, so this doesn't work with frox proxy +#endif + rv << Chat::expect("221") + << Chat::discardUntil("\r\n"); + + rv << Chat::RemoteDisconnect; + return rv; } void tst_NetworkSelfTest::ftpServer() diff --git a/tests/auto/platformsocketengine/.gitignore b/tests/auto/platformsocketengine/.gitignore new file mode 100644 index 0000000..afe9389 --- /dev/null +++ b/tests/auto/platformsocketengine/.gitignore @@ -0,0 +1 @@ +tst_platformsocketengine diff --git a/tests/auto/qnativesocketengine/qsocketengine.pri b/tests/auto/platformsocketengine/platformsocketengine.pri index 15f31fd..15f31fd 100644 --- a/tests/auto/qnativesocketengine/qsocketengine.pri +++ b/tests/auto/platformsocketengine/platformsocketengine.pri diff --git a/tests/auto/platformsocketengine/platformsocketengine.pro b/tests/auto/platformsocketengine/platformsocketengine.pro new file mode 100644 index 0000000..faf745c --- /dev/null +++ b/tests/auto/platformsocketengine/platformsocketengine.pro @@ -0,0 +1,16 @@ +load(qttest_p4) +SOURCES += tst_platformsocketengine.cpp + +include(../platformsocketengine/platformsocketengine.pri) + +requires(contains(QT_CONFIG,private_tests)) + +MOC_DIR=tmp + +QT = core network + +symbian { + TARGET.CAPABILITY = NetworkServices + INCLUDEPATH += $$OS_LAYER_SYSTEMINCLUDE + LIBS += -lesock +} diff --git a/tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp index 41eb1e25..184371d 100644 --- a/tests/auto/qnativesocketengine/tst_qnativesocketengine.cpp +++ b/tests/auto/platformsocketengine/tst_platformsocketengine.cpp @@ -50,7 +50,6 @@ #include <qdatastream.h> -#include <private/qnativesocketengine_p.h> #include <qhostaddress.h> #include <qdatetime.h> @@ -63,6 +62,20 @@ #include <stddef.h> +#ifdef Q_OS_SYMBIAN +#include <QNetworkConfigurationManager> +#include <QNetworkConfiguration> +#include <QNetworkSession> +#include <QScopedPointer> +#define PLATFORMSOCKETENGINE QSymbianSocketEngine +#define PLATFORMSOCKETENGINESTRING "QSymbianSocketEngine" +#include <private/qsymbiansocketengine_p.h> +#include <private/qcore_symbian_p.h> +#else +#define PLATFORMSOCKETENGINE QNativeSocketEngine +#define PLATFORMSOCKETENGINESTRING "QNativeSocketEngine" +#include <private/qnativesocketengine_p.h> +#endif #include <qstringlist.h> @@ -70,13 +83,13 @@ //TESTED_FILES=network/qnativesocketengine.cpp network/qnativesocketengine_p.h network/qnativesocketengine_unix.cpp -class tst_QNativeSocketEngine : public QObject +class tst_PlatformSocketEngine : public QObject { Q_OBJECT public: - tst_QNativeSocketEngine(); - virtual ~tst_QNativeSocketEngine(); + tst_PlatformSocketEngine(); + virtual ~tst_PlatformSocketEngine(); public slots: @@ -92,35 +105,35 @@ private slots: void udpLoopbackPerformance(); void tcpLoopbackPerformance(); void readWriteBufferSize(); - void tooManySockets(); void bind(); void networkError(); void setSocketDescriptor(); void invalidSend(); void receiveUrgentData(); + void tooManySockets(); }; -tst_QNativeSocketEngine::tst_QNativeSocketEngine() +tst_PlatformSocketEngine::tst_PlatformSocketEngine() { Q_SET_DEFAULT_IAP } -tst_QNativeSocketEngine::~tst_QNativeSocketEngine() +tst_PlatformSocketEngine::~tst_PlatformSocketEngine() { } -void tst_QNativeSocketEngine::init() +void tst_PlatformSocketEngine::init() { } -void tst_QNativeSocketEngine::cleanup() +void tst_PlatformSocketEngine::cleanup() { } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::construction() +void tst_PlatformSocketEngine::construction() { - QNativeSocketEngine socketDevice; + PLATFORMSOCKETENGINE socketDevice; QVERIFY(!socketDevice.isValid()); @@ -137,17 +150,17 @@ void tst_QNativeSocketEngine::construction() QVERIFY(socketDevice.peerPort() == 0); QVERIFY(socketDevice.error() == QAbstractSocket::UnknownSocketError); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::bytesAvailable() was called in QAbstractSocket::UnconnectedState"); QVERIFY(socketDevice.bytesAvailable() == 0); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::hasPendingDatagrams() was called in QAbstractSocket::UnconnectedState"); QVERIFY(!socketDevice.hasPendingDatagrams()); } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::simpleConnectToIMAP() +void tst_PlatformSocketEngine::simpleConnectToIMAP() { - QNativeSocketEngine socketDevice; + PLATFORMSOCKETENGINE socketDevice; // Initialize device QVERIFY(socketDevice.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); @@ -202,12 +215,9 @@ void tst_QNativeSocketEngine::simpleConnectToIMAP() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackTest() +void tst_PlatformSocketEngine::udpLoopbackTest() { -#ifdef SYMBIAN_WINSOCK_CONNECTIVITY - QSKIP("Not working on Emulator without WinPCAP", SkipAll); -#endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); @@ -224,7 +234,7 @@ void tst_QNativeSocketEngine::udpLoopbackTest() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); // Connect device #2 to #1 @@ -253,12 +263,9 @@ void tst_QNativeSocketEngine::udpLoopbackTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpIPv6LoopbackTest() +void tst_PlatformSocketEngine::udpIPv6LoopbackTest() { -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian: IPv6 is not yet supported", SkipAll); -#endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 bool init = udpSocket.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol); @@ -275,7 +282,7 @@ void tst_QNativeSocketEngine::udpIPv6LoopbackTest() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket, QAbstractSocket::IPv6Protocol)); // Connect device #2 to #1 @@ -305,12 +312,26 @@ void tst_QNativeSocketEngine::udpIPv6LoopbackTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::broadcastTest() +void tst_PlatformSocketEngine::broadcastTest() { +#ifdef Q_OS_SYMBIAN + //broadcast isn't supported on loopback connections, but is on WLAN +#ifndef QT_NO_BEARERMANAGEMENT + QScopedPointer<QNetworkConfigurationManager> netConfMan(new QNetworkConfigurationManager()); + QNetworkConfiguration networkConfiguration(netConfMan->defaultConfiguration()); + QScopedPointer<QNetworkSession> networkSession(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + bool ok = networkSession->waitForOpened(30000); + qDebug() << networkSession->isOpen() << networkSession->error() << networkSession->errorString(); + QVERIFY(ok); + } +#endif +#endif #ifdef Q_OS_AIX QSKIP("Broadcast does not work on darko", SkipAll); #endif - QNativeSocketEngine broadcastSocket; + PLATFORMSOCKETENGINE broadcastSocket; // Initialize a regular Udp socket QVERIFY(broadcastSocket.initialize(QAbstractSocket::UdpSocket)); @@ -324,10 +345,18 @@ void tst_QNativeSocketEngine::broadcastTest() // Broadcast an inappropriate troll message QByteArray trollMessage = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH."; - QVERIFY(broadcastSocket.writeDatagram(trollMessage.data(), + qint64 written = broadcastSocket.writeDatagram(trollMessage.data(), trollMessage.size(), QHostAddress::Broadcast, - port) == trollMessage.size()); + port); + +#ifdef Q_OS_SYMBIAN + //On symbian, broadcasts return 0 bytes written if none of the interfaces support it. + //Notably the loopback interfaces do not. (though they do support multicast!?) + if (written == 0) + QEXPECT_FAIL("", "No active interface supports broadcast", Abort); +#endif + QCOMPARE((int)written, trollMessage.size()); // Wait until we receive it ourselves #if defined(Q_OS_FREEBSD) @@ -346,9 +375,9 @@ void tst_QNativeSocketEngine::broadcastTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::serverTest() +void tst_PlatformSocketEngine::serverTest() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; // Initialize a Tcp socket QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -363,7 +392,7 @@ void tst_QNativeSocketEngine::serverTest() QVERIFY(server.state() == QAbstractSocket::ListeningState); // Initialize a Tcp socket - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { QVERIFY(client.state() == QAbstractSocket::ConnectingState); @@ -377,7 +406,7 @@ void tst_QNativeSocketEngine::serverTest() // A socket device is initialized on the server side, passing the // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); @@ -400,12 +429,12 @@ void tst_QNativeSocketEngine::serverTest() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::udpLoopbackPerformance() +void tst_PlatformSocketEngine::udpLoopbackPerformance() { #ifdef SYMBIAN_WINSOCK_CONNECTIVITY QSKIP("Not working on Emulator without WinPCAP", SkipAll); #endif - QNativeSocketEngine udpSocket; + PLATFORMSOCKETENGINE udpSocket; // Initialize device #1 QVERIFY(udpSocket.initialize(QAbstractSocket::UdpSocket)); @@ -422,7 +451,7 @@ void tst_QNativeSocketEngine::udpLoopbackPerformance() QVERIFY(port != 0); // Initialize device #2 - QNativeSocketEngine udpSocket2; + PLATFORMSOCKETENGINE udpSocket2; QVERIFY(udpSocket2.initialize(QAbstractSocket::UdpSocket)); // Connect device #2 to #1 @@ -454,9 +483,9 @@ void tst_QNativeSocketEngine::udpLoopbackPerformance() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tcpLoopbackPerformance() +void tst_PlatformSocketEngine::tcpLoopbackPerformance() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; // Initialize a Tcp socket QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -471,7 +500,7 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() QVERIFY(server.state() == QAbstractSocket::ListeningState); // Initialize a Tcp socket - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); // Connect to our server @@ -481,17 +510,21 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() QVERIFY(client.state() == QAbstractSocket::ConnectedState); } - // The server accepts the connectio + // The server accepts the connection int socketDescriptor = server.accept(); QVERIFY(socketDescriptor > 0); // A socket device is initialized on the server side, passing the // socket descriptor from accept(). It's pre-connected. - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); +#if defined (Q_OS_SYMBIAN) && defined (__WINS__) + const int messageSize = 1024 * 16; +#else const int messageSize = 1024 * 256; +#endif QByteArray message1(messageSize, '@'); QByteArray answer(messageSize, '@'); @@ -517,9 +550,9 @@ void tst_QNativeSocketEngine::tcpLoopbackPerformance() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::readWriteBufferSize() +void tst_PlatformSocketEngine::readWriteBufferSize() { - QNativeSocketEngine device; + PLATFORMSOCKETENGINE device; QVERIFY(device.initialize(QAbstractSocket::TcpSocket)); @@ -539,15 +572,15 @@ void tst_QNativeSocketEngine::readWriteBufferSize() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::tooManySockets() +void tst_PlatformSocketEngine::tooManySockets() { #if defined Q_OS_WIN QSKIP("Certain windows machines suffocate and spend too much time in this test.", SkipAll); #endif - QList<QNativeSocketEngine *> sockets; - QNativeSocketEngine *socketLayer = 0; + QList<PLATFORMSOCKETENGINE *> sockets; + PLATFORMSOCKETENGINE *socketLayer = 0; for (;;) { - socketLayer = new QNativeSocketEngine; + socketLayer = new PLATFORMSOCKETENGINE; sockets.append(socketLayer); if (!socketLayer->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)) @@ -560,20 +593,20 @@ void tst_QNativeSocketEngine::tooManySockets() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::bind() +void tst_PlatformSocketEngine::bind() { #if !defined Q_OS_WIN && !defined Q_OS_SYMBIAN - QNativeSocketEngine binder; + PLATFORMSOCKETENGINE binder; QVERIFY(binder.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(!binder.bind(QHostAddress::Any, 82)); QVERIFY(binder.error() == QAbstractSocket::SocketAccessError); #endif - QNativeSocketEngine binder2; + PLATFORMSOCKETENGINE binder2; QVERIFY(binder2.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(binder2.bind(QHostAddress::Any, 31180)); - QNativeSocketEngine binder3; + PLATFORMSOCKETENGINE binder3; QVERIFY(binder3.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); QVERIFY(!binder3.bind(QHostAddress::Any, 31180)); @@ -586,9 +619,9 @@ void tst_QNativeSocketEngine::bind() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::networkError() +void tst_PlatformSocketEngine::networkError() { - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol)); @@ -604,6 +637,12 @@ void tst_QNativeSocketEngine::networkError() #ifdef Q_OS_WIN // could use shutdown to produce different errors ::closesocket(client.socketDescriptor()); +#elif defined(Q_OS_SYMBIAN) + RSocket sock; + QVERIFY(QSymbianSocketManager::instance().lookupSocket(client.socketDescriptor(), sock)); + TRequestStatus stat; + sock.Shutdown(RSocket::EImmediate, stat); + User::WaitForRequest(stat); #else ::close(client.socketDescriptor()); #endif @@ -612,31 +651,31 @@ void tst_QNativeSocketEngine::networkError() } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::setSocketDescriptor() +void tst_PlatformSocketEngine::setSocketDescriptor() { - QNativeSocketEngine socket1; + PLATFORMSOCKETENGINE socket1; QVERIFY(socket1.initialize(QAbstractSocket::TcpSocket)); - QNativeSocketEngine socket2; + PLATFORMSOCKETENGINE socket2; QVERIFY(socket2.initialize(socket1.socketDescriptor())); } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::invalidSend() +void tst_PlatformSocketEngine::invalidSend() { - QNativeSocketEngine socket; + PLATFORMSOCKETENGINE socket; QVERIFY(socket.initialize(QAbstractSocket::TcpSocket)); - QTest::ignoreMessage(QtWarningMsg, "QNativeSocketEngine::writeDatagram() was" + QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::writeDatagram() was" " called by a socket other than QAbstractSocket::UdpSocket"); QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143), (qlonglong) -1); } //--------------------------------------------------------------------------- -void tst_QNativeSocketEngine::receiveUrgentData() +void tst_PlatformSocketEngine::receiveUrgentData() { - QNativeSocketEngine server; + PLATFORMSOCKETENGINE server; QVERIFY(server.initialize(QAbstractSocket::TcpSocket)); @@ -648,7 +687,7 @@ void tst_QNativeSocketEngine::receiveUrgentData() QVERIFY(server.listen()); QVERIFY(server.state() == QAbstractSocket::ListeningState); - QNativeSocketEngine client; + PLATFORMSOCKETENGINE client; QVERIFY(client.initialize(QAbstractSocket::TcpSocket)); if (!client.connectToHost(QHostAddress("127.0.0.1"), port)) { @@ -660,7 +699,7 @@ void tst_QNativeSocketEngine::receiveUrgentData() int socketDescriptor = server.accept(); QVERIFY(socketDescriptor > 0); - QNativeSocketEngine serverSocket; + PLATFORMSOCKETENGINE serverSocket; QVERIFY(serverSocket.initialize(socketDescriptor)); QVERIFY(serverSocket.state() == QAbstractSocket::ConnectedState); @@ -676,7 +715,18 @@ void tst_QNativeSocketEngine::receiveUrgentData() // The server sends an urgent message msg = 'Q'; +#if defined(Q_OS_SYMBIAN) + RSocket sock; + QVERIFY(QSymbianSocketManager::instance().lookupSocket(socketDescriptor, sock)); + TRequestStatus stat; + TSockXfrLength len; + sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len); + User::WaitForRequest(stat); + QVERIFY(stat == KErrNone); + QCOMPARE(len(), 1); +#else QCOMPARE(int(::send(socketDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); +#endif // The client receives the urgent message QVERIFY(client.waitForRead()); @@ -689,7 +739,15 @@ void tst_QNativeSocketEngine::receiveUrgentData() // The client sends an urgent message msg = 'T'; int clientDescriptor = client.socketDescriptor(); +#if defined(Q_OS_SYMBIAN) + QVERIFY(QSymbianSocketManager::instance().lookupSocket(clientDescriptor, sock)); + sock.Send(TPtrC8((TUint8*)&msg,1), KSockWriteUrgent, stat, len); + User::WaitForRequest(stat); + QVERIFY(stat == KErrNone); + QCOMPARE(len(), 1); +#else QCOMPARE(int(::send(clientDescriptor, &msg, sizeof(msg), MSG_OOB)), 1); +#endif // The server receives the urgent message QVERIFY(serverSocket.waitForRead()); @@ -701,5 +759,5 @@ void tst_QNativeSocketEngine::receiveUrgentData() } -QTEST_MAIN(tst_QNativeSocketEngine) -#include "tst_qnativesocketengine.moc" +QTEST_MAIN(tst_PlatformSocketEngine) +#include "tst_platformsocketengine.moc" diff --git a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp index db0d0a7..76e6711 100644 --- a/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp +++ b/tests/auto/qabstractnetworkcache/tst_qabstractnetworkcache.cpp @@ -45,6 +45,12 @@ #include "../../shared/util.h" #include "../network-settings.h" +#ifndef QT_NO_BEARERMANAGEMENT +#include <QtNetwork/qnetworkconfigmanager.h> +#include <QtNetwork/qnetworkconfiguration.h> +#include <QtNetwork/qnetworksession.h> +#endif + #define TESTFILE QString("http://%1/qtest/cgi-bin/").arg(QtNetworkSettings::serverName()) class tst_QAbstractNetworkCache : public QObject @@ -56,6 +62,7 @@ public: virtual ~tst_QAbstractNetworkCache(); private slots: + void initTestCase(); void expires_data(); void expires(); void expiresSynchronous_data(); @@ -81,6 +88,12 @@ private slots: private: void check(); void checkSynchronous(); + +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer<QNetworkSession> networkSession; +#endif }; class NetworkDiskCache : public QNetworkDiskCache @@ -124,6 +137,19 @@ static bool AlwaysFalse = false; Q_DECLARE_METATYPE(QNetworkRequest::CacheLoadControl) +void tst_QAbstractNetworkCache::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif +} + void tst_QAbstractNetworkCache::expires_data() { QTest::addColumn<QNetworkRequest::CacheLoadControl>("cacheLoadControl"); 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/qbytearray/tst_qbytearray.cpp b/tests/auto/qbytearray/tst_qbytearray.cpp index 5fff22a..0dea9be 100644 --- a/tests/auto/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/qbytearray/tst_qbytearray.cpp @@ -898,12 +898,12 @@ void tst_QByteArray::indexOf_data() QByteArray veryBigHaystack(500, 'a'); veryBigHaystack += 'B'; QTest::newRow("BoyerMooreStressTest") << veryBigHaystack << veryBigHaystack << 0 << 0; - QTest::newRow("BoyerMooreStressTest2") << veryBigHaystack + 'c' << veryBigHaystack << 0 << 0; - QTest::newRow("BoyerMooreStressTest3") << 'c' + veryBigHaystack << veryBigHaystack << 0 << 1; - QTest::newRow("BoyerMooreStressTest4") << veryBigHaystack << veryBigHaystack + 'c' << 0 << -1; - QTest::newRow("BoyerMooreStressTest5") << veryBigHaystack << 'c' + veryBigHaystack << 0 << -1; - QTest::newRow("BoyerMooreStressTest6") << 'd' + veryBigHaystack << 'c' + veryBigHaystack << 0 << -1; - QTest::newRow("BoyerMooreStressTest6") << veryBigHaystack + 'c' << 'c' + veryBigHaystack << 0 << -1; + QTest::newRow("BoyerMooreStressTest2") << QByteArray(veryBigHaystack + 'c') << QByteArray(veryBigHaystack) << 0 << 0; + QTest::newRow("BoyerMooreStressTest3") << QByteArray('c' + veryBigHaystack) << QByteArray(veryBigHaystack) << 0 << 1; + QTest::newRow("BoyerMooreStressTest4") << QByteArray(veryBigHaystack) << QByteArray(veryBigHaystack + 'c') << 0 << -1; + QTest::newRow("BoyerMooreStressTest5") << QByteArray(veryBigHaystack) << QByteArray('c' + veryBigHaystack) << 0 << -1; + QTest::newRow("BoyerMooreStressTest6") << QByteArray('d' + veryBigHaystack) << QByteArray('c' + veryBigHaystack) << 0 << -1; + QTest::newRow("BoyerMooreStressTest6") << QByteArray(veryBigHaystack + 'c') << QByteArray('c' + veryBigHaystack) << 0 << -1; } void tst_QByteArray::indexOf() diff --git a/tests/auto/qdatetime/tst_qdatetime.cpp b/tests/auto/qdatetime/tst_qdatetime.cpp index fa9c70b..f8836a6 100644 --- a/tests/auto/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/qdatetime/tst_qdatetime.cpp @@ -198,8 +198,8 @@ void tst_QDateTime::ctor() QDateTime dt3(QDate(2004, 1, 2), QTime(1, 2, 3), Qt::UTC); QVERIFY(dt1 == dt2); - QVERIFY(dt1 != dt3); if (europeanTimeZone) { + QVERIFY(dt1 != dt3); QVERIFY(dt1 < dt3); QVERIFY(dt1.addSecs(3600).toUTC() == dt3); } 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/qdbusabstractinterface/qpinger/qpinger.cpp b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp new file mode 100644 index 0000000..3b605c8 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 "../interface.h" + +static const char serviceName[] = "com.trolltech.autotests.qpinger"; +static const char objectPath[] = "/com/trolltech/qpinger"; +//static const char *interfaceName = serviceName; + +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); + + if (!con.registerService(serviceName)) + exit(2); + + 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/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/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/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index 04f7fa9..8112814 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -574,6 +574,12 @@ void tst_QDir::entryList_data() << int(QDir::AllEntries | QDir::Writable) << int(QDir::Name) << filterLinks(QString(".,..,directory,linktodirectory.lnk,writable").split(',')); #endif + QTest::newRow("QDir::Files | QDir::Readable") << SRCDIR "entrylist/" << QStringList("*") + << int(QDir::Files | QDir::Readable) << int(QDir::Name) + << filterLinks(QString("file,linktofile.lnk,writable").split(',')); + QTest::newRow("QDir::Dirs | QDir::Readable") << SRCDIR "entrylist/" << QStringList("*") + << int(QDir::Dirs | QDir::Readable) << int(QDir::Name) + << filterLinks(QString(".,..,directory,linktodirectory.lnk").split(',')); QTest::newRow("Namefilters b*") << SRCDIR "entrylist/" << QStringList("d*") << int(QDir::NoFilter) << int(QDir::Name) << filterLinks(QString("directory").split(',')); 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/qeventloop/qeventloop.pro b/tests/auto/qeventloop/qeventloop.pro index f6c24ae..e7489fa 100644 --- a/tests/auto/qeventloop/qeventloop.pro +++ b/tests/auto/qeventloop/qeventloop.pro @@ -5,3 +5,4 @@ QT += network win32:!wince*:LIBS += -luser32 +symbian:TARGET.CAPABILITY += NetworkServices
\ No newline at end of file diff --git a/tests/auto/qeventloop/tst_qeventloop.cpp b/tests/auto/qeventloop/tst_qeventloop.cpp index 6860f19..fa2a34e 100644 --- a/tests/auto/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/qeventloop/tst_qeventloop.cpp @@ -602,8 +602,10 @@ public slots: QTcpSocket *serverSocket = server->nextPendingConnection(); serverSocket->write(data, size); serverSocket->flush(); + QTest::qSleep(200); //allow the TCP/IP stack time to loopback the data, so our socket is ready to read QCoreApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); testResult = dataArrived; + QCoreApplication::processEvents(); //check the deferred event is processed serverSocket->close(); QThread::currentThread()->exit(0); } @@ -620,9 +622,11 @@ public: if (tester->init()) exec(); testResult = tester->testResult; + dataArrived = tester->dataArrived; delete tester; } bool testResult; + bool dataArrived; }; void tst_QEventLoop::processEventsExcludeSocket() @@ -631,6 +635,7 @@ void tst_QEventLoop::processEventsExcludeSocket() thread.start(); QVERIFY(thread.wait()); QVERIFY(!thread.testResult); + QVERIFY(thread.dataArrived); } class TimerReceiver : public QObject diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index 79539c9..688a92d 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -3294,13 +3294,18 @@ public: static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {} AutoIgnoreInvalidParameter() { - old = _set_invalid_parameter_handler(ignore_invalid_parameter); + oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter); + //also disable the abort/retry/ignore popup + oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG); } ~AutoIgnoreInvalidParameter() { - _set_invalid_parameter_handler(old); + //restore previous settings + _set_invalid_parameter_handler(oldHandler); + _CrtSetReportMode(_CRT_ASSERT, oldReportMode); } - _invalid_parameter_handler old; + _invalid_parameter_handler oldHandler; + int oldReportMode; #endif }; diff --git a/tests/auto/qftp/tst_qftp.cpp b/tests/auto/qftp/tst_qftp.cpp index 64d49d8..78157d8 100644 --- a/tests/auto/qftp/tst_qftp.cpp +++ b/tests/auto/qftp/tst_qftp.cpp @@ -50,6 +50,10 @@ #include <time.h> #include <stdlib.h> #include <QNetworkProxy> +#include <QNetworkConfiguration> +#include <qnetworkconfigmanager.h> +#include <QNetworkSession> +#include <QtNetwork/private/qnetworksession_p.h> #include "../network-settings.h" @@ -62,7 +66,9 @@ #define SRCDIR "" #endif - +#ifndef QT_NO_BEARERMANAGEMENT +Q_DECLARE_METATYPE(QNetworkConfiguration) +#endif class tst_QFtp : public QObject { @@ -148,6 +154,10 @@ private: void renameCleanup( const QString &host, const QString &user, const QString &password, const QString &fileToDelete ); QFtp *ftp; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer<QNetworkSession> networkSessionExplicit; + QSharedPointer<QNetworkSession> networkSessionImplicit; +#endif QList<int> ids; // helper to make sure that all expected signals are emitted int current_id; @@ -186,9 +196,9 @@ private: const int bytesTotal_init = -10; const int bytesDone_init = -10; -tst_QFtp::tst_QFtp() +tst_QFtp::tst_QFtp() : + ftp(0) { - Q_SET_DEFAULT_IAP } tst_QFtp::~tst_QFtp() @@ -199,33 +209,62 @@ void tst_QFtp::initTestCase_data() { QTest::addColumn<bool>("setProxy"); QTest::addColumn<int>("proxyType"); + QTest::addColumn<bool>("setSession"); - QTest::newRow("WithoutProxy") << false << 0; - QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); + QTest::newRow("WithoutProxy") << false << 0 << false; + QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy) << false; //### doesn't work well yet. //QTest::newRow("WithHttpProxy") << true << int(QNetworkProxy::HttpProxy); + +#ifndef QT_NO_BEARERMANAGEMENT + QTest::newRow("WithoutProxyWithSession") << false << 0 << true; + QTest::newRow("WithSocks5ProxyAndSession") << true << int(QNetworkProxy::Socks5Proxy) << true; +#endif } void tst_QFtp::initTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager manager; + networkSessionImplicit = QSharedPointer<QNetworkSession>(new QNetworkSession(manager.defaultConfiguration())); + networkSessionImplicit->open(); + QVERIFY(networkSessionImplicit->waitForOpened(60000)); //there may be user prompt on 1st connect +#endif } void tst_QFtp::cleanupTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + networkSessionExplicit.clear(); + networkSessionImplicit.clear(); +#endif } void tst_QFtp::init() { QFETCH_GLOBAL(bool, setProxy); + QFETCH_GLOBAL(int, proxyType); + QFETCH_GLOBAL(bool, setSession); if (setProxy) { - QFETCH_GLOBAL(int, proxyType); if (proxyType == QNetworkProxy::Socks5Proxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::Socks5Proxy, QtNetworkSettings::serverName(), 1080)); } else if (proxyType == QNetworkProxy::HttpProxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy(QNetworkProxy::HttpProxy, QtNetworkSettings::serverName(), 3128)); } } +#ifndef QT_NO_BEARERMANAGEMENT + if (setSession) { + networkSessionExplicit = networkSessionImplicit; + if (!networkSessionExplicit->isOpen()) { + networkSessionExplicit->open(); + QVERIFY(networkSessionExplicit->waitForOpened(30000)); + } + } else { + networkSessionExplicit.clear(); + } +#endif + delete ftp; ftp = 0; ids.clear(); @@ -270,6 +309,12 @@ void tst_QFtp::cleanup() if (setProxy) { QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy); } + + delete ftp; + ftp = 0; +#ifndef QT_NO_BEARERMANAGEMENT + networkSessionExplicit.clear(); +#endif } void tst_QFtp::connectToHost_data() @@ -1538,7 +1583,6 @@ void tst_QFtp::proxy() } } - void tst_QFtp::binaryAscii() { QString file = "asciifile%1.txt"; @@ -1899,6 +1943,11 @@ void tst_QFtp::dataTransferProgress( qint64 done, qint64 total ) QFtp *tst_QFtp::newFtp() { QFtp *nFtp = new QFtp( this ); +#ifndef QT_NO_BEARERMANAGEMENT + if (networkSessionExplicit) { + nFtp->setProperty("_q_networksession", QVariant::fromValue(networkSessionExplicit)); + } +#endif connect( nFtp, SIGNAL(commandStarted(int)), SLOT(commandStarted(int)) ); connect( nFtp, SIGNAL(commandFinished(int,bool)), diff --git a/tests/auto/qfuture/tst_qfuture.cpp b/tests/auto/qfuture/tst_qfuture.cpp index fa4ccb5..8afdf48 100644 --- a/tests/auto/qfuture/tst_qfuture.cpp +++ b/tests/auto/qfuture/tst_qfuture.cpp @@ -81,6 +81,7 @@ private slots: void voidConversions(); #ifndef QT_NO_EXCEPTIONS void exceptions(); + void exceptions_QTBUG18149(); #endif }; @@ -1431,6 +1432,33 @@ void tst_QFuture::exceptions() } + +void tst_QFuture::exceptions_QTBUG18149() +{ + class MyClass + { + public: + ~MyClass() + { + QFuture<void> f = createExceptionFuture(); + bool caught = false; + try { + f.waitForFinished(); + } catch (Exception &) { + caught = true; + } + QVERIFY(caught); + } + }; + + try { + MyClass m; + throw 0; + } catch (int) {} + +} + + #endif // QT_NO_EXCEPTIONS #include "tst_qfuture.moc" 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/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp index ee2fe0d..af0631e 100644 --- a/tests/auto/qhostinfo/tst_qhostinfo.cpp +++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp @@ -62,6 +62,12 @@ #include <private/qthread_p.h> #include <QTcpServer> +#ifndef QT_NO_BEARERMANAGEMENT +#include <QtNetwork/qnetworkconfigmanager.h> +#include <QtNetwork/qnetworkconfiguration.h> +#include <QtNetwork/qnetworksession.h> +#endif + #include <time.h> #include <qlibrary.h> #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) @@ -126,6 +132,7 @@ private slots: void raceCondition(); void threadSafety(); + void threadSafetyAsynchronousAPI(); void multipleSameLookups(); void multipleDifferentLookups_data(); @@ -133,6 +140,8 @@ private slots: void cache(); + void abortHostLookup(); + void abortHostLookupInDifferentThread(); protected slots: void resultsReady(const QHostInfo &); @@ -142,6 +151,11 @@ private: bool lookupDone; int lookupsDoneCounter; QHostInfo lookupResults; +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer<QNetworkSession> networkSession; +#endif }; // Testing get/set functions @@ -182,6 +196,21 @@ tst_QHostInfo::~tst_QHostInfo() void tst_QHostInfo::initTestCase() { +#ifndef QT_NO_BEARERMANAGEMENT + //start the default network + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif + +#ifdef Q_OS_SYMBIAN + ipv6Available = true; + ipv6LookupsAvailable = true; +#else ipv6Available = false; ipv6LookupsAvailable = false; #if !defined(QT_NO_GETADDRINFO) @@ -204,6 +233,7 @@ void tst_QHostInfo::initTestCase() } } #endif +#endif QTcpServer server; if (server.listen(QHostAddress("::1"))) { @@ -237,18 +267,14 @@ void tst_QHostInfo::lookupIPv4_data() QTest::addColumn<QString>("addresses"); QTest::addColumn<int>("err"); -#ifdef Q_OS_SYMBIAN // Test server lookup QTest::newRow("lookup_01") << QtNetworkSettings::serverName() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError); - QTest::newRow("literal_ip4") << QtNetworkSettings::serverIP().toString() << QtNetworkSettings::serverIP().toString() << int(QHostInfo::NoError); - QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError); -#else QTest::newRow("empty") << "" << "" << int(QHostInfo::HostNotFound); QTest::newRow("single_ip4") << "lupinella.troll.no" << lupinellaIp << int(QHostInfo::NoError); QTest::newRow("multiple_ip4") << "multi.dev.troll.no" << "1.2.3.4 1.2.3.5 10.3.3.31" << int(QHostInfo::NoError); QTest::newRow("literal_ip4") << lupinellaIp << lupinellaIp << int(QHostInfo::NoError); -#endif + QTest::newRow("notfound") << "this-name-does-not-exist-hopefully." << "" << int(QHostInfo::HostNotFound); QTest::newRow("idn-ace") << "xn--alqualond-34a.troll.no" << "10.3.3.55" << int(QHostInfo::NoError); @@ -290,7 +316,11 @@ void tst_QHostInfo::lookupIPv6_data() QTest::addColumn<QString>("addresses"); QTest::addColumn<int>("err"); - QTest::newRow("ip6") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError); + QTest::newRow("ipv6-net") << "www.ipv6-net.org" << "62.93.217.177 2001:618:1401:0:0:0:0:4" << int(QHostInfo::NoError); + QTest::newRow("ipv6-test") << "ipv6-test.dev.troll.no" << "2001:638:a00:2:0:0:0:2" << int(QHostInfo::NoError); + QTest::newRow("dns6-test") << "dns6-test-dev.troll.no" << "2001:470:1f01:115:0:0:0:10" << int(QHostInfo::NoError); + QTest::newRow("multi-dns6") << "multi-dns6-test-dev.troll.no" << "2001:470:1f01:115:0:0:0:11 2001:470:1f01:115:0:0:0:12" << int(QHostInfo::NoError); + QTest::newRow("dns46-test") << "dns46-test-dev.troll.no" << "10.3.4.90 2001:470:1f01:115:0:0:0:13" << int(QHostInfo::NoError); // avoid using real IPv6 addresses here because this will do a DNS query // real addresses are between 2000:: and 3fff:ffff:ffff:ffff:ffff:ffff:ffff @@ -310,7 +340,7 @@ void tst_QHostInfo::lookupIPv6() lookupDone = false; QHostInfo::lookupHost(hostname, this, SLOT(resultsReady(const QHostInfo&))); - QTestEventLoop::instance().enterLoop(3); + QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(lookupDone); @@ -337,7 +367,7 @@ void tst_QHostInfo::reverseLookup_data() // ### Use internal DNS instead. Discussed with Andreas. //QTest::newRow("classical.hexago.com") << QString("2001:5c0:0:2::24") << QStringList(QString("classical.hexago.com")) << 0; - QTest::newRow("origin.cisco.com") << QString("12.159.148.94") << QStringList(QString("origin.cisco.com")) << 0; + QTest::newRow("gitorious.org") << QString("87.238.52.168") << QStringList(QString("gitorious.org")) << 0; QTest::newRow("bogus-name") << QString("1::2::3::4") << QStringList() << 1; } @@ -411,6 +441,8 @@ protected: inline void run() { QHostInfo info = QHostInfo::fromName("qt.nokia.com"); + QCOMPARE(info.error(), QHostInfo::NoError); + QVERIFY(info.addresses().count() > 0); QCOMPARE(info.addresses().at(0).toString(), QString("87.238.50.178")); } }; @@ -418,7 +450,7 @@ protected: void tst_QHostInfo::threadSafety() { const int nattempts = 5; -#if defined(Q_OS_WINCE) +#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) const int runs = 10; #else const int runs = 100; @@ -432,6 +464,56 @@ void tst_QHostInfo::threadSafety() } } +class LookupReceiver : public QObject +{ + Q_OBJECT +public slots: + void start(); + void resultsReady(const QHostInfo&); +public: + QHostInfo result; + int numrequests; +}; + +void LookupReceiver::start() +{ + for (int i=0;i<numrequests;i++) + QHostInfo::lookupHost(QString("qt.nokia.com"), this, SLOT(resultsReady(const QHostInfo&))); +} + +void LookupReceiver::resultsReady(const QHostInfo &info) +{ + result = info; + numrequests--; + if (numrequests == 0 || info.error() != QHostInfo::NoError) + QThread::currentThread()->quit(); +} + +void tst_QHostInfo::threadSafetyAsynchronousAPI() +{ + const int nattempts = 10; + const int lookupsperthread = 10; + QList<QThread*> threads; + QList<LookupReceiver*> receivers; + for (int i = 0; i < nattempts; ++i) { + QThread* thread = new QThread; + LookupReceiver* receiver = new LookupReceiver; + receiver->numrequests = lookupsperthread; + receivers.append(receiver); + receiver->moveToThread(thread); + connect(thread, SIGNAL(started()), receiver, SLOT(start())); + thread->start(); + threads.append(thread); + } + for (int k = threads.count() - 1; k >= 0; --k) + QVERIFY(threads.at(k)->wait(60000)); + foreach (LookupReceiver* receiver, receivers) { + QCOMPARE(receiver->result.error(), QHostInfo::NoError); + QCOMPARE(receiver->result.addresses().at(0).toString(), QString("87.238.50.178")); + QCOMPARE(receiver->numrequests, 0); + } +} + // this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all, // not about getting correct IPs void tst_QHostInfo::multipleSameLookups() @@ -478,8 +560,9 @@ void tst_QHostInfo::multipleDifferentLookups() QElapsedTimer timer; timer.start(); - while (timer.elapsed() < 10000 && lookupsDoneCounter < repeats*COUNT) { + while (timer.elapsed() < 60000 && lookupsDoneCounter < repeats*COUNT) { QTestEventLoop::instance().enterLoop(2); + //qDebug() << "t:" << timer.elapsed(); } QCOMPARE(lookupsDoneCounter, repeats*COUNT); } @@ -520,7 +603,7 @@ void tst_QHostInfo::cache() QVERIFY(result.addresses().isEmpty()); // the slot should have been called 2 times. - QVERIFY(lookupsDoneCounter == 2); + QCOMPARE(lookupsDoneCounter, 2); } void tst_QHostInfo::resultsReady(const QHostInfo &hi) @@ -531,5 +614,52 @@ void tst_QHostInfo::resultsReady(const QHostInfo &hi) QMetaObject::invokeMethod(&QTestEventLoop::instance(), "exitLoop", Qt::QueuedConnection); } +void tst_QHostInfo::abortHostLookup() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + //it is assumed that the DNS request/response in the backend is slower than it takes to call abort + QHostInfo::abortHostLookup(id); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + +class LookupAborter : public QObject +{ + Q_OBJECT +public slots: + void abort() + { + QHostInfo::abortHostLookup(id); + QThread::currentThread()->quit(); + } +public: + int id; +}; + +void tst_QHostInfo::abortHostLookupInDifferentThread() +{ + //reset counter + lookupsDoneCounter = 0; + bool valid = false; + int id = -1; + QHostInfo result = qt_qhostinfo_lookup("qt.nokia.com", this, SLOT(resultsReady(QHostInfo)), &valid, &id); + QVERIFY(!valid); + QThread thread; + LookupAborter aborter; + aborter.id = id; + aborter.moveToThread(&thread); + connect(&thread, SIGNAL(started()), &aborter, SLOT(abort())); + //it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort + thread.start(); + QVERIFY(thread.wait(5000)); + QTestEventLoop::instance().enterLoop(5); + QCOMPARE(lookupsDoneCounter, 0); +} + QTEST_MAIN(tst_QHostInfo) #include "tst_qhostinfo.moc" diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 0b72139..ba1f8c8 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -195,8 +195,8 @@ void tst_QHttpNetworkConnection::head() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); - // only check it if it is set - if (reply->contentLength() != -1) + // only check it if it is set and expected + if (reply->contentLength() != -1 && contentLength != -1) QCOMPARE(reply->contentLength(), qint64(contentLength)); QVERIFY(reply->isFinished()); @@ -219,8 +219,8 @@ void tst_QHttpNetworkConnection::get_data() QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; QTest::newRow("success-external") << "http://" << "www.ietf.org" << "/rfc/rfc3252.txt" << ushort(80) << false << 200 << "OK" << 25962 << 25962; - QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size(); - QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << 930 + QtNetworkSettings::serverName().size(); + QTest::newRow("failure-path") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << 404 << "Not Found" << -1 << -1; + QTest::newRow("failure-protocol") << "" << QtNetworkSettings::serverName() << "/qtest/rfc3252.txt" << ushort(80) << false << 400 << "Bad Request" << -1 << -1; } void tst_QHttpNetworkConnection::get() @@ -255,8 +255,8 @@ void tst_QHttpNetworkConnection::get() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); - // only check it if it is set - if (reply->contentLength() != -1) + // only check it if it is set and expected + if (reply->contentLength() != -1 && contentLength != -1) QCOMPARE(reply->contentLength(), qint64(contentLength)); stopWatch.start(); @@ -270,7 +270,12 @@ void tst_QHttpNetworkConnection::get() } while (!reply->isFinished()); QVERIFY(reply->isFinished()); - QCOMPARE(ba.size(), downloadSize); + //do not require server generated error pages to be a fixed size + if (downloadSize != -1) + QCOMPARE(ba.size(), downloadSize); + //but check against content length if it was sent + if (reply->contentLength() != -1) + QCOMPARE(ba.size(), (int)reply->contentLength()); delete reply; } @@ -385,7 +390,7 @@ void tst_QHttpNetworkConnection::post_data() QTest::addColumn<int>("downloadSize"); QTest::newRow("success-internal") << "http://" << QtNetworkSettings::serverName() << "/qtest/cgi-bin/echo.cgi" << ushort(80) << false << "7 bytes" << 200 << "OK" << 7 << 7; - QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << 997 + QtNetworkSettings::serverName().size(); + QTest::newRow("failure-internal") << "http://" << QtNetworkSettings::serverName() << "/t" << ushort(80) << false << "Hello World" << 404 << "Not Found" << -1 << -1; } void tst_QHttpNetworkConnection::post() @@ -429,13 +434,16 @@ void tst_QHttpNetworkConnection::post() QCOMPARE(reply->reasonPhrase(), statusString); qint64 cLen = reply->contentLength(); - if (cLen==-1) { - // HTTP 1.1 server may respond with chunked encoding and in that - // case contentLength is not present in reply -> verify that it is the case - QByteArray transferEnc = reply->headerField("Transfer-Encoding"); - QCOMPARE(transferEnc, QByteArray("chunked")); - } else { - QCOMPARE(cLen, qint64(contentLength)); + if (contentLength != -1) { + // only check the content length if test expected it to be set + if (cLen==-1) { + // HTTP 1.1 server may respond with chunked encoding and in that + // case contentLength is not present in reply -> verify that it is the case + QByteArray transferEnc = reply->headerField("Transfer-Encoding"); + QCOMPARE(transferEnc, QByteArray("chunked")); + } else { + QCOMPARE(cLen, qint64(contentLength)); + } } stopWatch.start(); @@ -449,7 +457,12 @@ void tst_QHttpNetworkConnection::post() } while (!reply->isFinished()); QVERIFY(reply->isFinished()); - QCOMPARE(ba.size(), downloadSize); + //don't require fixed size for generated error pages + if (downloadSize != -1) + QCOMPARE(ba.size(), downloadSize); + //but do compare with content length if possible + if (cLen != -1) + QCOMPARE(ba.size(), (int)cLen); delete reply; } @@ -630,7 +643,8 @@ void tst_QHttpNetworkConnection::compression() QCOMPARE(reply->statusCode(), statusCode); QCOMPARE(reply->reasonPhrase(), statusString); bool isLengthOk = (reply->contentLength() == qint64(contentLength) - || reply->contentLength() == qint64(downloadSize)); + || reply->contentLength() == qint64(downloadSize) + || reply->contentLength() == -1); //apache2 does not send content-length for compressed pages QVERIFY(isLengthOk); diff --git a/tests/auto/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/qhttpsocketengine/qhttpsocketengine.pro index d76ebb6..6df6192 100644 --- a/tests/auto/qhttpsocketengine/qhttpsocketengine.pro +++ b/tests/auto/qhttpsocketengine/qhttpsocketengine.pro @@ -2,7 +2,7 @@ load(qttest_p4) SOURCES += tst_qhttpsocketengine.cpp -include(../qnativesocketengine/qsocketengine.pri) +include(../platformsocketengine/platformsocketengine.pri) MOC_DIR=tmp diff --git a/tests/auto/qlistview/tst_qlistview.cpp b/tests/auto/qlistview/tst_qlistview.cpp index b6e69a0..ee03386 100644 --- a/tests/auto/qlistview/tst_qlistview.cpp +++ b/tests/auto/qlistview/tst_qlistview.cpp @@ -1893,7 +1893,8 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); - QPoint p = view.visualRect(model.index(model.rowCount() - 1)).center() + QPoint(0, 20); + const QRect itemRect = view.visualRect(model.index(model.rowCount() - 1)); + QPoint p = view.visualRect(model.index(model.rowCount() - 1)).center() + QPoint(0, itemRect.height()); //first the left button QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p); QVERIFY(!view.selectionModel()->hasSelection()); diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index 3b62d64..2b7eaae 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -140,6 +140,11 @@ private slots: #endif void ampm(); + void currency(); + void quoteString(); + void uiLanguages(); + void weekendDays(); + void listPatterns(); private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; @@ -181,6 +186,7 @@ void tst_QLocale::ctor() QCOMPARE(l.language(), QLocale::C); QCOMPARE(l.country(), QLocale::AnyCountry); } + TEST_CTOR(AnyLanguage, AnyCountry, default_lang, default_country) TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) TEST_CTOR(Aymara, AnyCountry, default_lang, default_country) TEST_CTOR(Aymara, France, default_lang, default_country) @@ -306,6 +312,7 @@ void tst_QLocale::ctor() TEST_CTOR("en@", English, UnitedStates) TEST_CTOR("en.@", English, UnitedStates) TEST_CTOR("en_", English, UnitedStates) + TEST_CTOR("en_U", English, UnitedStates) TEST_CTOR("en_.", English, UnitedStates) TEST_CTOR("en_.@", English, UnitedStates) TEST_CTOR("en.bla", English, UnitedStates) @@ -316,6 +323,8 @@ void tst_QLocale::ctor() TEST_CTOR("en_GB.bla", English, UnitedKingdom) TEST_CTOR("en_GB@.bla", English, UnitedKingdom) TEST_CTOR("en_GB@bla", English, UnitedKingdom) + TEST_CTOR("en-GB", English, UnitedKingdom) + TEST_CTOR("en-GB@bla", English, UnitedKingdom) Q_ASSERT(QLocale::Norwegian == QLocale::NorwegianBokmal); TEST_CTOR("no", Norwegian, Norway) @@ -326,13 +335,38 @@ void tst_QLocale::ctor() TEST_CTOR("nn_NO", NorwegianNynorsk, Norway) TEST_CTOR("es_ES", Spanish, Spain) TEST_CTOR("es_419", Spanish, LatinAmericaAndTheCaribbean) + TEST_CTOR("es-419", Spanish, LatinAmericaAndTheCaribbean) // test default countries for languages + TEST_CTOR("zh", Chinese, China) + TEST_CTOR("zh-Hans", Chinese, China) TEST_CTOR("mn", Mongolian, Mongolia) TEST_CTOR("ne", Nepali, Nepal) #undef TEST_CTOR +#define TEST_CTOR(req_lc, exp_lang, exp_script, exp_country) \ + { \ + QLocale l(req_lc); \ + QVERIFY2(l.language() == QLocale::exp_lang \ + && l.script() == QLocale::exp_script \ + && l.country() == QLocale::exp_country, \ + QString("requested: \"" + QString(req_lc) + "\", got: " \ + + QLocale::languageToString(l.language()) \ + + "/" + QLocale::scriptToString(l.script()) \ + + "/" + QLocale::countryToString(l.country())).toLatin1().constData()); \ + } + + TEST_CTOR("zh_CN", Chinese, AnyScript, China) + TEST_CTOR("zh_Hans_CN", Chinese, SimplifiedHanScript, China) + TEST_CTOR("zh_Hans", Chinese, SimplifiedHanScript, China) + TEST_CTOR("zh_Hant", Chinese, TraditionalHanScript, HongKong) + TEST_CTOR("zh_Hans_MO", Chinese, SimplifiedHanScript, Macau) + TEST_CTOR("zh_Hant_MO", Chinese, TraditionalHanScript, Macau) + TEST_CTOR("az_Latn_AZ", Azerbaijani, LatinScript, Azerbaijan) + TEST_CTOR("ha_Arab_NG", Hausa, ArabicScript, Nigeria) + TEST_CTOR("ha_Latn_NG", Hausa, LatinScript, Nigeria) +#undef TEST_CTOR } void tst_QLocale::emptyCtor() @@ -405,11 +439,12 @@ void tst_QLocale::emptyCtor() TEST_CTOR("nb_NO", "nb_NO") TEST_CTOR("nn_NO", "nn_NO") + TEST_CTOR("DE", "de_DE"); + TEST_CTOR("EN", "en_US"); + TEST_CTOR("en/", defaultLoc) - TEST_CTOR("DE", defaultLoc); TEST_CTOR("asdfghj", defaultLoc); TEST_CTOR("123456", defaultLoc); - TEST_CTOR("EN", defaultLoc); #undef TEST_CTOR #endif @@ -1095,6 +1130,11 @@ void tst_QLocale::macDefaultLocale() const QString timeString = locale.toString(QTime(1,2,3), QLocale::LongFormat); QVERIFY(timeString.contains(QString("1:02:03"))); + QCOMPARE(locale.toCurrencyString(qulonglong(1234)), QString("$1,234.00")); + QCOMPARE(locale.toCurrencyString(qlonglong(-1234)), QString("($1,234.00)")); + QCOMPARE(locale.toCurrencyString(double(1234.56)), QString("$1,234.56")); + QCOMPARE(locale.toCurrencyString(double(-1234.56)), QString("($1,234.56)")); + // Depending on the configured time zone, the time string might not // contain a GMT specifier. (Sometimes it just names the zone, like "CEST") if (timeString.contains(QString("GMT"))) { @@ -1117,6 +1157,13 @@ void tst_QLocale::macDefaultLocale() QCOMPARE(locale.dayName(7), QString("Sunday")); QCOMPARE(locale.monthName(1), QString("January")); QCOMPARE(locale.monthName(12), QString("December")); + QCOMPARE(locale.firstDayOfWeek(), Qt::Sunday); + QCOMPARE(locale.quoteString("string"), QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d")); + QCOMPARE(locale.quoteString("string", QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99")); + + QList<Qt::DayOfWeek> days; + days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; + QCOMPARE(locale.weekdays(), days); } @@ -1772,6 +1819,7 @@ void tst_QLocale::measurementSystems_data() void tst_QLocale::measurementSystems() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); QFETCH(QString, localeName); QFETCH(int, mSystem); @@ -1833,6 +1881,7 @@ void tst_QLocale::systemMeasurementSystems_data() void tst_QLocale::systemMeasurementSystems() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); // Theoretically, we could include HPUX in this test, but its setenv implementation // stinks. It's called putenv, and it requires you to keep the variable you pass // to it around forever. @@ -1955,6 +2004,7 @@ void tst_QLocale::queryMeasureSystem_data() void tst_QLocale::queryMeasureSystem() { + QSKIP("Meh, skip the test as we do not reread the environment variables anymore", SkipAll); // Theoretically, we could include HPUX in this test, but its setenv implementation // stinks. It's called putenv, and it requires you to keep the variable you pass // to it around forever. @@ -2070,6 +2120,10 @@ void tst_QLocale::monthName() QCOMPARE(ru.monthName(1, QLocale::LongFormat), QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217")); QCOMPARE(ru.monthName(1, QLocale::ShortFormat), QString::fromUtf8("\321\217\320\275\320\262\56")); QCOMPARE(ru.monthName(1, QLocale::NarrowFormat), QString::fromUtf8("\320\257")); + + // check that our CLDR scripts handle surrogate pairs correctly + QLocale dsrt("en-Dsrt-US"); + QCOMPARE(dsrt.monthName(1, QLocale::LongFormat), QString::fromUtf8("\xf0\x90\x90\x96\xf0\x90\x90\xb0\xf0\x90\x91\x8c\xf0\x90\x90\xb7\xf0\x90\x90\xad\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xa8")); } void tst_QLocale::standaloneMonthName() @@ -2127,5 +2181,102 @@ void tst_QLocale::symbianSystemLocale() } #endif +void tst_QLocale::currency() +{ + const QLocale c(QLocale::C); + QCOMPARE(c.toCurrencyString(qulonglong(1234)), QString("1234")); + QCOMPARE(c.toCurrencyString(qlonglong(-1234)), QString("-1234")); + QCOMPARE(c.toCurrencyString(double(1234.56)), QString("1234.56")); + QCOMPARE(c.toCurrencyString(double(-1234.56)), QString("-1234.56")); + + const QLocale ru_RU("ru_RU"); + QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1234\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1234\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(double(1234.56)), QString::fromUtf8("1234,56\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1234,56\xc2\xa0\xd1\x80\xd1\x83\xd0\xb1.")); + + const QLocale de_DE("de_DE"); + QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)), QString::fromUtf8("1234\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ")), QString::fromUtf8("1234\xc2\xa0" "BAZ")); + QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)), QString::fromUtf8("-1234\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ")), QString::fromUtf8("-1234\xc2\xa0" "BAZ")); + QCOMPARE(de_DE.toCurrencyString(double(1234.56)), QString::fromUtf8("1234,56\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), QString::fromUtf8("-1234,56\xc2\xa0\xe2\x82\xac")); + QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ")), QString::fromUtf8("-1234,56\xc2\xa0" "BAZ")); + + const QLocale system = QLocale::system(); + QVERIFY(system.toCurrencyString(1, QLatin1String("FOO")).contains(QLatin1String("FOO"))); +} + +void tst_QLocale::quoteString() +{ + const QString someText("text"); + const QLocale c(QLocale::C); + QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22")); + QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\x27" "text" "\x27")); + + const QLocale de_CH("de_CH"); + QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xc2\xab" "text" "\xc2\xbb")); + QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), QString::fromUtf8("\xe2\x80\xb9" "text" "\xe2\x80\xba")); + +} + +void tst_QLocale::uiLanguages() +{ + const QLocale c(QLocale::C); + QCOMPARE(c.uiLanguages().size(), 1); + QCOMPARE(c.uiLanguages().at(0), QLatin1String("C")); + + const QLocale en_US("en_US"); + QCOMPARE(en_US.uiLanguages().size(), 1); + QCOMPARE(en_US.uiLanguages().at(0), QLatin1String("en-US")); + + const QLocale ru_RU("ru_RU"); + QCOMPARE(ru_RU.uiLanguages().size(), 1); + QCOMPARE(ru_RU.uiLanguages().at(0), QLatin1String("ru-RU")); +} + +void tst_QLocale::weekendDays() +{ + const QLocale c(QLocale::C); + QList<Qt::DayOfWeek> days; + days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; + QCOMPARE(c.weekdays(), days); +} + +void tst_QLocale::listPatterns() +{ + QStringList sl1; + QStringList sl2; + sl2 << "aaa"; + QStringList sl3; + sl3 << "aaa" << "bbb"; + QStringList sl4; + sl4 << "aaa" << "bbb" << "ccc"; + QStringList sl5; + sl5 << "aaa" << "bbb" << "ccc" << "ddd"; + + const QLocale c(QLocale::C); + QCOMPARE(c.createSeparatedList(sl1), QString("")); + QCOMPARE(c.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(c.createSeparatedList(sl3), QString("aaa, bbb")); + QCOMPARE(c.createSeparatedList(sl4), QString("aaa, bbb, ccc")); + QCOMPARE(c.createSeparatedList(sl5), QString("aaa, bbb, ccc, ddd")); + + const QLocale en_US("en_US"); + QCOMPARE(en_US.createSeparatedList(sl1), QString("")); + QCOMPARE(en_US.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(en_US.createSeparatedList(sl3), QString("aaa and bbb")); + QCOMPARE(en_US.createSeparatedList(sl4), QString("aaa, bbb, and ccc")); + QCOMPARE(en_US.createSeparatedList(sl5), QString("aaa, bbb, ccc, and ddd")); + + const QLocale zh_CN("zh_CN"); + QCOMPARE(zh_CN.createSeparatedList(sl1), QString("")); + QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa")); + QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb")); + QCOMPARE(zh_CN.createSeparatedList(sl4), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc")); + QCOMPARE(zh_CN.createSeparatedList(sl5), QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" "ccc" "\xe5\x92\x8c" "ddd")); +} + QTEST_APPLESS_MAIN(tst_QLocale) #include "tst_qlocale.moc" diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index d496c56..13e3bcd 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -175,6 +175,9 @@ private slots: void metaMethod(); + void indexOfMethod_data(); + void indexOfMethod(); + signals: void value6Changed(); void value7Changed(const QString &); @@ -1077,5 +1080,31 @@ void tst_QMetaObject::metaMethod() QCOMPARE(obj.slotResult, QString("sl13")); } +void tst_QMetaObject::indexOfMethod_data() +{ + QTest::addColumn<QObject *>("object"); + QTest::addColumn<QByteArray>("name"); + QTest::addColumn<bool>("isSignal"); + QTest::newRow("indexOfMethod_data") << (QObject*)this << QByteArray("indexOfMethod_data()") << false; + QTest::newRow("deleteLater") << (QObject*)this << QByteArray("deleteLater()") << false; + QTest::newRow("value6changed") << (QObject*)this << QByteArray("value6Changed()") << true; + QTest::newRow("value7changed") << (QObject*)this << QByteArray("value7Changed(QString)") << true; + QTest::newRow("destroyed") << (QObject*)this << QByteArray("destroyed()") << true; + QTest::newRow("destroyed2") << (QObject*)this << QByteArray("destroyed(QObject*)") << true; +} + +void tst_QMetaObject::indexOfMethod() +{ + QFETCH(QObject *, object); + QFETCH(QByteArray, name); + QFETCH(bool, isSignal); + int idx = object->metaObject()->indexOfMethod(name); + QVERIFY(idx >= 0); + QCOMPARE(object->metaObject()->method(idx).signature(), name.constData()); + QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx); + QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx); +} + + QTEST_MAIN(tst_QMetaObject) #include "tst_qmetaobject.moc" diff --git a/tests/auto/qnativesocketengine/.gitignore b/tests/auto/qnativesocketengine/.gitignore deleted file mode 100644 index 4700e5e..0000000 --- a/tests/auto/qnativesocketengine/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qnativesocketengine diff --git a/tests/auto/qnativesocketengine/qnativesocketengine.pro b/tests/auto/qnativesocketengine/qnativesocketengine.pro deleted file mode 100644 index 0275d37..0000000 --- a/tests/auto/qnativesocketengine/qnativesocketengine.pro +++ /dev/null @@ -1,13 +0,0 @@ -load(qttest_p4) -SOURCES += tst_qnativesocketengine.cpp - -include(../qnativesocketengine/qsocketengine.pri) - -requires(contains(QT_CONFIG,private_tests)) - -MOC_DIR=tmp - -QT = core network - -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp index 42bb069..f7c5ca1 100644 --- a/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp +++ b/tests/auto/qnetworkaccessmanager_and_qprogressdialog/tst_qnetworkaccessmanager_and_qprogressdialog.cpp @@ -58,6 +58,7 @@ public: tst_QNetworkAccessManager_And_QProgressDialog(); private slots: void downloadCheck(); + void downloadCheck_data(); }; class DownloadCheckWidget : public QWidget @@ -72,9 +73,14 @@ public: QMetaObject::invokeMethod(this, "go", Qt::QueuedConnection); } bool lateReadyRead; + bool zeroCopy; public slots: void go() { + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile")); + if (zeroCopy) + request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 10*1024*1024); + QNetworkReply *reply = netmanager.get( QNetworkRequest( QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/bigfile") @@ -106,20 +112,30 @@ public slots: QTestEventLoop::instance().exitLoop(); } - private: QProgressDialog progressDlg; QNetworkAccessManager netmanager; }; + tst_QNetworkAccessManager_And_QProgressDialog::tst_QNetworkAccessManager_And_QProgressDialog() { Q_SET_DEFAULT_IAP } +void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck_data() +{ + QTest::addColumn<bool>("useZeroCopy"); + QTest::newRow("with-zeroCopy") << true; + QTest::newRow("without-zeroCopy") << false; +} + void tst_QNetworkAccessManager_And_QProgressDialog::downloadCheck() { + QFETCH(bool, useZeroCopy); + DownloadCheckWidget widget; + widget.zeroCopy = useZeroCopy; widget.show(); // run and exit on finished() QTestEventLoop::instance().enterLoop(10); diff --git a/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro b/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro index 77ad347..ae0941e 100644 --- a/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro +++ b/tests/auto/qnetworkcachemetadata/qnetworkcachemetadata.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui QT += network SOURCES += tst_qnetworkcachemetadata.cpp diff --git a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp index adcfd93..c31eac7 100644 --- a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp +++ b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp @@ -52,7 +52,7 @@ */ #include <QNetworkAccessManager> -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include <stdio.h> #include <iapconf.h> #endif @@ -73,7 +73,7 @@ private slots: void isRoamingAvailable(); private: -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -85,7 +85,7 @@ private: void tst_QNetworkConfiguration::initTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -158,7 +158,7 @@ void tst_QNetworkConfiguration::initTestCase() void tst_QNetworkConfiguration::cleanupTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); diff --git a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp index 443fd18..7787608 100644 --- a/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp +++ b/tests/auto/qnetworkconfigurationmanager/tst_qnetworkconfigurationmanager.cpp @@ -45,7 +45,7 @@ #include <QtNetwork/qnetworkconfiguration.h> #include <QtNetwork/qnetworkconfigmanager.h> -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include <stdio.h> #include <iapconf.h> #endif @@ -67,7 +67,7 @@ private slots: void configurationFromIdentifier(); private: -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -79,7 +79,7 @@ private: void tst_QNetworkConfigurationManager::initTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -153,7 +153,7 @@ void tst_QNetworkConfigurationManager::initTestCase() void tst_QNetworkConfigurationManager::cleanupTestCase() { -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); diff --git a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp index 91dfe47..e0c477b 100644 --- a/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp +++ b/tests/auto/qnetworkcookie/tst_qnetworkcookie.cpp @@ -707,6 +707,7 @@ void tst_QNetworkCookie::parseMultipleCookies_data() cookie.setDomain("!@#$%^&*();:."); // the ';' is actually problematic, because it is a separator list = QList<QNetworkCookie>(); QTest::newRow("domain-non-alpha-numeric") << "NonAlphNumDomName=NonAlphNumDomValue; domain=!@#$%^&*()" << list; + QTest::newRow("expiration-3digit1") << "a=b; expires=123" << list; // used to ASSERT } void tst_QNetworkCookie::parseMultipleCookies() diff --git a/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro index 3b13087..c05171d 100644 --- a/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro +++ b/tests/auto/qnetworkdiskcache/qnetworkdiskcache.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui QT += network SOURCES += tst_qnetworkdiskcache.cpp diff --git a/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp index e974fcc..78b5f1b 100644 --- a/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp +++ b/tests/auto/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -46,6 +46,8 @@ #include "../../shared/util.h" #define EXAMPLE_URL "http://user:pass@www.example.com/#foo" +//cached objects are organized into these many subdirs +#define NUM_SUBDIRECTORIES 16 class tst_QNetworkDiskCache : public QObject { @@ -176,10 +178,10 @@ void tst_QNetworkDiskCache::initTestCase() cache.clear(); QString s = QDir::tempPath() + "/diskCache/"; QDir dir; - dir.rmdir(s + "http"); - dir.rmdir(s + "https"); + dir.rmdir(s + "data7"); // the number is the internal cache version dir.rmdir(s + "prepared"); dir.rmdir(s); + dir.rmdir(s + "http"); // delete directory used by 4.7 and earlier (would make the tests fail) } // This will be called after the last test function is executed. @@ -277,16 +279,16 @@ void tst_QNetworkDiskCache::clear() QVERIFY(cache.cacheSize() > qint64(0)); QString cacheDirectory = cache.cacheDirectory(); - QCOMPARE(countFiles(cacheDirectory).count(), 3); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); cache.clear(); - QCOMPARE(countFiles(cacheDirectory).count(), 2); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2); // don't delete files that it didn't create - QTemporaryFile file(cacheDirectory + "/cache_XXXXXX"); + QTemporaryFile file(cacheDirectory + "/XXXXXX"); if (file.open()) { - QCOMPARE(countFiles(cacheDirectory).count(), 3); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); cache.clear(); - QCOMPARE(countFiles(cacheDirectory).count(), 3); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); } } @@ -309,20 +311,11 @@ void tst_QNetworkDiskCache::data_data() // public QIODevice* data(QUrl const& url) void tst_QNetworkDiskCache::data() { -#ifdef Q_OS_SYMBIAN - QSKIP("Due to mmap(...) bug in Open C [Temtrack DEF142242]", SkipAll); -#endif QFETCH(QNetworkCacheMetaData, data); SubQNetworkDiskCache cache; QUrl url(EXAMPLE_URL); cache.setupWithOne(url, data); - // flush the cache - QTemporaryFile file(cache.cacheDirectory() + "/cache_XXXXXX.cache"); - if (file.open()) { - cache.call_fileMetaData(file.fileName()); - } - for (int i = 0; i < 3; ++i) { QIODevice *d = cache.data(url); QVERIFY(d); @@ -362,9 +355,9 @@ void tst_QNetworkDiskCache::remove() QUrl url(EXAMPLE_URL); cache.setupWithOne(url); QString cacheDirectory = cache.cacheDirectory(); - QCOMPARE(countFiles(cacheDirectory).count(), 3); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 3); cache.remove(url); - QCOMPARE(countFiles(cacheDirectory).count(), 2); + QCOMPARE(countFiles(cacheDirectory).count(), NUM_SUBDIRECTORIES + 2); } void tst_QNetworkDiskCache::setCacheDirectory_data() @@ -388,9 +381,6 @@ void tst_QNetworkDiskCache::setCacheDirectory() // public void updateMetaData(QNetworkCacheMetaData const& metaData) void tst_QNetworkDiskCache::updateMetaData() { -#ifdef Q_OS_SYMBIAN - QSKIP("Due to mmap(...) bug in Open C [Temtrack DEF142242]", SkipAll); -#endif QUrl url(EXAMPLE_URL); SubQNetworkDiskCache cache; cache.setupWithOne(url); @@ -414,7 +404,7 @@ void tst_QNetworkDiskCache::fileMetaData() QString cacheDirectory = cache.cacheDirectory(); QStringList list = countFiles(cacheDirectory); - QCOMPARE(list.count(), 3); + QCOMPARE(list.count(), NUM_SUBDIRECTORIES + 3); foreach(QString fileName, list) { QFileInfo info(fileName); if (info.isFile()) { @@ -491,7 +481,7 @@ void tst_QNetworkDiskCache::oldCacheVersionFile() if (pass == 0) { QString name; { - QTemporaryFile file(cache.cacheDirectory() + "/cache_XXXXXX.cache"); + QTemporaryFile file(cache.cacheDirectory() + "/XXXXXX.d"); file.setAutoRemove(false); QVERIFY(file.open()); QDataStream out(&file); @@ -507,7 +497,7 @@ void tst_QNetworkDiskCache::oldCacheVersionFile() QVERIFY(!QFile::exists(name)); } else { QStringList files = countFiles(cache.cacheDirectory()); - QCOMPARE(files.count(), 3); + QCOMPARE(files.count(), NUM_SUBDIRECTORIES + 3); // find the file QString cacheFile; foreach (QString file, files) { diff --git a/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp index 0d7c68e..c630eca 100644 --- a/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp +++ b/tests/auto/qnetworkinterface/tst_qnetworkinterface.cpp @@ -45,6 +45,8 @@ #include <qcoreapplication.h> #include <qnetworkinterface.h> #include <qtcpsocket.h> +#include <QNetworkConfigurationManager> +#include <QNetworkSession> #include "../network-settings.h" //TESTED_FILES=qnetworkinterface.cpp qnetworkinterface.h qnetworkinterface_unix.cpp qnetworkinterface_win.cpp @@ -58,23 +60,52 @@ public: virtual ~tst_QNetworkInterface(); private slots: + void initTestCase(); + void cleanupTestCase(); void dump(); void loopbackIPv4(); void loopbackIPv6(); void localAddress(); void interfaceFromXXX(); void copyInvalidInterface(); + +private: +#ifndef QT_NO_BEARER_MANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer<QNetworkSession> networkSession; +#endif }; tst_QNetworkInterface::tst_QNetworkInterface() { - Q_SET_DEFAULT_IAP } tst_QNetworkInterface::~tst_QNetworkInterface() { } +void tst_QNetworkInterface::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif +} + +void tst_QNetworkInterface::cleanupTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + if (networkSession && networkSession->isOpen()) { + networkSession->close(); + } +#endif +} void tst_QNetworkInterface::dump() { @@ -127,10 +158,6 @@ void tst_QNetworkInterface::loopbackIPv4() void tst_QNetworkInterface::loopbackIPv6() { -#ifdef Q_OS_SYMBIAN - QSKIP( "Symbian: IPv6 is not yet supported", SkipAll ); -#else - QList<QHostAddress> all = QNetworkInterface::allAddresses(); bool loopbackfound = false; @@ -144,7 +171,6 @@ void tst_QNetworkInterface::loopbackIPv6() anyIPv6 = true; QVERIFY(!anyIPv6 || loopbackfound); -#endif } void tst_QNetworkInterface::localAddress() diff --git a/tests/auto/qnetworkreply/image1.jpg b/tests/auto/qnetworkreply/image1.jpg Binary files differnew file mode 100644 index 0000000..dba31c1 --- /dev/null +++ b/tests/auto/qnetworkreply/image1.jpg diff --git a/tests/auto/qnetworkreply/image2.jpg b/tests/auto/qnetworkreply/image2.jpg Binary files differnew file mode 100644 index 0000000..72936e2 --- /dev/null +++ b/tests/auto/qnetworkreply/image2.jpg diff --git a/tests/auto/qnetworkreply/image3.jpg b/tests/auto/qnetworkreply/image3.jpg Binary files differnew file mode 100644 index 0000000..cede519 --- /dev/null +++ b/tests/auto/qnetworkreply/image3.jpg diff --git a/tests/auto/qnetworkreply/test/test.pro b/tests/auto/qnetworkreply/test/test.pro index 7efc2fb..d1f6707 100644 --- a/tests/auto/qnetworkreply/test/test.pro +++ b/tests/auto/qnetworkreply/test/test.pro @@ -1,4 +1,5 @@ load(qttest_p4) +QT -= gui SOURCES += ../tst_qnetworkreply.cpp TARGET = ../tst_qnetworkreply @@ -15,24 +16,21 @@ win32 { QT = core network RESOURCES += ../qnetworkreply.qrc -wince*: { - addFiles.files = ../empty ../rfc3252.txt ../resource - addFiles.path = . - DEPLOYMENT += addFiles -} - -symbian:{ - addFiles.files = ../empty ../rfc3252.txt ../resource ../bigfile +symbian|wince*:{ + # For cross compiled targets, reference data files need to be deployed + addFiles.files = ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg addFiles.path = . DEPLOYMENT += addFiles certFiles.files = ../certs certFiles.path = . DEPLOYMENT += certFiles +} +symbian:{ # Symbian toolchain does not support correct include semantics INCLUDEPATH+=..\\..\\..\\..\\include\\QtNetwork\\private # bigfile test case requires more heap - TARGET.EPOCHEAPSIZE="0x100 0x1000000" + TARGET.EPOCHEAPSIZE="0x100 0x10000000" TARGET.CAPABILITY="ALL -TCB" } diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 2c79951..f509cea 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -47,6 +47,7 @@ #include <QtCore/QEventLoop> #include <QtCore/QFile> #include <QtCore/QSharedPointer> +#include <QtCore/QScopedPointer> #include <QtCore/QTemporaryFile> #include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpSocket> @@ -60,10 +61,17 @@ #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> #include <QtNetwork/qnetworkcookie.h> +#include <QtNetwork/QHttpPart> +#include <QtNetwork/QHttpMultiPart> #ifndef QT_NO_OPENSSL #include <QtNetwork/qsslerror.h> #include <QtNetwork/qsslconfiguration.h> #endif +#ifndef QT_NO_BEARERMANAGEMENT +#include <QtNetwork/qnetworkconfigmanager.h> +#include <QtNetwork/qnetworkconfiguration.h> +#include <QtNetwork/qnetworksession.h> +#endif #include <time.h> @@ -83,6 +91,11 @@ Q_DECLARE_METATYPE(QNetworkProxyQuery) Q_DECLARE_METATYPE(QList<QNetworkProxy>) Q_DECLARE_METATYPE(QNetworkReply::NetworkError) Q_DECLARE_METATYPE(QBuffer*) +Q_DECLARE_METATYPE(QHttpMultiPart *) +Q_DECLARE_METATYPE(QList<QFile*>) // for multiparts +#ifndef QT_NO_OPENSSL +Q_DECLARE_METATYPE(QSslConfiguration) +#endif class QNetworkReplyPtr: public QSharedPointer<QNetworkReply> { @@ -133,12 +146,19 @@ class tst_QNetworkReply: public QObject QSslConfiguration storedSslConfiguration; QList<QSslError> storedExpectedSslErrors; #endif +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QScopedPointer<QNetworkSession> networkSession; +#endif public: tst_QNetworkReply(); ~tst_QNetworkReply(); QString runSimpleRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QNetworkReplyPtr &reply, const QByteArray &data = QByteArray()); + QString runMultipartRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply, + QHttpMultiPart *multiPart, const QByteArray &verb); QString runCustomRequest(const QNetworkRequest &request, QNetworkReplyPtr &reply, const QByteArray &verb, QIODevice *data); @@ -185,10 +205,14 @@ private Q_SLOTS: void putToHttp(); void putToHttpSynchronous_data(); void putToHttpSynchronous(); + void putToHttpMultipart_data(); + void putToHttpMultipart(); void postToHttp_data(); void postToHttp(); void postToHttpSynchronous_data(); void postToHttpSynchronous(); + void postToHttpMultipart_data(); + void postToHttpMultipart(); void deleteFromHttp_data(); void deleteFromHttp(); void putGetDeleteGetFromHttp_data(); @@ -309,6 +333,8 @@ private Q_SLOTS: void ignoreSslErrorsList(); void ignoreSslErrorsListWithSlot_data(); void ignoreSslErrorsListWithSlot(); + void sslConfiguration_data(); + void sslConfiguration(); #endif void getAndThenDeleteObject_data(); @@ -337,6 +363,8 @@ private Q_SLOTS: void qtbug15311doubleContentLength(); + void qtbug18232gzipContentLengthZero(); + void synchronousRequest_data(); void synchronousRequest(); #ifndef QT_NO_OPENSSL @@ -416,16 +444,23 @@ public: QTcpSocket *client; // always the last one that was received QByteArray dataToTransmit; QByteArray receivedData; + QSemaphore ready; bool doClose; bool doSsl; bool multiple; int totalConnections; - MiniHttpServer(const QByteArray &data, bool ssl = false) + MiniHttpServer(const QByteArray &data, bool ssl = false, QThread *thread = 0) : client(0), dataToTransmit(data), doClose(true), doSsl(ssl), multiple(false), totalConnections(0) { listen(); + if (thread) { + connect(thread, SIGNAL(started()), this, SLOT(threadStartedSlot())); + moveToThread(thread); + thread->start(); + ready.acquire(); + } } protected: @@ -502,6 +537,11 @@ public slots: disconnect(client, 0, this, 0); } } + + void threadStartedSlot() + { + ready.release(); + } }; class MyCookieJar: public QNetworkCookieJar @@ -1090,6 +1130,38 @@ void tst_QNetworkReply::storeSslConfiguration() } #endif +QString tst_QNetworkReply::runMultipartRequest(const QNetworkRequest &request, + QNetworkReplyPtr &reply, + QHttpMultiPart *multiPart, + const QByteArray &verb) +{ + if (verb == "POST") + reply = manager.post(request, multiPart); + else + reply = manager.put(request, multiPart); + + // the code below is copied from tst_QNetworkReply::runSimpleRequest, see below + reply->setParent(this); + connect(reply, SIGNAL(finished()), SLOT(finished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(gotError())); + multiPart->setParent(reply); + + returnCode = Timeout; + loop = new QEventLoop; + QTimer::singleShot(25000, loop, SLOT(quit())); + int code = returnCode == Timeout ? loop->exec() : returnCode; + delete loop; + loop = 0; + + switch (code) { + case Failure: + return "Request failed: " + reply->errorString(); + case Timeout: + return "Network timeout"; + } + return QString(); +} + QString tst_QNetworkReply::runSimpleRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QNetworkReplyPtr &reply, @@ -1197,6 +1269,18 @@ void tst_QNetworkReply::initTestCase() #endif QDir::setSearchPaths("srcdir", QStringList() << SRCDIR); +#ifndef QT_NO_OPENSSL + QSslSocket::defaultCaCertificates(); //preload certificates +#endif +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession.reset(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif } void tst_QNetworkReply::cleanupTestCase() @@ -1204,6 +1288,9 @@ void tst_QNetworkReply::cleanupTestCase() #if !defined Q_OS_WIN QFile::remove(wronlyFileName); #endif + if (networkSession && networkSession->isOpen()) { + networkSession->close(); + } } void tst_QNetworkReply::init() @@ -1563,7 +1650,7 @@ void tst_QNetworkReply::getErrors() QNetworkRequest request(url); #if defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN) - if (qstrcmp(QTest::currentDataTag(), "empty-scheme-host") == 0) + if (qstrcmp(QTest::currentDataTag(), "empty-scheme-host") == 0 && QFileInfo(url).isAbsolute()) QTest::ignoreMessage(QtWarningMsg, "QNetworkAccessFileBackendFactory: URL has no schema set, use file:// for files"); #endif @@ -1582,7 +1669,8 @@ void tst_QNetworkReply::getErrors() QFETCH(int, error); #if defined(Q_OS_WIN) || defined (Q_OS_SYMBIAN) - QEXPECT_FAIL("empty-scheme-host", "this is expected to fail on Windows and Symbian, QTBUG-17731", Abort); + if (QFileInfo(url).isAbsolute()) + QEXPECT_FAIL("empty-scheme-host", "this is expected to fail on Windows and Symbian, QTBUG-17731", Abort); #endif QEXPECT_FAIL("ftp-is-dir", "QFtp cannot provide enough detail", Abort); // the line below is not necessary @@ -1788,6 +1876,7 @@ void tst_QNetworkReply::postToHttp() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply; QFETCH(QByteArray, data); @@ -1814,6 +1903,7 @@ void tst_QNetworkReply::postToHttpSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, @@ -1835,6 +1925,307 @@ void tst_QNetworkReply::postToHttpSynchronous() QCOMPARE(uploadedData, md5sum.toHex()); } +void tst_QNetworkReply::postToHttpMultipart_data() +{ + QTest::addColumn<QUrl>("url"); + QTest::addColumn<QHttpMultiPart *>("multiPart"); + QTest::addColumn<QByteArray>("expectedReplyData"); + QTest::addColumn<QByteArray>("contentType"); + + QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/multipart.cgi"); + QByteArray expectedData; + + + // empty parts + + QHttpMultiPart *emptyMultiPart = new QHttpMultiPart; + QTest::newRow("empty") << url << emptyMultiPart << expectedData << QByteArray("mixed"); + + QHttpMultiPart *emptyRelatedMultiPart = new QHttpMultiPart; + emptyRelatedMultiPart->setContentType(QHttpMultiPart::RelatedType); + QTest::newRow("empty-related") << url << emptyRelatedMultiPart << expectedData << QByteArray("related"); + + QHttpMultiPart *emptyAlternativeMultiPart = new QHttpMultiPart; + emptyAlternativeMultiPart->setContentType(QHttpMultiPart::AlternativeType); + QTest::newRow("empty-alternative") << url << emptyAlternativeMultiPart << expectedData << QByteArray("alternative"); + + + // text-only parts + + QHttpPart textPart; + textPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\"")); + textPart.setBody("7 bytes"); + QHttpMultiPart *multiPart1 = new QHttpMultiPart; + multiPart1->setContentType(QHttpMultiPart::FormDataType); + multiPart1->append(textPart); + expectedData = "key: text, value: 7 bytes\n"; + QTest::newRow("text") << url << multiPart1 << expectedData << QByteArray("form-data"); + + QHttpMultiPart *customMultiPart = new QHttpMultiPart; + customMultiPart->append(textPart); + expectedData = "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text\"'\n" + "content: 7 bytes\n" + "\n"; + QTest::newRow("text-custom") << url << customMultiPart << expectedData << QByteArray("custom"); + + QHttpPart textPart2; + textPart2.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart2.setRawHeader("myRawHeader", "myValue"); + textPart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text2\"")); + textPart2.setBody("some more bytes"); + textPart2.setBodyDevice((QIODevice *) 1); // test whether setting and unsetting of the device works + textPart2.setBodyDevice(0); + QHttpMultiPart *multiPart2 = new QHttpMultiPart; + multiPart2->setContentType(QHttpMultiPart::FormDataType); + multiPart2->append(textPart); + multiPart2->append(textPart2); + expectedData = "key: text2, value: some more bytes\n" + "key: text, value: 7 bytes\n"; + QTest::newRow("text-text") << url << multiPart2 << expectedData << QByteArray("form-data"); + + + QHttpPart textPart3; + textPart3.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); + textPart3.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text3\"")); + textPart3.setRawHeader("Content-Location", "http://my.test.location.tld"); + textPart3.setBody("even more bytes"); + QHttpMultiPart *multiPart3 = new QHttpMultiPart; + multiPart3->setContentType(QHttpMultiPart::AlternativeType); + multiPart3->append(textPart); + multiPart3->append(textPart2); + multiPart3->append(textPart3); + expectedData = "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text\"'\n" + "content: 7 bytes\n" + "\n" + "header: Content-Type, value: 'text/plain'\n" + "header: myRawHeader, value: 'myValue'\n" + "header: Content-Disposition, value: 'form-data; name=\"text2\"'\n" + "content: some more bytes\n" + "\n" + "header: Content-Type, value: 'text/plain'\n" + "header: Content-Disposition, value: 'form-data; name=\"text3\"'\n" + "header: Content-Location, value: 'http://my.test.location.tld'\n" + "content: even more bytes\n\n"; + QTest::newRow("text-text-text") << url << multiPart3 << expectedData << QByteArray("alternative"); + + + + // text and image parts + + QHttpPart imagePart11; + imagePart11.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart11.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage\"")); + imagePart11.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart11.setRawHeader("Content-ID", "my@id.tld"); + QFile *file11 = new QFile(SRCDIR "/image1.jpg"); + file11->open(QIODevice::ReadOnly); + imagePart11.setBodyDevice(file11); + QHttpMultiPart *imageMultiPart1 = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageMultiPart1->append(imagePart11); + file11->setParent(imageMultiPart1); + expectedData = "key: testImage, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"; // md5 sum of file + QTest::newRow("image") << url << imageMultiPart1 << expectedData << QByteArray("form-data"); + + QHttpPart imagePart21; + imagePart21.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart21.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\"")); + imagePart21.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart21.setRawHeader("Content-ID", "my@id.tld"); + QFile *file21 = new QFile(SRCDIR "/image1.jpg"); + file21->open(QIODevice::ReadOnly); + imagePart21.setBodyDevice(file21); + QHttpMultiPart *imageMultiPart2 = new QHttpMultiPart(); + imageMultiPart2->setContentType(QHttpMultiPart::FormDataType); + imageMultiPart2->append(textPart); + imageMultiPart2->append(imagePart21); + file21->setParent(imageMultiPart2); + QHttpPart imagePart22; + imagePart22.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart22.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\"")); + QFile *file22 = new QFile(SRCDIR "/image2.jpg"); + file22->open(QIODevice::ReadOnly); + imagePart22.setBodyDevice(file22); + imageMultiPart2->append(imagePart22); + file22->setParent(imageMultiPart2); + expectedData = "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n" + "key: text, value: 7 bytes\n" + "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n"; + QTest::newRow("text-image-image") << url << imageMultiPart2 << expectedData << QByteArray("form-data"); + + + QHttpPart imagePart31; + imagePart31.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart31.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage1\"")); + imagePart31.setRawHeader("Content-Location", "http://my.test.location.tld"); + imagePart31.setRawHeader("Content-ID", "my@id.tld"); + QFile *file31 = new QFile(SRCDIR "/image1.jpg"); + file31->open(QIODevice::ReadOnly); + imagePart31.setBodyDevice(file31); + QHttpMultiPart *imageMultiPart3 = new QHttpMultiPart(QHttpMultiPart::FormDataType); + imageMultiPart3->append(imagePart31); + file31->setParent(imageMultiPart3); + QHttpPart imagePart32; + imagePart32.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart32.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage2\"")); + QFile *file32 = new QFile(SRCDIR "/image2.jpg"); + file32->open(QIODevice::ReadOnly); + imagePart32.setBodyDevice(file31); // check that resetting works + imagePart32.setBodyDevice(file32); + imageMultiPart3->append(imagePart32); + file32->setParent(imageMultiPart3); + QHttpPart imagePart33; + imagePart33.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart33.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage3\"")); + QFile *file33 = new QFile(SRCDIR "/image3.jpg"); + file33->open(QIODevice::ReadOnly); + imagePart33.setBodyDevice(file33); + imageMultiPart3->append(imagePart33); + file33->setParent(imageMultiPart3); + expectedData = "key: testImage1, value: 87ef3bb319b004ba9e5e9c9fa713776e\n" + "key: testImage2, value: 483761b893f7fb1bd2414344cd1f3dfb\n" + "key: testImage3, value: ab0eb6fd4fcf8b4436254870b4513033\n"; + QTest::newRow("3-images") << url << imageMultiPart3 << expectedData << QByteArray("form-data"); + + + // note: nesting multiparts is not working currently; for that, the outputDevice would need to be public + +// QHttpPart imagePart41; +// imagePart41.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); +// QFile *file41 = new QFile(SRCDIR "/image1.jpg"); +// file41->open(QIODevice::ReadOnly); +// imagePart41.setBodyDevice(file41); +// +// QHttpMultiPart *innerMultiPart = new QHttpMultiPart(); +// innerMultiPart->setContentType(QHttpMultiPart::FormDataType); +// textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant()); +// innerMultiPart->append(textPart); +// innerMultiPart->append(imagePart41); +// textPart2.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant()); +// innerMultiPart->append(textPart2); +// +// QHttpPart nestedPart; +// nestedPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"nestedMessage")); +// nestedPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/alternative; boundary=\"" + innerMultiPart->boundary() + "\"")); +// innerMultiPart->outputDevice()->open(QIODevice::ReadOnly); +// nestedPart.setBodyDevice(innerMultiPart->outputDevice()); +// +// QHttpMultiPart *outerMultiPart = new QHttpMultiPart; +// outerMultiPart->setContentType(QHttpMultiPart::FormDataType); +// outerMultiPart->append(textPart); +// outerMultiPart->append(nestedPart); +// outerMultiPart->append(textPart2); +// expectedData = "nothing"; // the CGI.pm module running on the test server does not understand nested multiparts +// openFiles.clear(); +// openFiles << file41; +// QTest::newRow("nested") << url << outerMultiPart << expectedData << openFiles; + + + // test setting large chunks of content with a byte array instead of a device (DISCOURAGED because of high memory consumption, + // but we need to test that the behavior is correct) + QHttpPart imagePart51; + imagePart51.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); + imagePart51.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"testImage\"")); + QFile *file51 = new QFile(SRCDIR "/image1.jpg"); + file51->open(QIODevice::ReadOnly); + QByteArray imageData = file51->readAll(); + file51->close(); + delete file51; + imagePart51.setBody("7 bytes"); // check that resetting works + imagePart51.setBody(imageData); + QHttpMultiPart *imageMultiPart5 = new QHttpMultiPart; + imageMultiPart5->setContentType(QHttpMultiPart::FormDataType); + imageMultiPart5->append(imagePart51); + expectedData = "key: testImage, value: 87ef3bb319b004ba9e5e9c9fa713776e\n"; // md5 sum of file + QTest::newRow("image-as-content") << url << imageMultiPart5 << expectedData << QByteArray("form-data"); +} + +void tst_QNetworkReply::postToHttpMultipart() +{ + QFETCH(QUrl, url); + + static QSet<QByteArray> boundaries; + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + + QFETCH(QHttpMultiPart *, multiPart); + QFETCH(QByteArray, expectedReplyData); + QFETCH(QByteArray, contentType); + + // hack for testing the setting of the content-type header by hand: + if (contentType == "custom") { + QByteArray contentType("multipart/custom; boundary=\"" + multiPart->boundary() + "\""); + request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + } + + QVERIFY2(! boundaries.contains(multiPart->boundary()), "boundary '" + multiPart->boundary() + "' has been created twice"); + boundaries.insert(multiPart->boundary()); + + RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "POST")); + multiPart->deleteLater(); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QVERIFY(multiPart->boundary().count() > 20); // check that there is randomness after the "boundary_.oOo._" string + QVERIFY(multiPart->boundary().count() < 70); + QByteArray replyData = reply->readAll(); + + expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n"); +// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above + QCOMPARE(replyData, expectedReplyData); +} + +void tst_QNetworkReply::putToHttpMultipart_data() +{ + postToHttpMultipart_data(); +} + +void tst_QNetworkReply::putToHttpMultipart() +{ + QSKIP("test server script cannot handle PUT data yet", SkipAll); + QFETCH(QUrl, url); + + static QSet<QByteArray> boundaries; + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + + QFETCH(QHttpMultiPart *, multiPart); + QFETCH(QByteArray, expectedReplyData); + QFETCH(QByteArray, contentType); + + // hack for testing the setting of the content-type header by hand: + if (contentType == "custom") { + QByteArray contentType("multipart/custom; boundary=\"" + multiPart->boundary() + "\""); + request.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + } + + QVERIFY2(! boundaries.contains(multiPart->boundary()), "boundary '" + multiPart->boundary() + "' has been created twice"); + boundaries.insert(multiPart->boundary()); + + RUN_REQUEST(runMultipartRequest(request, reply, multiPart, "PUT")); + multiPart->deleteLater(); + + QCOMPARE(reply->url(), url); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); // 200 Ok + + QVERIFY(multiPart->boundary().count() > 20); // check that there is randomness after the "boundary_.oOo._" string + QVERIFY(multiPart->boundary().count() < 70); + QByteArray replyData = reply->readAll(); + + expectedReplyData.prepend("content type: multipart/" + contentType + "; boundary=\"" + multiPart->boundary() + "\"\n"); +// QEXPECT_FAIL("nested", "the server does not understand nested multipart messages", Continue); // see above + QCOMPARE(replyData, expectedReplyData); +} + void tst_QNetworkReply::deleteFromHttp_data() { QTest::addColumn<QUrl>("url"); @@ -3272,8 +3663,7 @@ void tst_QNetworkReply::ioPutToFileFromLocalSocket() QString socketname = "networkreplytest"; QLocalServer server; if (!server.listen(socketname)) { - if (QFile::exists(server.fullServerName())) - QFile::remove(server.fullServerName()); + QLocalServer::removeServer(socketname); QVERIFY(server.listen(socketname)); } QLocalSocket active; @@ -3318,7 +3708,7 @@ void tst_QNetworkReply::ioPutToFileFromProcess() { #if defined(Q_OS_WINCE) || defined (Q_OS_SYMBIAN) QSKIP("Currently no stdin/out supported for Windows CE / Symbian OS", SkipAll); -#endif +#else #ifdef Q_OS_WIN if (qstrcmp(QTest::currentDataTag(), "small") == 0) @@ -3356,6 +3746,7 @@ void tst_QNetworkReply::ioPutToFileFromProcess() QByteArray contents = file.readAll(); QCOMPARE(contents, data); #endif +#endif } void tst_QNetworkReply::ioPutToFtpFromFile_data() @@ -3469,6 +3860,8 @@ void tst_QNetworkReply::ioPostToHttpFromFile() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3545,8 +3938,10 @@ void tst_QNetworkReply::ioPostToHttpFromSocket() socketpair.endPoints[0]->write(data); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); + manager.setProxy(proxy); - QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), socketpair.endPoints[1]); + QNetworkReplyPtr reply = manager.post(request, socketpair.endPoints[1]); socketpair.endPoints[0]->close(); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3619,6 +4014,7 @@ void tst_QNetworkReply::ioPostToHttpFromSocketSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/md5sum.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, true); @@ -3648,7 +4044,8 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileToEnd() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); - QNetworkReplyPtr reply = manager.post(QNetworkRequest(url), &sourceFile); + request.setRawHeader("Content-Type", "application/octet-stream"); + QNetworkReplyPtr reply = manager.post(request, &sourceFile); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), @@ -3674,6 +4071,7 @@ void tst_QNetworkReply::ioPostToHttpFromMiddleOfFileFiveBytes() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); // only send 5 bytes request.setHeader(QNetworkRequest::ContentLengthHeader, 5); QVERIFY(request.header(QNetworkRequest::ContentLengthHeader).isValid()); @@ -3734,6 +4132,7 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag() QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi"; QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); // disallow buffering request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, true); request.setHeader(QNetworkRequest::ContentLengthHeader, data.size()); @@ -3796,6 +4195,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() // create the request QUrl url = QUrl(QString("https://127.0.0.1:%1/").arg(server.serverPort())); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply = manager.post(request, &sourceFile); QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); connect(&server, SIGNAL(newEncryptedConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -3814,14 +4214,8 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() // some progress should have been made QVERIFY(!spy.isEmpty()); QList<QVariant> args = spy.last(); - qDebug() << "tst_QNetworkReply::ioPostToHttpsUploadProgress" - << args.at(0).toLongLong() - << sourceFile.size() - << spy.size(); QVERIFY(args.at(0).toLongLong() > 0); - // FIXME this is where it messes up - QEXPECT_FAIL("", "Either the readBufferSize of QSslSocket is broken or we do upload too much. Hm.", Abort); QVERIFY(args.at(0).toLongLong() != sourceFile.size()); incomingSocket->setReadBufferSize(32*1024); @@ -3870,6 +4264,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp_data() void tst_QNetworkReply::ioGetFromBuiltinHttp() { + QSKIP("Limiting is broken right now, check QTBUG-15065", SkipAll); QFETCH(bool, https); QFETCH(int, bufferSize); @@ -3908,7 +4303,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); QTime loopTime; loopTime.start(); - QTestEventLoop::instance().enterLoop(11); + QTestEventLoop::instance().enterLoop(30); const int elapsedTime = loopTime.elapsed(); server.wait(); reader.wrapUp(); @@ -3940,10 +4335,9 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() const int minRate = rate * 1024 * (100-allowedDeviation) / 100; const int maxRate = rate * 1024 * (100+allowedDeviation) / 100; qDebug() << minRate << "<="<< server.transferRate << "<=" << maxRate << "?"; - QVERIFY(server.transferRate >= minRate); QEXPECT_FAIL("http+limited", "Limiting is broken right now, check QTBUG-15065", Continue); QEXPECT_FAIL("https+limited", "Limiting is broken right now, check QTBUG-15065", Continue); - QVERIFY(server.transferRate <= maxRate); + QVERIFY(server.transferRate >= minRate && server.transferRate <= maxRate); } } @@ -4018,6 +4412,7 @@ void tst_QNetworkReply::ioPostToHttpEmptyUploadProgress() // create the request QUrl url = QUrl(QString("http://127.0.0.1:%1/").arg(server.serverPort())); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply = manager.post(request, &buffer); QSignalSpy spy(reply, SIGNAL(uploadProgress(qint64,qint64))); connect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); @@ -4364,6 +4759,7 @@ void tst_QNetworkReply::receiveCookiesFromHttp() QByteArray data = cookieString.toLatin1() + '\n'; QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi"); QNetworkRequest request(url); + request.setRawHeader("Content-Type", "application/octet-stream"); QNetworkReplyPtr reply; RUN_REQUEST(runSimpleRequest(QNetworkAccessManager::PostOperation, request, reply, data)); @@ -4391,7 +4787,7 @@ void tst_QNetworkReply::receiveCookiesFromHttpSynchronous() QUrl url("http://" + QtNetworkSettings::serverName() + "/qtest/cgi-bin/set-cookie.cgi"); QNetworkRequest request(url); - + request.setRawHeader("Content-Type", "application/octet-stream"); request.setAttribute( QNetworkRequest::SynchronousRequestAttribute, true); @@ -4607,6 +5003,26 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous_data() httpProxyCommands_data(); } +struct QThreadCleanup +{ + static inline void cleanup(QThread *thread) + { + thread->quit(); + if (thread->wait(3000)) + delete thread; + else + qWarning("thread hung, leaking memory so test can finish"); + } +}; + +struct QDeleteLaterCleanup +{ + static inline void cleanup(QObject *o) + { + o->deleteLater(); + } +}; + void tst_QNetworkReply::httpProxyCommandsSynchronous() { QFETCH(QUrl, url); @@ -4616,11 +5032,9 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() // when using synchronous commands, we need a different event loop for // the server thread, because the client is never returning to the // event loop - MiniHttpServer proxyServer(responseToSend); - QThread serverThread; - proxyServer.moveToThread(&serverThread); - serverThread.start(); - QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort()); + QScopedPointer<QThread, QThreadCleanup> serverThread(new QThread); + QScopedPointer<MiniHttpServer, QDeleteLaterCleanup> proxyServer(new MiniHttpServer(responseToSend, false, serverThread.data())); + QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer->serverPort()); manager.setProxy(proxy); QNetworkRequest request(url); @@ -4633,8 +5047,6 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() QNetworkReplyPtr reply = manager.get(request); QVERIFY(reply->isFinished()); // synchronous manager.setProxy(QNetworkProxy()); - serverThread.quit(); - serverThread.wait(3000); //qDebug() << reply->error() << reply->errorString(); @@ -4642,7 +5054,7 @@ void tst_QNetworkReply::httpProxyCommandsSynchronous() // especially since it won't succeed in the HTTPS case // so just check that the command was correct - QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length()); + QString receivedHeader = proxyServer->receivedData.left(expectedCommand.length()); QCOMPARE(receivedHeader, expectedCommand); } @@ -5025,6 +5437,37 @@ void tst_QNetworkReply::ignoreSslErrorsListWithSlot() QCOMPARE(reply->error(), expectedNetworkError); } +void tst_QNetworkReply::sslConfiguration_data() +{ + QTest::addColumn<QSslConfiguration>("configuration"); + QTest::addColumn<bool>("works"); + + QTest::newRow("empty") << QSslConfiguration() << false; + QSslConfiguration conf = QSslConfiguration::defaultConfiguration(); + QTest::newRow("default") << conf << false; // does not contain test server cert + QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "/certs/qt-test-server-cacert.pem"); + conf.setCaCertificates(testServerCert); + QTest::newRow("set-root-cert") << conf << true; + conf.setProtocol(QSsl::SecureProtocols); + QTest::newRow("secure") << conf << true; +} + +void tst_QNetworkReply::sslConfiguration() +{ + QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html")); + QFETCH(QSslConfiguration, configuration); + request.setSslConfiguration(configuration); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QFETCH(bool, works); + QNetworkReply::NetworkError expectedError = works ? QNetworkReply::NoError : QNetworkReply::SslHandshakeFailedError; + QCOMPARE(reply->error(), expectedError); +} + #endif // QT_NO_OPENSSL void tst_QNetworkReply::getAndThenDeleteObject_data() @@ -5135,7 +5578,7 @@ void tst_QNetworkReply::getFromHttpIntoBuffer() // FIXME we really need to consolidate all those server implementations class GetFromHttpIntoBuffer2Server : QObject { - Q_OBJECT; + Q_OBJECT qint64 dataSize; qint64 dataSent; QTcpServer server; @@ -5257,6 +5700,7 @@ public: void finishedSlot() { // We should have already received all readyRead + QVERIFY(!bytesAvailableList.isEmpty()); QVERIFY(bytesAvailableList.last() == uploadSize); } }; @@ -5402,7 +5846,7 @@ void tst_QNetworkReply::getFromUnreachableIp() QNetworkReplyPtr reply = manager.get(request); connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); - QTestEventLoop::instance().enterLoop(5); + QTestEventLoop::instance().enterLoop(10); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(reply->error() != QNetworkReply::NoError); @@ -5532,6 +5976,25 @@ void tst_QNetworkReply::qtbug15311doubleContentLength() QCOMPARE(reply->readAll(), QByteArray("ABC")); } +void tst_QNetworkReply::qtbug18232gzipContentLengthZero() +{ + QByteArray response("HTTP/1.0 200 OK\r\nContent-Encoding: gzip\r\nContent-Length: 0\r\n\r\n"); + MiniHttpServer server(response); + server.doClose = true; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QVERIFY(reply->isFinished()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->size(), qint64(0)); + QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), qint64(0)); + QCOMPARE(reply->readAll(), QByteArray()); +} + void tst_QNetworkReply::synchronousRequest_data() { QTest::addColumn<QUrl>("url"); @@ -5569,7 +6032,7 @@ void tst_QNetworkReply::synchronousRequest_data() << QString("text/plain"); QTest::newRow("simple-file") - << QUrl(QString::fromLatin1("file:///" SRCDIR "/rfc3252.txt")) + << QUrl::fromLocalFile(SRCDIR "/rfc3252.txt") << QString("file:" SRCDIR "/rfc3252.txt") << true << QString(); diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp index 3315836..13cedda 100644 --- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp +++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp @@ -48,7 +48,7 @@ #include <QtNetwork/qnetworkconfigmanager.h> #include <QtNetwork/qnetworksession.h> -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) #include <stdio.h> #include <iapconf.h> #endif @@ -105,7 +105,7 @@ private: int inProcessSessionManagementCount; -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) Maemo::IAPConf *iapconf; Maemo::IAPConf *iapconf2; Maemo::IAPConf *gprsiap; @@ -140,7 +140,7 @@ void tst_QNetworkSession::initTestCase() testsToRun["userChoiceSession"] = true; testsToRun["sessionOpenCloseStop"] = true; -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf = new Maemo::IAPConf("007"); iapconf->setValue("ipv4_type", "AUTO"); iapconf->setValue("wlan_wepkey1", "connt"); @@ -226,7 +226,7 @@ void tst_QNetworkSession::cleanupTestCase() "inProcessSessionManagement()"); } -#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) +#if defined(Q_OS_UNIX) && !defined(QT_NO_ICD) && !defined (Q_OS_SYMBIAN) iapconf->clear(); delete iapconf; iapconf2->clear(); diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index d2307ee..4b926e4 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -135,7 +135,7 @@ private slots: void disconnectByMetaMethod(); void disconnectNotSignalMetaMethod(); void autoConnectionBehavior(); - + void baseDestroyed(); protected: }; @@ -3925,5 +3925,34 @@ void tst_QObject::autoConnectionBehavior() delete receiver; } +class BaseDestroyed : public QObject +{ Q_OBJECT + QList<QString> fooList; + bool destroyed; +public: + BaseDestroyed() : destroyed(false) + { fooList << "a" << "b"; } + ~BaseDestroyed() + { + QVERIFY(!destroyed); + destroyed = true; + } + +public slots: + void slotUseList() + { + QVERIFY(!destroyed); + fooList << "c" << "d"; + } +}; + +void tst_QObject::baseDestroyed() +{ + BaseDestroyed d; + connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList())); + //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has + // already been destroyed while ~QObject emit destroyed +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.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/qsocketnotifier/tst_qsocketnotifier.cpp b/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp index 0b7e7ef..5594dc3 100644 --- a/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp +++ b/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp @@ -46,7 +46,13 @@ #include <QtCore/QSocketNotifier> #include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpSocket> +#ifdef Q_OS_SYMBIAN +#include <private/qsymbiansocketengine_p.h> +#define NATIVESOCKETENGINE QSymbianSocketEngine +#else #include <private/qnativesocketengine_p.h> +#define NATIVESOCKETENGINE QNativeSocketEngine +#endif class tst_QSocketNotifier : public QObject { @@ -71,10 +77,10 @@ class UnexpectedDisconnectTester : public QObject { Q_OBJECT public: - QNativeSocketEngine *readEnd1, *readEnd2; + NATIVESOCKETENGINE *readEnd1, *readEnd2; int sequence; - UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2) + UnexpectedDisconnectTester(NATIVESOCKETENGINE *s1, NATIVESOCKETENGINE *s2) : readEnd1(s1), readEnd2(s2), sequence(0) { QSocketNotifier *notifier1 = @@ -124,7 +130,7 @@ void tst_QSocketNotifier::unexpectedDisconnection() QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost, 0)); - QNativeSocketEngine readEnd1; + NATIVESOCKETENGINE readEnd1; readEnd1.initialize(QAbstractSocket::TcpSocket); bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort()); QVERIFY(readEnd1.waitForWrite()); @@ -135,7 +141,7 @@ void tst_QSocketNotifier::unexpectedDisconnection() QTcpSocket *writeEnd1 = server.nextPendingConnection(); QVERIFY(writeEnd1 != 0); - QNativeSocketEngine readEnd2; + NATIVESOCKETENGINE readEnd2; readEnd2.initialize(QAbstractSocket::TcpSocket); b = readEnd2.connectToHost(server.serverAddress(), server.serverPort()); QVERIFY(readEnd2.waitForWrite()); diff --git a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro index 171d428..c82c62d 100644 --- a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro +++ b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro @@ -2,7 +2,7 @@ load(qttest_p4) SOURCES += tst_qsocks5socketengine.cpp -include(../qnativesocketengine/qsocketengine.pri) +include(../platformsocketengine/platformsocketengine.pri) MOC_DIR=tmp 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/qsslsocket/qsslsocket.pro b/tests/auto/qsslsocket/qsslsocket.pro index aeeae8f..77517e0 100644 --- a/tests/auto/qsslsocket/qsslsocket.pro +++ b/tests/auto/qsslsocket/qsslsocket.pro @@ -23,8 +23,8 @@ wince* { DEPLOYMENT += certFiles } else:symbian { DEFINES += QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - TARGET.EPOCHEAPSIZE="0x100 0x1000000" - TARGET.CAPABILITY=NetworkServices + TARGET.EPOCHEAPSIZE="0x100 0x3000000" + TARGET.CAPABILITY=NetworkServices ReadUserData certFiles.files = certs ssl.tar.gz certFiles.path = . diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index ccfe0f3..b508d47 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -67,6 +67,7 @@ typedef QList<QSslError::SslError> SslErrorList; Q_DECLARE_METATYPE(SslErrorList) Q_DECLARE_METATYPE(QSslError) Q_DECLARE_METATYPE(QSsl::SslProtocol) +Q_DECLARE_METATYPE(QSslConfiguration) #endif #if defined Q_OS_HPUX && defined Q_CC_GNU @@ -152,6 +153,8 @@ private slots: void setLocalCertificate(); void setPrivateKey(); void setSocketDescriptor(); + void setSslConfiguration_data(); + void setSslConfiguration(); void waitForEncrypted(); void waitForConnectedEncryptedReadyRead(); void startClientEncryption(); @@ -185,7 +188,7 @@ private slots: void ignoreSslErrorsListWithSlot(); void readFromClosedSocket(); void writeBigChunk(); - void blacklist(); + void blacklistedCertificates(); void setEmptyDefaultConfiguration(); static void exitLoop() @@ -534,6 +537,8 @@ void tst_QSslSocket::sslErrors() QSslSocketPtr socket = newSocket(); socket->connectToHostEncrypted(host, port); + if (!socket->waitForConnected()) + QEXPECT_FAIL("imap.trolltech.com", "server not open to internet", Continue); socket->waitForEncrypted(5000); SslErrorList output; @@ -542,7 +547,7 @@ void tst_QSslSocket::sslErrors() } #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - if (output.last() == QSslError::CertificateUntrusted) + if (output.count() && output.last() == QSslError::CertificateUntrusted) output.takeLast(); #endif QCOMPARE(output, expected); @@ -651,7 +656,7 @@ void tst_QSslSocket::sessionCipher() connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); QVERIFY(socket->sessionCipher().isNull()); socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */); - QVERIFY(socket->waitForConnected(5000)); + QVERIFY(socket->waitForConnected(10000)); QVERIFY(socket->sessionCipher().isNull()); socket->startClientEncryption(); QVERIFY(socket->waitForEncrypted(5000)); @@ -685,7 +690,7 @@ void tst_QSslSocket::localCertificate() socket->setPrivateKey(QLatin1String(SRCDIR "certs/fluke.key")); socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted(5000)); + QVERIFY(socket->waitForEncrypted(10000)); } void tst_QSslSocket::mode() @@ -926,13 +931,15 @@ void tst_QSslSocket::protocolServerSide_data() QTest::newRow("ssl3-tls1") << QSsl::SslV3 << QSsl::TlsV1 << false; QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true; QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << true; - QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << true; + QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a + // numerical IP, so OpenSSL will send a SSL 2 handshake QTest::newRow("tls1-ssl2") << QSsl::TlsV1 << QSsl::SslV2 << false; QTest::newRow("tls1-ssl3") << QSsl::TlsV1 << QSsl::SslV3 << false; QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1 << QSsl::TlsV1SslV3 << true; QTest::newRow("tls1-secure") << QSsl::TlsV1 << QSsl::SecureProtocols << true; - QTest::newRow("tls1-any") << QSsl::TlsV1 << QSsl::AnyProtocol << true; + QTest::newRow("tls1-any") << QSsl::TlsV1 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a + // numerical IP, so OpenSSL will send a SSL 2 handshake QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false; QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true; @@ -1044,6 +1051,39 @@ void tst_QSslSocket::setSocketDescriptor() QVERIFY(client->localPort() != 0); } +void tst_QSslSocket::setSslConfiguration_data() +{ + QTest::addColumn<QSslConfiguration>("configuration"); + QTest::addColumn<bool>("works"); + + QTest::newRow("empty") << QSslConfiguration() << false; + QSslConfiguration conf = QSslConfiguration::defaultConfiguration(); + QTest::newRow("default") << conf << false; // does not contain test server cert + QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); + conf.setCaCertificates(testServerCert); + QTest::newRow("set-root-cert") << conf << true; + conf.setProtocol(QSsl::SecureProtocols); + QTest::newRow("secure") << conf << true; +} + +void tst_QSslSocket::setSslConfiguration() +{ + if (!QSslSocket::supportsSsl()) + return; + + QSslSocketPtr socket = newSocket(); + QFETCH(QSslConfiguration, configuration); + socket->setSslConfiguration(configuration); + this->socket = socket; + socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); + QFETCH(bool, works); + QCOMPARE(socket->waitForEncrypted(10000), works); + if (works) { + socket->disconnectFromHost(); + QVERIFY2(socket->waitForDisconnected(), qPrintable(socket->errorString())); + } +} + void tst_QSslSocket::waitForEncrypted() { if (!QSslSocket::supportsSsl()) @@ -1525,8 +1565,8 @@ protected: // delayed start of encryption QTest::qSleep(100); QSslSocket *socket = server.socket; - Q_ASSERT(socket); - Q_ASSERT(socket->isValid()); + QVERIFY(socket); + QVERIFY(socket->isValid()); socket->ignoreSslErrors(); socket->startServerEncryption(); if (!socket->waitForEncrypted(2000)) @@ -1716,7 +1756,7 @@ void tst_QSslSocket::disconnectFromHostWhenConnecting() QCOMPARE(state, socket->state()); QVERIFY(socket->state() == QAbstractSocket::HostLookupState || socket->state() == QAbstractSocket::ConnectingState); - QVERIFY(socket->waitForDisconnected(5000)); + QVERIFY(socket->waitForDisconnected(10000)); QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState); // we did not call close, so the socket must be still open QVERIFY(socket->isOpen()); @@ -1945,7 +1985,7 @@ void tst_QSslSocket::writeBigChunk() socket->close(); } -void tst_QSslSocket::blacklist() +void tst_QSslSocket::blacklistedCertificates() { QFETCH_GLOBAL(bool, setProxy); if (setProxy) @@ -1966,14 +2006,15 @@ void tst_QSslSocket::blacklist() QVERIFY(sender->state() == QAbstractSocket::ConnectedState); receiver->setObjectName("receiver"); sender->setObjectName("sender"); - receiver->ignoreSslErrors(); receiver->startClientEncryption(); - connect(receiver, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(exitLoop())); + connect(receiver, SIGNAL(sslErrors(QList<QSslError>)), SLOT(exitLoop())); connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop())); enterLoop(1); - QCOMPARE(receiver->error(), QAbstractSocket::SslHandshakeFailedError); - QCOMPARE(receiver->errorString(), QString("The peer certificate is blacklisted")); + QList<QSslError> sslErrors = receiver->sslErrors(); + QVERIFY(sslErrors.count() > 0); + // there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error + QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted); } void tst_QSslSocket::setEmptyDefaultConfiguration() @@ -1987,8 +2028,9 @@ void tst_QSslSocket::setEmptyDefaultConfiguration() QSslConfiguration::setDefaultConfiguration(emptyConf); QSslSocketPtr socket = newSocket(); + connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - + QVERIFY2(!socket->waitForEncrypted(4000), qPrintable(socket->errorString())); } #endif // QT_NO_OPENSSL diff --git a/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro index ea62865..53020eb 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro +++ b/tests/auto/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro @@ -17,17 +17,9 @@ win32 { wince* { DEFINES += SRCDIR=\\\"./\\\" - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles } else:symbian { TARGET.EPOCHEAPSIZE="0x100 0x1000000" - TARGET.CAPABILITY=NetworkServices - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles + TARGET.CAPABILITY=NetworkServices ReadUserData INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE # Needed for e32svr.h in S^3 envs } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp b/tests/auto/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp index abdd550..6d3590a 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp +++ b/tests/auto/qsslsocket_onDemandCertificates_member/tst_qsslsocket_onDemandCertificates_member.cpp @@ -217,6 +217,13 @@ void tst_QSslSocket_onDemandCertificates_member::onDemandRootCertLoadingMemberMe socket3->setCaCertificates(QList<QSslCertificate>()); socket3->connectToHostEncrypted(host, 443); QVERIFY(!socket3->waitForEncrypted()); + + // setting empty SSL configuration explicitly -> should not work + QSslSocketPtr socket4 = newSocket(); + this->socket = socket4; + socket4->setSslConfiguration(QSslConfiguration()); + socket4->connectToHostEncrypted(host, 443); + QVERIFY(!socket4->waitForEncrypted()); } #endif // QT_NO_OPENSSL diff --git a/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro index 13990cb..3452a92 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro +++ b/tests/auto/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro @@ -17,17 +17,9 @@ win32 { wince* { DEFINES += SRCDIR=\\\"./\\\" - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles } else:symbian { TARGET.EPOCHEAPSIZE="0x100 0x1000000" - TARGET.CAPABILITY=NetworkServices - - certFiles.files = certs ssl.tar.gz - certFiles.path = . - DEPLOYMENT += certFiles + TARGET.CAPABILITY=NetworkServices ReadUserData INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE # Needed for e32svr.h in S^3 envs } else { DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp b/tests/auto/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp index 5003b5c..14a7c3b 100644 --- a/tests/auto/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp +++ b/tests/auto/qsslsocket_onDemandCertificates_static/tst_qsslsocket_onDemandCertificates_static.cpp @@ -218,6 +218,18 @@ void tst_QSslSocket_onDemandCertificates_static::onDemandRootCertLoadingStaticMe this->socket = socket3; socket3->connectToHostEncrypted(host, 443); QVERIFY(!socket3->waitForEncrypted()); + + QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); + + // setting empty default configuration -> should not work + QSslConfiguration conf; + QSslConfiguration originalDefaultConf = QSslConfiguration::defaultConfiguration(); + QSslConfiguration::setDefaultConfiguration(conf); + QSslSocketPtr socket4 = newSocket(); + this->socket = socket4; + socket4->connectToHostEncrypted(host, 443); + QVERIFY(!socket4->waitForEncrypted(4000)); + QSslConfiguration::setDefaultConfiguration(originalDefaultConf); // restore old behaviour for run with proxies etc. } #endif // QT_NO_OPENSSL diff --git a/tests/auto/qstring/qstring.pro b/tests/auto/qstring/qstring.pro index e980042..1c123ad 100644 --- a/tests/auto/qstring/qstring.pro +++ b/tests/auto/qstring/qstring.pro @@ -7,3 +7,5 @@ QT = core DEFINES += QT_NO_CAST_TO_ASCII CONFIG += parallel_test + +contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index abc8d9a..3d80e80 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -222,6 +222,8 @@ private slots: void task262677remove(); void QTBUG10404_compareRef(); void QTBUG9281_arg_locale(); + + void toUpperLower_icu(); }; typedef QList<int> IntList; @@ -697,11 +699,11 @@ void tst_QString::acc_01() QVERIFY(a<=c); QVERIFY(!(c<=a)); QVERIFY(!(d<=a)); - QCOMPARE(a+b,(QString)"ABCABC"); - QCOMPARE(a +"XXXX",(QString)"ABCXXXX"); - QCOMPARE(a+'X',(QString)"ABCX"); - QCOMPARE("XXXX"+a,(QString)"XXXXABC"); - QCOMPARE('X'+a,(QString)"XABC"); + QCOMPARE(QString(a+b),(QString)"ABCABC"); + QCOMPARE(QString(a+"XXXX"),(QString)"ABCXXXX"); + QCOMPARE(QString(a+'X'),(QString)"ABCX"); + QCOMPARE(QString("XXXX"+a),(QString)"XXXXABC"); + QCOMPARE(QString('X'+a),(QString)"XABC"); a = (const char*)0; QVERIFY(a.isNull()); QVERIFY(*a.toLatin1().constData() == '\0'); @@ -1060,12 +1062,12 @@ void tst_QString::indexOf_data() QString veryBigHaystack(500, 'a'); veryBigHaystack += 'B'; QTest::newRow("BoyerMooreStressTest") << veryBigHaystack << veryBigHaystack << 0 << true << 0; - QTest::newRow("BoyerMooreStressTest2") << veryBigHaystack + 'c' << veryBigHaystack << 0 << true << 0; - QTest::newRow("BoyerMooreStressTest3") << 'c' + veryBigHaystack << veryBigHaystack << 0 << true << 1; - QTest::newRow("BoyerMooreStressTest4") << veryBigHaystack << veryBigHaystack + 'c' << 0 << true << -1; - QTest::newRow("BoyerMooreStressTest5") << veryBigHaystack << 'c' + veryBigHaystack << 0 << true << -1; - QTest::newRow("BoyerMooreStressTest6") << 'd' + veryBigHaystack << 'c' + veryBigHaystack << 0 << true << -1; - QTest::newRow("BoyerMooreStressTest6") << veryBigHaystack + 'c' << 'c' + veryBigHaystack << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest2") << QString(veryBigHaystack + 'c') << veryBigHaystack << 0 << true << 0; + QTest::newRow("BoyerMooreStressTest3") << QString('c' + veryBigHaystack) << veryBigHaystack << 0 << true << 1; + QTest::newRow("BoyerMooreStressTest4") << veryBigHaystack << QString(veryBigHaystack + 'c') << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest5") << veryBigHaystack << QString('c' + veryBigHaystack) << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest6") << QString('d' + veryBigHaystack) << QString('c' + veryBigHaystack) << 0 << true << -1; + QTest::newRow("BoyerMooreStressTest6") << QString(veryBigHaystack + 'c') << QString('c' + veryBigHaystack) << 0 << true << -1; QTest::newRow("BoyerMooreInsensitiveStressTest") << veryBigHaystack << veryBigHaystack << 0 << false << 0; @@ -1175,14 +1177,14 @@ void tst_QString::indexOf2_data() QString whale = "a5zby6cx7dw8evf9ug0th1si2rj3qkp4lomn"; QString minnow = "zby"; QTest::newRow( "data40" ) << whale << minnow << 2; - QTest::newRow( "data41" ) << (whale + whale) << minnow << 2; - QTest::newRow( "data42" ) << (minnow + whale) << minnow << 0; + QTest::newRow( "data41" ) << QString(whale + whale) << minnow << 2; + QTest::newRow( "data42" ) << QString(minnow + whale) << minnow << 0; QTest::newRow( "data43" ) << whale << whale << 0; - QTest::newRow( "data44" ) << (whale + whale) << whale << 0; - QTest::newRow( "data45" ) << whale << (whale + whale) << -1; - QTest::newRow( "data46" ) << (whale + whale) << (whale + whale) << 0; - QTest::newRow( "data47" ) << (whale + whale) << (whale + minnow) << -1; - QTest::newRow( "data48" ) << (minnow + whale) << whale << (int)minnow.length(); + QTest::newRow( "data44" ) << QString(whale + whale) << whale << 0; + QTest::newRow( "data45" ) << whale << QString(whale + whale) << -1; + QTest::newRow( "data46" ) << QString(whale + whale) << QString(whale + whale) << 0; + QTest::newRow( "data47" ) << QString(whale + whale) << QString(whale + minnow) << -1; + QTest::newRow( "data48" ) << QString(minnow + whale) << whale << (int)minnow.length(); } void tst_QString::indexOf2() @@ -1603,6 +1605,11 @@ void tst_QString::toUpper() QCOMPARE( lower.toUpper(), upper); +#ifdef QT_USE_ICU + // test doesn't work with ICU support, since QChar is unaware of any locale + QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); + QVERIFY(false); +#else for (int i = 0; i < 65536; ++i) { QString str(1, QChar(i)); QString upper = str.toUpper(); @@ -1610,6 +1617,7 @@ void tst_QString::toUpper() if (upper.length() == 1) QVERIFY(upper == QString(1, QChar(i).toUpper())); } +#endif } void tst_QString::toLower() @@ -1631,7 +1639,7 @@ void tst_QString::toLower() QCOMPARE( QString("`ABYZ{").toLower(), QString("`abyz{")); QCOMPARE( QString("`abyz{").toLower(), QString("`abyz{")); - QCOMPARE( QString(1, QChar(0x130)).toLower(), QString(1, QChar(0x69)) + QChar(0x307)); + QCOMPARE( QString(1, QChar(0x130)).toLower(), QString(QString(1, QChar(0x69)) + QChar(0x307))); QString lower; lower += QChar(QChar::highSurrogate(0x10428)); @@ -1641,6 +1649,11 @@ void tst_QString::toLower() upper += QChar(QChar::lowSurrogate(0x10400)); QCOMPARE( upper.toLower(), lower); +#ifdef QT_USE_ICU + // test doesn't work with ICU support, since QChar is unaware of any locale + QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue); + QVERIFY(false); +#else for (int i = 0; i < 65536; ++i) { QString str(1, QChar(i)); QString lower = str.toLower(); @@ -1648,6 +1661,7 @@ void tst_QString::toLower() if (lower.length() == 1) QVERIFY(str.toLower() == QString(1, QChar(i).toLower())); } +#endif } void tst_QString::trimmed() @@ -4352,6 +4366,8 @@ void tst_QString::localeAwareCompare() #elif defined (Q_WS_MAC) QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll); +#elif defined(QT_USE_ICU) + QLocale::setDefault(QLocale(locale)); #else if (!locale.isEmpty()) { const char *newLocale = setlocale(LC_ALL, locale.toLatin1()); @@ -4363,6 +4379,11 @@ void tst_QString::localeAwareCompare() } #endif +#ifdef QT_USE_ICU + // ### for c1, ICU disagrees with libc on how to compare + QEXPECT_FAIL("c1", "ICU disagrees with test", Abort); +#endif + int testres = QString::localeAwareCompare(s1, s2); if (result < 0) { QVERIFY(testres < 0); @@ -5065,6 +5086,40 @@ void tst_QString::QTBUG9281_arg_locale() QLocale::setDefault(QLocale::C); } +void tst_QString::toUpperLower_icu() +{ +#ifndef QT_USE_ICU + QSKIP("Qt was built without ICU support", SkipAll); +#endif + + QString s = QString::fromLatin1("i"); + + QCOMPARE(s.toUpper(), QString::fromLatin1("I")); + QCOMPARE(s.toLower(), QString::fromLatin1("i")); + + QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey)); + + // turkish locale has a capital I with a dot (U+0130, utf8 c4b0) + + QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0")); + QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s); + + // nothing should happen here + QCOMPARE(s.toLower(), s); + QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I")); + + // U+0131, utf8 c4b1 is the lower-case i without a dot + QString sup = QString::fromUtf8("\xc4\xb1"); + + QCOMPARE(sup.toUpper(), QString::fromLatin1("I")); + QCOMPARE(QString::fromLatin1("I").toLower(), sup); + + // nothing should happen here + QCOMPARE(sup.toLower(), sup); + QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i")); + + // the cleanup function will restore the default locale +} QTEST_APPLESS_MAIN(tst_QString) diff --git a/tests/auto/qstringbuilder1/stringbuilder.cpp b/tests/auto/qstringbuilder1/stringbuilder.cpp index f3c0ea9..d7a32bf 100644 --- a/tests/auto/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/qstringbuilder1/stringbuilder.cpp @@ -137,4 +137,60 @@ void runScenario() string = QString::fromLatin1(LITERAL); QCOMPARE(QByteArray(qPrintable(string P string)), QByteArray(string.toLatin1() + string.toLatin1())); + + + + //QByteArray + { + QByteArray ba = LITERAL; + QByteArray superba = ba P ba P LITERAL; + QCOMPARE(superba, QByteArray(LITERAL LITERAL LITERAL)); + + QByteArray testWith0 = ba P "test\0with\0zero" P ba; + QCOMPARE(testWith0, QByteArray(LITERAL "test" LITERAL)); + + QByteArray ba2 = ba P '\0' + LITERAL; + QCOMPARE(ba2, QByteArray(LITERAL "\0" LITERAL, ba.size()*2+1)); + + const char *mmh = "test\0foo"; + QCOMPARE(QByteArray(ba P mmh P ba), testWith0); + + QByteArray raw = QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); + QByteArray r = "hello" P raw; + QByteArray r2 = "hello" UTF8_LITERAL; + QCOMPARE(r, r2); + r2 = QByteArray("hello\0") P UTF8_LITERAL; + QCOMPARE(r, r2); + } + + //operator QString += + { + QString str = QString::fromUtf8(UTF8_LITERAL); + str += QLatin1String(LITERAL) P str; + QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); +#ifndef QT_NO_CAST_FROM_ASCII + str = (QString::fromUtf8(UTF8_LITERAL) += QLatin1String(LITERAL) P UTF8_LITERAL); + QCOMPARE(str, QString::fromUtf8(UTF8_LITERAL LITERAL UTF8_LITERAL)); +#endif + } + + //operator QByteArray += + { + QByteArray ba = UTF8_LITERAL; + ba += QByteArray(LITERAL) P UTF8_LITERAL; + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); + ba += LITERAL P QByteArray::fromRawData(UTF8_LITERAL_EXTRA, UTF8_LITERAL_LEN); + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL LITERAL UTF8_LITERAL)); + QByteArray withZero = QByteArray(LITERAL "\0" LITERAL, LITERAL_LEN*2+1); + QByteArray ba2 = withZero; + ba2 += ba2 P withZero; + QCOMPARE(ba2, QByteArray(withZero + withZero + withZero)); +#ifndef QT_NO_CAST_TO_ASCII + ba = UTF8_LITERAL; + ba2 = (ba += QLatin1String(LITERAL) + QString::fromUtf8(UTF8_LITERAL)); + QCOMPARE(ba2, ba); + QCOMPARE(ba, QByteArray(UTF8_LITERAL LITERAL UTF8_LITERAL)); +#endif + } + } diff --git a/tests/auto/qstringlist/tst_qstringlist.cpp b/tests/auto/qstringlist/tst_qstringlist.cpp index 283c17f..d8db00a 100644 --- a/tests/auto/qstringlist/tst_qstringlist.cpp +++ b/tests/auto/qstringlist/tst_qstringlist.cpp @@ -78,6 +78,8 @@ private slots: void join() const; void join_data() const; void joinEmptiness() const; + + void initializeList() const; }; extern const char email[]; @@ -321,5 +323,16 @@ void tst_QStringList::joinEmptiness() const QVERIFY(string.isNull()); } +void tst_QStringList::initializeList() const +{ +#ifdef Q_COMPILER_INITIALIZER_LISTS + QStringList v1{QLatin1String("hello"),"world",QString::fromLatin1("plop")}; + QCOMPARE(v1, (QStringList() << "hello" << "world" << "plop")); + QCOMPARE(v1, (QStringList{"hello","world","plop"})); +#else + QSKIP("Require C++0x support, pass the right flag to the compiler", SkipAll); +#endif +} + QTEST_APPLESS_MAIN(tst_QStringList) #include "tst_qstringlist.moc" diff --git a/tests/auto/qstyle/tst_qstyle.cpp b/tests/auto/qstyle/tst_qstyle.cpp index ad5d7ff..5c319f0 100644 --- a/tests/auto/qstyle/tst_qstyle.cpp +++ b/tests/auto/qstyle/tst_qstyle.cpp @@ -272,6 +272,18 @@ void tst_QStyle::drawItemPixmap() QPixmap p(QString(SRCDIR) + "/task_25863.png", "PNG"); QPixmap actualPix = QPixmap::grabWidget(testWidget); + +#ifdef Q_OS_SYMBIAN + // QPixmap cannot be assumed to be exactly same, unless it is created from exactly same content. + // In Symbian, pixmap format might get "optimized" depending on how QPixmap is created. + // Therefore, force the content to specific format and compare QImages. + // Then re-create the QPixmaps and compare those. + QImage i1 = p.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + p = QPixmap::fromImage(i1); + QImage i2 = actualPix.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); + actualPix = QPixmap::fromImage(i2); + QVERIFY(i1 == i2); +#endif QVERIFY(pixmapsAreEqual(&actualPix,&p)); testWidget->hide(); } diff --git a/tests/auto/qtcpserver/crashingServer/crashingServer.pro b/tests/auto/qtcpserver/crashingServer/crashingServer.pro index 0bea655..700e952 100644 --- a/tests/auto/qtcpserver/crashingServer/crashingServer.pro +++ b/tests/auto/qtcpserver/crashingServer/crashingServer.pro @@ -6,3 +6,4 @@ DESTDIR = ./ # This means the auto test works on some machines for MinGW. No dialog stalls # the application. win32-g++*:CONFIG += console +symbian: TARGET.CAPABILITY += NetworkServices ReadUserData diff --git a/tests/auto/qtcpserver/qtcpserver.pro b/tests/auto/qtcpserver/qtcpserver.pro index a3744a2..e123cfe 100644 --- a/tests/auto/qtcpserver/qtcpserver.pro +++ b/tests/auto/qtcpserver/qtcpserver.pro @@ -1,6 +1,4 @@ TEMPLATE = subdirs SUBDIRS = test crashingServer -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qtcpserver/test/test.pro b/tests/auto/qtcpserver/test/test.pro index e91ba20..65e1d82 100644 --- a/tests/auto/qtcpserver/test/test.pro +++ b/tests/auto/qtcpserver/test/test.pro @@ -13,9 +13,10 @@ wince*: { } symbian { - crashApp.files = $$QT_BUILD_TREE/examples/widgets/wiggly/$${BUILD_DIR}/crashingServer.exe - crashApp.path = . - DEPLOYMENT += crashApp + crashApp.files = $$QT_BUILD_TREE/examples/widgets/wiggly/$${BUILD_DIR}/crashingServer.exe + crashApp.path = . + DEPLOYMENT += crashApp + TARGET.CAPABILITY += NetworkServices ReadUserData } TARGET = ../tst_qtcpserver diff --git a/tests/auto/qtcpserver/tst_qtcpserver.cpp b/tests/auto/qtcpserver/tst_qtcpserver.cpp index 3d377a4..9cddc00 100644 --- a/tests/auto/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp @@ -70,6 +70,9 @@ Q_DECLARE_METATYPE(QNetworkProxy) Q_DECLARE_METATYPE(QList<QNetworkProxy>) +#include <QNetworkSession> +#include <QNetworkConfiguration> +#include <QNetworkConfigurationManager> #include "../network-settings.h" //TESTED_CLASS= @@ -86,6 +89,7 @@ public: public slots: void initTestCase_data(); + void initTestCase(); void init(); void cleanup(); private slots: @@ -93,6 +97,7 @@ private slots: void constructing(); void clientServerLoop(); void ipv6Server(); + void ipv6ServerMapped(); void crashTests(); void maxPendingConnections(); void listenError(); @@ -107,6 +112,11 @@ private slots: void proxyFactory(); void qtbug14268_peek(); + +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkSession *networkSession; +#endif }; // Testing get/set functions @@ -141,6 +151,16 @@ void tst_QTcpServer::initTestCase_data() QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); } +void tst_QTcpServer::initTestCase() +{ +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager man; + networkSession = new QNetworkSession(man.defaultConfiguration(), this); + networkSession->open(); + QVERIFY(networkSession->waitForOpened()); +#endif +} + void tst_QTcpServer::init() { QFETCH_GLOBAL(bool, setProxy); @@ -190,7 +210,7 @@ void tst_QTcpServer::clientServerLoop() QTcpSocket client; QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.serverAddress() == QHostAddress::Any)) + if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6)) serverAddress = server.serverAddress(); client.connectToHost(serverAddress, server.serverPort()); @@ -222,9 +242,6 @@ void tst_QTcpServer::clientServerLoop() //---------------------------------------------------------------------------------- void tst_QTcpServer::ipv6Server() { -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian: IPv6 is not yet supported", SkipAll); -#endif //### need to enter the event loop for the server to get the connection ?? ( windows) QTcpServer server; if (!server.listen(QHostAddress::LocalHostIPv6, 8944)) { @@ -244,6 +261,42 @@ void tst_QTcpServer::ipv6Server() QTcpSocket *serverSocket = 0; QVERIFY((serverSocket = server.nextPendingConnection())); + serverSocket->close(); + delete serverSocket; +} + +//---------------------------------------------------------------------------------- +void tst_QTcpServer::ipv6ServerMapped() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QTcpServer server; + QVERIFY(server.listen(QHostAddress::LocalHost)); + + // let's try the normal case + QTcpSocket client1; + client1.connectToHost("127.0.0.1", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // let's try the mapped one in the nice format + QTcpSocket client2; + client2.connectToHost("::ffff:127.0.0.1", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // let's try the mapped in hex format + QTcpSocket client3; + client3.connectToHost("::ffff:7F00:0001", server.serverPort()); + QVERIFY(server.waitForNewConnection(5000)); + delete server.nextPendingConnection(); + + // However connecting to the v6 localhost should not work + QTcpSocket client4; + client4.connectToHost("::1", server.serverPort()); + QVERIFY(!server.waitForNewConnection(5000)); } //---------------------------------------------------------------------------------- @@ -379,7 +432,8 @@ void tst_QTcpServer::setSocketDescriptor() QTcpServer server; QVERIFY(!server.setSocketDescriptor(42)); QCOMPARE(server.serverError(), QAbstractSocket::UnsupportedSocketOperationError); - +#ifndef Q_OS_SYMBIAN + //adopting Open C sockets is not supported, neither is adopting externally created RSocket #ifdef Q_OS_WIN // ensure winsock is started WSADATA wsaData; @@ -402,6 +456,7 @@ void tst_QTcpServer::setSocketDescriptor() #ifdef Q_OS_WIN WSACleanup(); #endif +#endif } //---------------------------------------------------------------------------------- @@ -493,6 +548,9 @@ void tst_QTcpServer::addressReusable() void tst_QTcpServer::setNewSocketDescriptorBlocking() { +#ifdef Q_OS_SYMBIAN + QSKIP("open C ioctls on Qt sockets not supported", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); if (setProxy) { QFETCH_GLOBAL(int, proxyType); @@ -507,6 +565,7 @@ void tst_QTcpServer::setNewSocketDescriptorBlocking() socket.connectToHost(QHostAddress::LocalHost, server.serverPort()); QVERIFY(server.waitForNewConnection(5000)); QVERIFY(server.ok); +#endif } void tst_QTcpServer::invalidProxy_data() diff --git a/tests/auto/qtcpsocket/qtcpsocket.pro b/tests/auto/qtcpsocket/qtcpsocket.pro index 8b1f664..5dfff5b 100644 --- a/tests/auto/qtcpsocket/qtcpsocket.pro +++ b/tests/auto/qtcpsocket/qtcpsocket.pro @@ -6,4 +6,3 @@ wince*|symbian|vxworks* : SUBDIRS = test requires(contains(QT_CONFIG,private_tests)) -symbian: TARGET.CAPABILITY = NetworkServices diff --git a/tests/auto/qtcpsocket/stressTest/stressTest.pro b/tests/auto/qtcpsocket/stressTest/stressTest.pro index 9a653c6..adf0217 100644 --- a/tests/auto/qtcpsocket/stressTest/stressTest.pro +++ b/tests/auto/qtcpsocket/stressTest/stressTest.pro @@ -9,4 +9,5 @@ DESTDIR = ./ MOC_DIR = .moc/ TMP_DIR = .tmp/ +symbian: TARGET.CAPABILITY = NetworkServices diff --git a/tests/auto/qtcpsocket/test/test.pro b/tests/auto/qtcpsocket/test/test.pro index c4369df..f4207d6 100644 --- a/tests/auto/qtcpsocket/test/test.pro +++ b/tests/auto/qtcpsocket/test/test.pro @@ -11,7 +11,10 @@ wince*: { QT += network vxworks:QT -= gui -symbian: TARGET.EPOCHEAPSIZE="0x100 0x1000000" +symbian: { + TARGET.EPOCHEAPSIZE="0x100 0x3000000" + TARGET.CAPABILITY = NetworkServices +} TARGET = tst_qtcpsocket diff --git a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp index 21092c4..623e02b 100644 --- a/tests/auto/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/qtcpsocket/tst_qtcpsocket.cpp @@ -106,6 +106,7 @@ Q_DECLARE_METATYPE(QList<QNetworkProxy>) //TESTED_FILES= QT_FORWARD_DECLARE_CLASS(QTcpSocket) +QT_FORWARD_DECLARE_CLASS(SocketPair) class tst_QTcpSocket : public QObject { @@ -138,6 +139,7 @@ public slots: void init(); void cleanup(); private slots: + void socketsConstructedBeforeEventLoop(); void constructing(); void setInvalidSocketDescriptor(); void setSocketDescriptor(); @@ -221,6 +223,8 @@ protected slots: void abortiveClose_abortSlot(); void remoteCloseErrorSlot(); void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth); + void earlySocketBytesSent(qint64 bytes); + void earlySocketReadyRead(); private: QByteArray expectedReplyIMAP(); @@ -243,6 +247,10 @@ private: bool gotClosedSignal; int numConnections; static int loopLevel; + + SocketPair *earlyConstructedSockets; + int earlyBytesWrittenCount; + int earlyReadyReadCount; }; enum ProxyTests { @@ -296,8 +304,16 @@ public: tst_QTcpSocket::tst_QTcpSocket() { - Q_SET_DEFAULT_IAP tmpSocket = 0; + + //This code relates to the socketsConstructedBeforeEventLoop test case + earlyConstructedSockets = new SocketPair; + QVERIFY(earlyConstructedSockets->create()); + earlyBytesWrittenCount = 0; + earlyReadyReadCount = 0; + connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead())); + connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64))); + earlyConstructedSockets->endPoints[1]->write("hello work"); } tst_QTcpSocket::~tst_QTcpSocket() @@ -336,7 +352,9 @@ void tst_QTcpSocket::init() QFETCH_GLOBAL(bool, setProxy); if (setProxy) { QFETCH_GLOBAL(int, proxyType); - QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(); + QList<QHostAddress> addresses = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses(); + QVERIFY2(addresses.count() > 0, "failed to get ip address for test server"); + QString fluke = addresses.first().toString(); QNetworkProxy proxy; switch (proxyType) { @@ -397,6 +415,33 @@ void tst_QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthent //---------------------------------------------------------------------------------- +void tst_QTcpSocket::socketsConstructedBeforeEventLoop() +{ + QFETCH_GLOBAL(bool, setProxy); + QFETCH_GLOBAL(bool, ssl); + if (setProxy || ssl) + return; + //This test checks that sockets constructed before QCoreApplication::exec() still emit signals + //see construction code in the tst_QTcpSocket constructor + enterLoop(3); + QCOMPARE(earlyBytesWrittenCount, 1); + QCOMPARE(earlyReadyReadCount, 1); + earlyConstructedSockets->endPoints[0]->close(); + earlyConstructedSockets->endPoints[1]->close(); +} + +void tst_QTcpSocket::earlySocketBytesSent(qint64 bytes) +{ + earlyBytesWrittenCount++; +} + +void tst_QTcpSocket::earlySocketReadyRead() +{ + earlyReadyReadCount++; +} + +//---------------------------------------------------------------------------------- + void tst_QTcpSocket::constructing() { QTcpSocket *socket = newSocket(); @@ -443,6 +488,9 @@ void tst_QTcpSocket::setInvalidSocketDescriptor() void tst_QTcpSocket::setSocketDescriptor() { +#ifdef Q_OS_SYMBIAN + QSKIP("adopting open c socket handles is not supported", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); if (setProxy) return; // this test doesn't make sense with proxies @@ -483,6 +531,7 @@ void tst_QTcpSocket::setSocketDescriptor() #ifdef Q_OS_WIN delete dummy; #endif +#endif } //---------------------------------------------------------------------------------- @@ -605,14 +654,14 @@ void tst_QTcpSocket::timeoutConnect() // Port 1357 is configured to drop packets on the test server socket->connectToHost(address, 1357); - QVERIFY(timer.elapsed() < 50); - QVERIFY(!socket->waitForConnected(200)); + QVERIFY(timer.elapsed() < 150); + QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication QCOMPARE(socket->state(), QTcpSocket::UnconnectedState); QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError)); timer.start(); socket->connectToHost(address, 1357); - QVERIFY(timer.elapsed() < 50); + QVERIFY(timer.elapsed() < 150); QTimer::singleShot(50, &QTestEventLoop::instance(), SLOT(exitLoop())); QTestEventLoop::instance().enterLoop(5); QVERIFY(!QTestEventLoop::instance().timeout()); @@ -975,6 +1024,9 @@ void tst_QTcpSocket::disconnectWhileConnecting_data() void tst_QTcpSocket::disconnectWhileConnecting() { QFETCH(QByteArray, data); + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -1035,7 +1087,7 @@ public: : server(0), ok(false), quit(false) { } - ~ReceiverThread() { /*delete server;*/ terminate(); wait(); } + ~ReceiverThread() { } bool listen() { @@ -1047,6 +1099,14 @@ public: return true; } + static void cleanup(void *ptr) + { + ReceiverThread* self = reinterpret_cast<ReceiverThread*>(ptr); + self->quit = true; + self->wait(30000); + delete self; + } + protected: void run() { @@ -1092,19 +1152,20 @@ void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop_data() void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop() { QFETCH(QByteArray, data); + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case - ReceiverThread thread; - QVERIFY(thread.listen()); - thread.start(); + QScopedPointer<ReceiverThread, ReceiverThread> thread (new ReceiverThread); + QVERIFY(thread->listen()); + thread->start(); // proceed to the connect-write-disconnect QTcpSocket *socket = newSocket(); - socket->connectToHost("127.0.0.1", thread.serverPort); + socket->connectToHost("127.0.0.1", thread->serverPort); if (!data.isEmpty()) socket->write(data); if (socket->state() == QAbstractSocket::ConnectedState) { - thread.quit = true; - thread.wait(); QSKIP("localhost connections are immediate, test case is invalid", SkipSingle); } @@ -1130,9 +1191,9 @@ void tst_QTcpSocket::disconnectWhileConnectingNoEventLoop() delete socket; // check if the other side received everything ok - QVERIFY(thread.wait(30000)); - QVERIFY(thread.ok); - QCOMPARE(thread.receivedData, data); + QVERIFY(thread->wait(30000)); + QVERIFY(thread->ok); + QCOMPARE(thread->receivedData, data); } //---------------------------------------------------------------------------------- @@ -1194,6 +1255,7 @@ void tst_QTcpSocket::downloadBigFile() connect(tmpSocket, SIGNAL(connected()), SLOT(exitLoopSlot())); connect(tmpSocket, SIGNAL(readyRead()), SLOT(downloadBigFileSlot())); + connect(tmpSocket, SIGNAL(disconnected()), SLOT(exitLoopSlot())); tmpSocket->connectToHost(QtNetworkSettings::serverName(), 80); @@ -1380,7 +1442,7 @@ void tst_QTcpSocket::flush() connect(socket, SIGNAL(connected()), SLOT(exitLoopSlot())); socket->connectToHost(QtNetworkSettings::serverName(), 143); - enterLoop(5000); + enterLoop(60); QVERIFY(socket->isOpen()); socket->write("1 LOGOUT\r\n"); @@ -1413,7 +1475,7 @@ void tst_QTcpSocket::dontCloseOnTimeout() QVERIFY(server.listen()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.serverAddress() == QHostAddress::Any)) + if (!(server.serverAddress() == QHostAddress::Any) && !(server.serverAddress() == QHostAddress::AnyIPv6)) serverAddress = server.serverAddress(); QTcpSocket *socket = newSocket(); @@ -1633,6 +1695,9 @@ private slots: //---------------------------------------------------------------------------------- void tst_QTcpSocket::remoteCloseError() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case RemoteCloseErrorServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -1943,6 +2008,9 @@ void tst_QTcpSocket::linuxKernelBugLocalSocket() //---------------------------------------------------------------------------------- void tst_QTcpSocket::abortiveClose() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); connect(&server, SIGNAL(newConnection()), this, SLOT(exitLoopSlot())); @@ -1981,6 +2049,9 @@ void tst_QTcpSocket::abortiveClose_abortSlot() //---------------------------------------------------------------------------------- void tst_QTcpSocket::localAddressEmptyOnBSD() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost)); @@ -2251,6 +2322,9 @@ void tst_QTcpSocket::moveToThread0() void tst_QTcpSocket::increaseReadBufferSize() { + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; //proxy not useful for localhost test case QTcpServer server; QTcpSocket *active = newSocket(); connect(active, SIGNAL(readyRead()), SLOT(exitLoopSlot())); diff --git a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp index f89e033..b6b0d3c 100644 --- a/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp @@ -75,6 +75,10 @@ public: public slots: void init(); void cleanup(); + + void initTestCase(); + void cleanupTestCase(); + private slots: void construction(); void fileTemplate(); @@ -97,9 +101,24 @@ private slots: void setTemplateAfterOpen(); void autoRemoveAfterFailedRename(); + void QTBUG_4796_data(); + void QTBUG_4796(); + public: }; +void tst_QTemporaryFile::initTestCase() +{ + // For QTBUG_4796 + QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); +} + +void tst_QTemporaryFile::cleanupTestCase() +{ + // From QTBUG_4796 + QVERIFY(QDir().rmdir("test-XXXXXX")); +} + void tst_QTemporaryFile::construction() { QTemporaryFile file(0); @@ -144,26 +163,35 @@ void tst_QTemporaryFile::cleanup() void tst_QTemporaryFile::fileTemplate_data() { QTest::addColumn<QString>("constructorTemplate"); + QTest::addColumn<QString>("prefix"); QTest::addColumn<QString>("suffix"); QTest::addColumn<QString>("fileTemplate"); - QTest::newRow("constructor default") << "" << "" << ""; - QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "xxx" << ""; - QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "xXx" << ""; - QTest::newRow("constructor with no sufix") << "qt_XXXXXX" << "" << ""; - QTest::newRow("constructor with >6 X's and xxx suffix") << "qt_XXXXXXXXXXxxx" << "xxx" << ""; - QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "" << ""; - - QTest::newRow("set template, no suffix") << "" << "" << "foo"; - QTest::newRow("set template, with lowercase XXXXXX") << "" << "xxxxxx" << "qt_XXXXXXxxxxxx"; - QTest::newRow("set template, with xxx") << "" << ".xxx" << "qt_XXXXXX.xxx"; - QTest::newRow("set template, with >6 X's") << "" << ".xxx" << "qt_XXXXXXXXXXXXXX.xxx"; - QTest::newRow("set template, with >6 X's, no suffix") << "" << "" << "qt_XXXXXXXXXXXXXX"; + QTest::newRow("constructor default") << "" << "." << "" << ""; + QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "qt_" << "xxx" << ""; + QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "qt_" << "xXx" << ""; + QTest::newRow("constructor with no sufix") << "qt_XXXXXX" << "qt_" << "" << ""; + QTest::newRow("constructor with >6 X's and xxx suffix") << "qt_XXXXXXXXXXxxx" << "qt_" << "xxx" << ""; + QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "qt_" << "" << ""; + + QTest::newRow("constructor with XXXX suffix") << "qt_XXXXXX_XXXX" << "qt_" << "_XXXX" << ""; + QTest::newRow("constructor with XXXXX suffix") << "qt_XXXXXX_XXXXX" << "qt_" << "_XXXXX" << ""; + QTest::newRow("constructor with XXXX prefix") << "qt_XXXX" << "qt_XXXX." << "" << ""; + QTest::newRow("constructor with XXXXX prefix") << "qt_XXXXX" << "qt_XXXXX." << "" << ""; + QTest::newRow("constructor with XXXX prefix and suffix") << "qt_XXXX_XXXXXX_XXXX" << "qt_XXXX_" << "_XXXX" << ""; + QTest::newRow("constructor with XXXXX prefix and suffix") << "qt_XXXXX_XXXXXX_XXXXX" << "qt_XXXXX_" << "_XXXXX" << ""; + + QTest::newRow("set template, no suffix") << "" << "foo" << "" << "foo"; + QTest::newRow("set template, with lowercase XXXXXX") << "" << "qt_" << "xxxxxx" << "qt_XXXXXXxxxxxx"; + QTest::newRow("set template, with xxx") << "" << "qt_" << ".xxx" << "qt_XXXXXX.xxx"; + QTest::newRow("set template, with >6 X's") << "" << "qt_" << ".xxx" << "qt_XXXXXXXXXXXXXX.xxx"; + QTest::newRow("set template, with >6 X's, no suffix") << "" << "qt_" << "" << "qt_XXXXXXXXXXXXXX"; } void tst_QTemporaryFile::fileTemplate() { QFETCH(QString, constructorTemplate); + QFETCH(QString, prefix); QFETCH(QString, suffix); QFETCH(QString, fileTemplate); @@ -173,8 +201,11 @@ void tst_QTemporaryFile::fileTemplate() QCOMPARE(file.open(), true); - QCOMPARE(file.fileName().right(suffix.length()), suffix); - file.close(); + if (prefix.length()) + QCOMPARE(file.fileName().left(prefix.length()), prefix); + + if (suffix.length()) + QCOMPARE(file.fileName().right(suffix.length()), suffix); } @@ -359,10 +390,7 @@ void tst_QTemporaryFile::stressTest() for (int i = 0; i < iterations; ++i) { QTemporaryFile file; file.setAutoRemove(false); - if (!file.open()) { - qDebug() << "Could not open File:" << file.fileName(); - continue; - } + QVERIFY2(file.open(), qPrintable(file.errorString())); QVERIFY(!names.contains(file.fileName())); names.insert(file.fileName()); } @@ -594,5 +622,108 @@ void tst_QTemporaryFile::autoRemoveAfterFailedRename() cleaner.reset(); } +void tst_QTemporaryFile::QTBUG_4796_data() +{ + QTest::addColumn<QString>("prefix"); + QTest::addColumn<QString>("suffix"); + QTest::addColumn<bool>("openResult"); + + QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8"); + + QTest::newRow("<empty>") << QString() << QString() << true; + QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true; + QTest::newRow("XXXXXXbla") << QString() << QString("bla") << true; + QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false; + QTest::newRow("XXXXXX<unicode>") << QString() << unicode << true; + QTest::newRow("<unicode>XXXXXX") << unicode << QString() << true; + QTest::newRow("<unicode>XXXXXX<unicode>") << unicode << unicode << true; +} + +void tst_QTemporaryFile::QTBUG_4796() +{ + QVERIFY(QDir("test-XXXXXX").exists()); + + struct CleanOnReturn + { + ~CleanOnReturn() + { + Q_FOREACH(QString tempName, tempNames) + QFile::remove(tempName); + } + + void reset() + { + tempNames.clear(); + } + + QStringList tempNames; + }; + + CleanOnReturn cleaner; + + QFETCH(QString, prefix); + QFETCH(QString, suffix); + QFETCH(bool, openResult); + + { + QString fileTemplate1 = prefix + QString("XX") + suffix; + QString fileTemplate2 = prefix + QString("XXXX") + suffix; + QString fileTemplate3 = prefix + QString("XXXXXX") + suffix; + QString fileTemplate4 = prefix + QString("XXXXXXXX") + suffix; + + QTemporaryFile file1(fileTemplate1); + QTemporaryFile file2(fileTemplate2); + QTemporaryFile file3(fileTemplate3); + QTemporaryFile file4(fileTemplate4); + QTemporaryFile file5("test-XXXXXX/" + fileTemplate1); + QTemporaryFile file6("test-XXXXXX/" + fileTemplate3); + + QCOMPARE(file1.open(), openResult); + QCOMPARE(file2.open(), openResult); + QCOMPARE(file3.open(), openResult); + QCOMPARE(file4.open(), openResult); + QCOMPARE(file5.open(), openResult); + QCOMPARE(file6.open(), openResult); + + QCOMPARE(file1.exists(), openResult); + QCOMPARE(file2.exists(), openResult); + QCOMPARE(file3.exists(), openResult); + QCOMPARE(file4.exists(), openResult); + QCOMPARE(file5.exists(), openResult); + QCOMPARE(file6.exists(), openResult); + + // make sure the file exists under the *correct* name + if (openResult) { + cleaner.tempNames << file1.fileName() + << file2.fileName() + << file3.fileName() + << file4.fileName() + << file5.fileName() + << file6.fileName(); + + QVERIFY(file1.fileName().startsWith(fileTemplate1 + QLatin1Char('.'))); + QVERIFY(file2.fileName().startsWith(fileTemplate2 + QLatin1Char('.'))); + QVERIFY(file5.fileName().startsWith("test-XXXXXX/" + fileTemplate1 + QLatin1Char('.'))); + QVERIFY(file6.fileName().startsWith("test-XXXXXX/" + prefix)); + + if (!prefix.isEmpty()) { + QVERIFY(file3.fileName().startsWith(prefix)); + QVERIFY(file4.fileName().startsWith(prefix)); + } + + if (!suffix.isEmpty()) { + QVERIFY(file3.fileName().endsWith(suffix)); + QVERIFY(file4.fileName().endsWith(suffix)); + QVERIFY(file6.fileName().endsWith(suffix)); + } + } + } + + Q_FOREACH(QString const &tempName, cleaner.tempNames) + QVERIFY( !QFile::exists(tempName) ); + + cleaner.reset(); +} + QTEST_MAIN(tst_QTemporaryFile) #include "tst_qtemporaryfile.moc" 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/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index 7386d9d..6ad0678 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -103,6 +103,7 @@ private slots: void adoptedThreadExit(); void adoptedThreadExec(); void adoptedThreadFinished(); + void adoptedThreadExecFinished(); void adoptMultipleThreads(); void adoptMultipleThreadsOverlap(); @@ -913,6 +914,21 @@ void tst_QThread::adoptedThreadFinished() QVERIFY(!QTestEventLoop::instance().timeout()); } +void tst_QThread::adoptedThreadExecFinished() +{ + NativeThreadWrapper nativeThread; + nativeThread.setWaitForStop(); + nativeThread.startAndWait(adoptedThreadExecFunction); + + QObject::connect(nativeThread.qthread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + nativeThread.stop(); + nativeThread.join(); + + QTestEventLoop::instance().enterLoop(5); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + void tst_QThread::adoptMultipleThreads() { #if defined(Q_OS_WIN) diff --git a/tests/auto/qudpsocket/clientserver/clientserver.pro b/tests/auto/qudpsocket/clientserver/clientserver.pro index 5fe65b3..6da1486 100644 --- a/tests/auto/qudpsocket/clientserver/clientserver.pro +++ b/tests/auto/qudpsocket/clientserver/clientserver.pro @@ -5,4 +5,4 @@ CONFIG -= app_bundle TARGET = clientserver DESTDIR = ./ - +symbian: TARGET.CAPABILITY += NetworkServices diff --git a/tests/auto/qudpsocket/qudpsocket.pro b/tests/auto/qudpsocket/qudpsocket.pro index 8fd3545..4ddb717 100644 --- a/tests/auto/qudpsocket/qudpsocket.pro +++ b/tests/auto/qudpsocket/qudpsocket.pro @@ -1,6 +1,4 @@ TEMPLATE = subdirs SUBDIRS = test clientserver -symbian: TARGET.CAPABILITY = NetworkServices - diff --git a/tests/auto/qudpsocket/test/test.pro b/tests/auto/qudpsocket/test/test.pro index 7e5ffe4..b68d30c 100644 --- a/tests/auto/qudpsocket/test/test.pro +++ b/tests/auto/qudpsocket/test/test.pro @@ -22,4 +22,4 @@ wince*|symbian: { TARGET = tst_qudpsocket - +symbian: TARGET.CAPABILITY += NetworkServices diff --git a/tests/auto/qudpsocket/tst_qudpsocket.cpp b/tests/auto/qudpsocket/tst_qudpsocket.cpp index 6ba55b2..2c8049f 100644 --- a/tests/auto/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/qudpsocket/tst_qudpsocket.cpp @@ -55,9 +55,15 @@ #include <qstringlist.h> #include "../network-settings.h" +#ifndef QT_NO_BEARERMANAGEMENT +#include <QtNetwork/qnetworkconfigmanager.h> +#include <QtNetwork/qnetworkconfiguration.h> +#include <QtNetwork/qnetworksession.h> +#endif + Q_DECLARE_METATYPE(QHostAddress) Q_DECLARE_METATYPE(QNetworkInterface) - +Q_DECLARE_METATYPE(QSharedPointer<QNetworkSession>) //TESTED_CLASS= //TESTED_FILES= @@ -108,10 +114,19 @@ private slots: void setMulticastInterface(); void multicast_data(); void multicast(); + void echo_data(); + void echo(); protected slots: void empty_readyReadSlot(); void empty_connectedSlot(); + +private: +#ifndef QT_NO_BEARERMANAGEMENT + QNetworkConfigurationManager *netConfMan; + QNetworkConfiguration networkConfiguration; + QSharedPointer<QNetworkSession> networkSession; +#endif }; tst_QUdpSocket::tst_QUdpSocket() @@ -130,6 +145,16 @@ void tst_QUdpSocket::initTestCase_data() QTest::newRow("WithoutProxy") << false << 0; QTest::newRow("WithSocks5Proxy") << true << int(QNetworkProxy::Socks5Proxy); + +#ifndef QT_NO_BEARERMANAGEMENT + netConfMan = new QNetworkConfigurationManager(this); + networkConfiguration = netConfMan->defaultConfiguration(); + networkSession = QSharedPointer<QNetworkSession>(new QNetworkSession(networkConfiguration)); + if (!networkSession->isOpen()) { + networkSession->open(); + QVERIFY(networkSession->waitForOpened(30000)); + } +#endif } void tst_QUdpSocket::init() @@ -154,6 +179,9 @@ void tst_QUdpSocket::cleanup() void tst_QUdpSocket::constructing() { QUdpSocket socket; +#ifdef FORCE_SESSION + socket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(socket.isSequential()); QVERIFY(!socket.isOpen()); @@ -171,6 +199,9 @@ void tst_QUdpSocket::constructing() void tst_QUdpSocket::unconnectedServerAndClientTest() { QUdpSocket serverSocket; +#ifdef FORCE_SESSION + serverSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState"); @@ -181,11 +212,14 @@ void tst_QUdpSocket::unconnectedServerAndClientTest() const char *message[] = {"Yo mista", "Yo", "Wassap"}; QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(serverSocket.localAddress() == QHostAddress::Any)) + if (!(serverSocket.localAddress() == QHostAddress::Any || serverSocket.localAddress() == QHostAddress::AnyIPv6)) serverAddress = serverSocket.localAddress(); for (int i = 0; i < 3; ++i) { QUdpSocket clientSocket; +#ifdef FORCE_SESSION + clientSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QCOMPARE(int(clientSocket.writeDatagram(message[i], strlen(message[i]), serverAddress, serverSocket.localPort())), int(strlen(message[i]))); @@ -216,8 +250,21 @@ void tst_QUdpSocket::broadcasting() #endif const char *message[] = {"Yo mista", "", "Yo", "Wassap"}; + QList<QHostAddress> broadcastAddresses; + foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) { + if ((iface.flags() & QNetworkInterface::CanBroadcast) + && iface.flags() & QNetworkInterface::IsUp) { + for (int i=0;i<iface.addressEntries().count();i++) + broadcastAddresses.append(iface.addressEntries().at(i).broadcast()); + } + } + if (broadcastAddresses.isEmpty()) + QSKIP("No interface can broadcast", SkipAll); for (int i = 0; i < 4; ++i) { QUdpSocket serverSocket; +#ifdef FORCE_SESSION + serverSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(serverSocket.bind(QHostAddress::Any, 5000), serverSocket.errorString().toLatin1().constData()); QCOMPARE(serverSocket.state(), QUdpSocket::BoundState); @@ -225,10 +272,18 @@ void tst_QUdpSocket::broadcasting() connect(&serverSocket, SIGNAL(readyRead()), SLOT(empty_readyReadSlot())); QUdpSocket broadcastSocket; +#ifdef FORCE_SESSION + broadcastSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + broadcastSocket.bind(); for (int j = 0; j < 100; ++j) { - broadcastSocket.writeDatagram(message[i], strlen(message[i]), - QHostAddress::Broadcast, 5000); + for (int k = 0; k < 4; k++) { + broadcastSocket.writeDatagram(message[i], strlen(message[i]), + QHostAddress::Broadcast, 5000); + foreach (QHostAddress addr, broadcastAddresses) + broadcastSocket.writeDatagram(message[i], strlen(message[i]), addr, 5000); + } QTestEventLoop::instance().enterLoop(15); if (QTestEventLoop::instance().timeout()) { #if defined(Q_OS_FREEBSD) @@ -279,15 +334,19 @@ void tst_QUdpSocket::loop() QUdpSocket peter; QUdpSocket paul; +#ifdef FORCE_SESSION + peter.setProperty("_q_networksession", QVariant::fromValue(networkSession)); + paul.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(peter.bind(), peter.errorString().toLatin1().constData()); QVERIFY2(paul.bind(), paul.errorString().toLatin1().constData()); QHostAddress peterAddress = QHostAddress::LocalHost; - if (!(peter.localAddress() == QHostAddress::Any)) + if (!(peter.localAddress() == QHostAddress::Any || peter.localAddress() == QHostAddress::AnyIPv6)) peterAddress = peter.localAddress(); QHostAddress pualAddress = QHostAddress::LocalHost; - if (!(paul.localAddress() == QHostAddress::Any)) + if (!(paul.localAddress() == QHostAddress::Any || paul.localAddress() == QHostAddress::AnyIPv6)) pualAddress = paul.localAddress(); QCOMPARE(peter.writeDatagram(peterMessage.data(), peterMessage.length(), @@ -320,8 +379,8 @@ void tst_QUdpSocket::ipv6Loop_data() void tst_QUdpSocket::ipv6Loop() { -#if defined(Q_OS_SYMBIAN) - QSKIP("Symbian IPv6 is not yet supported", SkipAll); +#if defined(QT_NO_IPV6) + QSKIP("IPv6 is not yet supported", SkipAll); #endif QFETCH(QByteArray, peterMessage); QFETCH(QByteArray, paulMessage); @@ -329,6 +388,10 @@ void tst_QUdpSocket::ipv6Loop() QUdpSocket peter; QUdpSocket paul; +#ifdef FORCE_SESSION + peter.setProperty("_q_networksession", QVariant::fromValue(networkSession)); + paul.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif quint16 peterPort = 28124; quint16 paulPort = 28123; @@ -380,9 +443,13 @@ void tst_QUdpSocket::empty_connectedSlot() void tst_QUdpSocket::readLine() { QUdpSocket socket1; + QUdpSocket socket2; +#ifdef FORCE_SESSION + socket1.setProperty("_q_networksession", QVariant::fromValue(networkSession)); + socket2.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(socket1.bind(), socket1.errorString().toLatin1().constData()); - QUdpSocket socket2; socket2.connectToHost("127.0.0.1", socket1.localPort()); QVERIFY(socket2.waitForConnected(5000)); } @@ -392,13 +459,19 @@ void tst_QUdpSocket::readLine() void tst_QUdpSocket::pendingDatagramSize() { QUdpSocket server; +#ifdef FORCE_SESSION + server.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(server.bind(), server.errorString().toLatin1().constData()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.localAddress() == QHostAddress::Any)) + if (!(server.localAddress() == QHostAddress::Any || server.localAddress() == QHostAddress::AnyIPv6)) serverAddress = server.localAddress(); QUdpSocket client; +#ifdef FORCE_SESSION + client.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(client.writeDatagram("this is", 7, serverAddress, server.localPort()) == 7); QVERIFY(client.writeDatagram(0, 0, serverAddress, server.localPort()) == 0); QVERIFY(client.writeDatagram("3 messages", 10, serverAddress, server.localPort()) == 10); @@ -440,13 +513,19 @@ void tst_QUdpSocket::pendingDatagramSize() void tst_QUdpSocket::writeDatagram() { QUdpSocket server; +#ifdef FORCE_SESSION + server.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(server.bind(), server.errorString().toLatin1().constData()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.localAddress() == QHostAddress::Any)) + if (!(server.localAddress() == QHostAddress::Any || server.localAddress() == QHostAddress::AnyIPv6)) serverAddress = server.localAddress(); QUdpSocket client; +#ifdef FORCE_SESSION + client.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif qRegisterMetaType<qint64>("qint64"); qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError"); @@ -473,8 +552,16 @@ void tst_QUdpSocket::writeDatagram() QCOMPARE(*static_cast<const qint64 *>(bytesspy.at(0).at(0).constData()), qint64(i * 1024)); QCOMPARE(errorspy.count(), 0); - if (!server.waitForReadyRead(5000)) + if (!server.waitForReadyRead(5000)) { +#ifdef Q_OS_SYMBIAN + //symbian receive buffer for datagrams is ~30k, but it can send datagrams up to the maximum 64k... + if (i > 28) { + i = 64; + continue; + } +#endif QSKIP(QString("UDP packet lost at size %1, unable to complete the test.").arg(i * 1024).toLatin1().data(), SkipSingle); + } QCOMPARE(server.pendingDatagramSize(), qint64(i * 1024)); QCOMPARE(server.readDatagram(0, 0), qint64(0)); } @@ -499,14 +586,21 @@ void tst_QUdpSocket::performance() #endif // Q_OS_SYMBIAN QUdpSocket server; +#ifdef FORCE_SESSION + server.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(server.bind(), server.errorString().toLatin1().constData()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.localAddress() == QHostAddress::Any)) + if (!(server.localAddress() == QHostAddress::Any || server.localAddress() == QHostAddress::AnyIPv6)) serverAddress = server.localAddress(); QUdpSocket client; +#ifdef FORCE_SESSION + client.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif client.connectToHost(serverAddress, server.localPort()); + QVERIFY(client.waitForConnected(10000)); QTime stopWatch; stopWatch.start(); @@ -546,8 +640,14 @@ void tst_QUdpSocket::bindMode() } QUdpSocket socket; +#ifdef FORCE_SESSION + socket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY2(socket.bind(), socket.errorString().toLatin1().constData()); QUdpSocket socket2; +#ifdef FORCE_SESSION + socket2.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(!socket2.bind(socket.localPort())); #if defined(Q_OS_SYMBIAN) if(RProcess().HasCapability(ECapabilityNetworkControl)) { @@ -617,16 +717,12 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer_data() QTest::addColumn<bool>("bind"); QTest::addColumn<QHostAddress>("peerAddress"); QHostAddress localhost(QHostAddress::LocalHost); -#if !defined(Q_OS_SYMBIAN) QHostAddress remote = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(); -#endif QTest::newRow("localhost-unbound") << false << localhost; QTest::newRow("localhost-bound") << true << localhost; -#if !defined(Q_OS_SYMBIAN) QTest::newRow("remote-unbound") << false << remote; QTest::newRow("remote-bound") << true << remote; -#endif } void tst_QUdpSocket::writeDatagramToNonExistingPeer() @@ -637,6 +733,9 @@ void tst_QUdpSocket::writeDatagramToNonExistingPeer() quint16 peerPort = 33533 + int(bind); QUdpSocket sUdp; +#ifdef FORCE_SESSION + sUdp.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QSignalSpy sReadyReadSpy(&sUdp, SIGNAL(readyRead())); if (bind) QVERIFY(sUdp.bind()); @@ -649,14 +748,10 @@ void tst_QUdpSocket::writeToNonExistingPeer_data() { QTest::addColumn<QHostAddress>("peerAddress"); QHostAddress localhost(QHostAddress::LocalHost); -#if !defined(Q_OS_SYMBIAN) QHostAddress remote = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first(); -#endif // write (required to be connected) QTest::newRow("localhost") << localhost; -#if !defined(Q_OS_SYMBIAN) QTest::newRow("remote") << remote; -#endif } void tst_QUdpSocket::writeToNonExistingPeer() @@ -667,9 +762,13 @@ void tst_QUdpSocket::writeToNonExistingPeer() qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError"); QUdpSocket sConnected; +#ifdef FORCE_SESSION + sConnected.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QSignalSpy sConnectedReadyReadSpy(&sConnected, SIGNAL(readyRead())); QSignalSpy sConnectedErrorSpy(&sConnected, SIGNAL(error(QAbstractSocket::SocketError))); sConnected.connectToHost(peerAddress, peerPort, QIODevice::ReadWrite); + QVERIFY(sConnected.waitForConnected(10000)); // the first write succeeds... QCOMPARE(sConnected.write("", 1), qint64(1)); @@ -843,12 +942,18 @@ void tst_QUdpSocket::zeroLengthDatagram() return; QUdpSocket receiver; +#ifdef FORCE_SESSION + receiver.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QVERIFY(receiver.bind()); QVERIFY(!receiver.waitForReadyRead(100)); QVERIFY(!receiver.hasPendingDatagrams()); QUdpSocket sender; +#ifdef FORCE_SESSION + sender.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif QCOMPARE(sender.writeDatagram(QByteArray(), QHostAddress::LocalHost, receiver.localPort()), qint64(0)); QVERIFY(receiver.waitForReadyRead(1000)); @@ -890,6 +995,9 @@ void tst_QUdpSocket::multicastTtlOption() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind, but ignore the result, we are only interested in initializing the socket (void) udpSocket.bind(bindAddress, 0); udpSocket.setSocketOption(QUdpSocket::MulticastTtlOption, ttl); @@ -929,6 +1037,9 @@ void tst_QUdpSocket::multicastLoopbackOption() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind, but ignore the result, we are only interested in initializing the socket (void) udpSocket.bind(bindAddress, 0); udpSocket.setSocketOption(QUdpSocket::MulticastLoopbackOption, loopback); @@ -949,6 +1060,9 @@ void tst_QUdpSocket::multicastJoinBeforeBind() QFETCH(QHostAddress, groupAddress); QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // cannot join group before binding QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::joinMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); QVERIFY(!udpSocket.joinMulticastGroup(groupAddress)); @@ -970,8 +1084,16 @@ void tst_QUdpSocket::multicastLeaveAfterClose() } QUdpSocket udpSocket; +#ifdef FORCE_SESSION + udpSocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif +#ifdef Q_OS_SYMBIAN + QVERIFY2(udpSocket.bind(), + qPrintable(udpSocket.errorString())); +#else QVERIFY2(udpSocket.bind(groupAddress, 0), qPrintable(udpSocket.errorString())); +#endif QVERIFY2(udpSocket.joinMulticastGroup(groupAddress), qPrintable(udpSocket.errorString())); udpSocket.close(); @@ -995,6 +1117,9 @@ void tst_QUdpSocket::setMulticastInterface_data() void tst_QUdpSocket::setMulticastInterface() { +#ifdef Q_OS_SYMBIAN + QSKIP("Symbian has no IPV6_MULTICAST_IF equivalent", SkipAll); +#else QFETCH_GLOBAL(bool, setProxy); QFETCH(QNetworkInterface, iface); QFETCH(QHostAddress, address); @@ -1017,6 +1142,7 @@ void tst_QUdpSocket::setMulticastInterface() } else { QVERIFY(!iface2.isValid()); } +#endif } void tst_QUdpSocket::multicast_data() @@ -1056,8 +1182,17 @@ void tst_QUdpSocket::multicast() } QUdpSocket receiver; +#ifdef FORCE_SESSION + receiver.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif // bind first, then verify that we can join the multicast group +#ifdef Q_OS_SYMBIAN + if (!setProxy) { + QEXPECT_FAIL("same bind, group ipv4 address", "bind to group address not supported on symbian", Abort); + QEXPECT_FAIL("same bind, group ipv6 address", "bind to group address not supported on symbian", Abort); + } +#endif QVERIFY2(receiver.bind(bindAddress, 0) == bindResult, qPrintable(receiver.errorString())); if (!bindResult) @@ -1075,6 +1210,10 @@ void tst_QUdpSocket::multicast() << QByteArray("cdef"); QUdpSocket sender; +#ifdef FORCE_SESSION + sender.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + sender.bind(); foreach (const QByteArray &datagram, datagrams) { QCOMPARE(int(sender.writeDatagram(datagram, groupAddress, receiver.localPort())), int(datagram.size())); @@ -1090,10 +1229,68 @@ void tst_QUdpSocket::multicast() receiver.readDatagram(datagram.data(), datagram.size(), 0, 0); receivedDatagrams << datagram; } +#ifdef Q_OS_SYMBIAN + QEXPECT_FAIL("valid bind, group ipv4 address", "IPv4 multicast not supported on symbian", Abort); +#endif QCOMPARE(receivedDatagrams, datagrams); QVERIFY2(receiver.leaveMulticastGroup(groupAddress), qPrintable(receiver.errorString())); } +void tst_QUdpSocket::echo_data() +{ + QTest::addColumn<bool>("connect"); + QTest::newRow("writeDatagram") << false; + QTest::newRow("write") << true; +} + +void tst_QUdpSocket::echo() +{ + QFETCH(bool, connect); + QHostInfo info = QHostInfo::fromName(QtNetworkSettings::serverName()); + QVERIFY(info.addresses().count()); + QHostAddress remote = info.addresses().first(); + + QUdpSocket sock; +#ifdef FORCE_SESSION + sock.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + if (connect) { + sock.connectToHost(remote, 7); + QVERIFY(sock.waitForConnected(10000)); + } else { + sock.bind(); + } + QByteArray out(30, 'x'); + QByteArray in; + int successes = 0; + for (int i=0;i<10;i++) { + if (connect) { + sock.write(out); + } else { + sock.writeDatagram(out, remote, 7); + } + if (sock.waitForReadyRead(1000)) { + while (sock.hasPendingDatagrams()) { + QHostAddress from; + quint16 port; + if (connect) { + in = sock.read(sock.pendingDatagramSize()); + } else { + in.resize(sock.pendingDatagramSize()); + sock.readDatagram(in.data(), in.length(), &from, &port); + } + if (in==out) + successes++; + } + } + if (!sock.isValid()) + QFAIL(sock.errorString().toLatin1().constData()); + qDebug() << "packets in" << successes << "out" << i; + QTest::qWait(50); //choke to avoid triggering flood/DDoS protections on echo service + } + QVERIFY(successes >= 9); +} + QTEST_MAIN(tst_QUdpSocket) #include "tst_qudpsocket.moc" diff --git a/tests/auto/qvariant/tst_qvariant.cpp b/tests/auto/qvariant/tst_qvariant.cpp index 62babdb..6ebe84e 100644 --- a/tests/auto/qvariant/tst_qvariant.cpp +++ b/tests/auto/qvariant/tst_qvariant.cpp @@ -275,6 +275,8 @@ private slots: void variantInVariant(); void colorInteger(); + + void forwardDeclare(); }; Q_DECLARE_METATYPE(QDate) @@ -2660,7 +2662,10 @@ void tst_QVariant::qvariant_cast_QObject_data() { QTest::addColumn<QVariant>("data"); QTest::addColumn<bool>("success"); - QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, new QObject(this)) << true; + QObject *obj = new QObject(this); + obj->setObjectName(QString::fromLatin1("Hello")); + QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, &obj) << true; + QTest::newRow("from QObject2") << QVariant::fromValue(obj) << true; QTest::newRow("from String") << QVariant(QLatin1String("1, 2, 3")) << false; QTest::newRow("from int") << QVariant((int) 123) << false; } @@ -2672,6 +2677,9 @@ void tst_QVariant::qvariant_cast_QObject() { QObject *o = qvariant_cast<QObject *>(data); QCOMPARE(o != 0, success); + if (success) { + QCOMPARE(o->objectName(), QString::fromLatin1("Hello")); + } } Q_DECLARE_METATYPE(qint8); @@ -3433,5 +3441,16 @@ void tst_QVariant::colorInteger() QCOMPARE(v.value<QColor>(), QColor(Qt::yellow)); } +class Forward; +Q_DECLARE_METATYPE(Forward*); + +void tst_QVariant::forwardDeclare() +{ + Forward *f = 0; + QVariant v = QVariant::fromValue(f); + QCOMPARE(qvariant_cast<Forward*>(v), f); +} + + QTEST_MAIN(tst_QVariant) #include "tst_qvariant.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 } } diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro index 00a1b37..b5e3a4b 100644 --- a/tests/benchmarks/benchmarks.pro +++ b/tests/benchmarks/benchmarks.pro @@ -7,6 +7,7 @@ SUBDIRS = \ svg contains(QT_CONFIG, opengl): SUBDIRS += opengl contains(QT_CONFIG, declarative): SUBDIRS += declarative +contains(QT_CONFIG, dbus): SUBDIRS += dbus check-trusted.CONFIG += recursive QMAKE_EXTRA_TARGETS += check-trusted diff --git a/tests/benchmarks/corelib/io/qdir/qdir.pro b/tests/benchmarks/corelib/io/qdir/qdir.pro index c572566..2c18e75 100644 --- a/tests/benchmarks/corelib/io/qdir/qdir.pro +++ b/tests/benchmarks/corelib/io/qdir/qdir.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs -SUBDIRS = 10000 +SUBDIRS = \ + 10000 \ + tree diff --git a/tests/benchmarks/dbus/dbus.pro b/tests/benchmarks/dbus/dbus.pro new file mode 100644 index 0000000..989a0db --- /dev/null +++ b/tests/benchmarks/dbus/dbus.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = \ + qdbusperformance \ + qdbustype diff --git a/tests/auto/qdbusperformance/.gitignore b/tests/benchmarks/dbus/qdbusperformance/.gitignore index 4cd8399..4cd8399 100644 --- a/tests/auto/qdbusperformance/.gitignore +++ b/tests/benchmarks/dbus/qdbusperformance/.gitignore diff --git a/tests/benchmarks/dbus/qdbusperformance/qdbusperformance.pro b/tests/benchmarks/dbus/qdbusperformance/qdbusperformance.pro new file mode 100644 index 0000000..90f88a7 --- /dev/null +++ b/tests/benchmarks/dbus/qdbusperformance/qdbusperformance.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS = server test diff --git a/tests/auto/qdbusperformance/server/server.cpp b/tests/benchmarks/dbus/qdbusperformance/server/server.cpp index 3bd5efc..3bd5efc 100644 --- a/tests/auto/qdbusperformance/server/server.cpp +++ b/tests/benchmarks/dbus/qdbusperformance/server/server.cpp diff --git a/tests/auto/qdbusperformance/server/server.pro b/tests/benchmarks/dbus/qdbusperformance/server/server.pro index 30f81dd..30f81dd 100644 --- a/tests/auto/qdbusperformance/server/server.pro +++ b/tests/benchmarks/dbus/qdbusperformance/server/server.pro diff --git a/tests/auto/qdbusperformance/serverobject.h b/tests/benchmarks/dbus/qdbusperformance/serverobject.h index 6f85bb4..6f85bb4 100644 --- a/tests/auto/qdbusperformance/serverobject.h +++ b/tests/benchmarks/dbus/qdbusperformance/serverobject.h diff --git a/tests/auto/qdbusperformance/test/test.pro b/tests/benchmarks/dbus/qdbusperformance/test/test.pro index 9f5712e..9f5712e 100644 --- a/tests/auto/qdbusperformance/test/test.pro +++ b/tests/benchmarks/dbus/qdbusperformance/test/test.pro diff --git a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp b/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp index a5b4b98..a5b4b98 100644 --- a/tests/auto/qdbusperformance/tst_qdbusperformance.cpp +++ b/tests/benchmarks/dbus/qdbusperformance/tst_qdbusperformance.cpp diff --git a/tests/benchmarks/dbus/qdbustype/main.cpp b/tests/benchmarks/dbus/qdbustype/main.cpp new file mode 100644 index 0000000..abaae7e --- /dev/null +++ b/tests/benchmarks/dbus/qdbustype/main.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 benchmarkSignature_data(); + void benchmarkSignature(); +}; + +static inline void benchmarkAddRow(const char *name, const char *data) +{ + QTest::newRow(QByteArray("native-") + name) << data << true; + QTest::newRow(name) << data << false; +} + +void tst_QDBusType::benchmarkSignature_data() +{ + QTest::addColumn<QString>("data"); + QTest::addColumn<bool>("useNative"); + + for (int loopCount = 0; loopCount < 2; ++loopCount) { + bool useNative = loopCount; + QByteArray prefix = useNative ? "native-" : ""; + + benchmarkAddRow("single-invalid", "~"); + benchmarkAddRow("single-invalid-array", "a~"); + benchmarkAddRow("single-invalid-struct", "(.)"); + + benchmarkAddRow("single-char", "b"); + benchmarkAddRow("single-array", "as"); + benchmarkAddRow("single-simplestruct", "(y)"); + benchmarkAddRow("single-simpledict", "a{sv}"); + benchmarkAddRow("single-complexdict", "a{s(aya{io})}"); + + benchmarkAddRow("multiple-char", "ssg"); + benchmarkAddRow("multiple-arrays", "asasay"); + + benchmarkAddRow("struct-missingclose", "(ayyyy"); + benchmarkAddRow("longstruct", "(yyyyyyayasy)"); + benchmarkAddRow("invalid-longstruct", "(yyyyyyayas.y)"); + benchmarkAddRow("complexstruct", "(y(aasay)oga{sv})"); + benchmarkAddRow("multiple-simple-structs", "(y)(y)(y)"); + } +} + +void tst_QDBusType::benchmarkSignature() +{ + QFETCH(QString, data); + QFETCH(bool, useNative); + + bool result; + if (useNative) { + dbus_signature_validate(data.toLatin1(), 0); + QBENCHMARK { + result = dbus_signature_validate(data.toLatin1(), 0); + } + } else { + QDBusUtil::isValidSignature(data); + QBENCHMARK { + result = QDBusUtil::isValidSignature(data); + } + } + Q_UNUSED(result); +} + +QTEST_MAIN(tst_QDBusType) + +#include "main.moc" diff --git a/tests/benchmarks/dbus/qdbustype/qdbustype.pro b/tests/benchmarks/dbus/qdbustype/qdbustype.pro new file mode 100644 index 0000000..d480a05 --- /dev/null +++ b/tests/benchmarks/dbus/qdbustype/qdbustype.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +TARGET = tst_bench_qdbustype +QT -= gui +QT += dbus +QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS +LIBS_PRIVATE += $$QT_LIBS_DBUS + +SOURCES += main.cpp diff --git a/tests/benchmarks/network/access/access.pro b/tests/benchmarks/network/access/access.pro index 43357e2..6cbd367 100644 --- a/tests/benchmarks/network/access/access.pro +++ b/tests/benchmarks/network/access/access.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = \ qfile_vs_qnetworkaccessmanager \ - qnetworkreply + qnetworkreply \ + qnetworkdiskcache diff --git a/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro b/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro new file mode 100644 index 0000000..7f665b3 --- /dev/null +++ b/tests/benchmarks/network/access/qnetworkdiskcache/qnetworkdiskcache.pro @@ -0,0 +1,15 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_bench_qnetworkdiskcache +DEPENDPATH += . +INCLUDEPATH += . + +QT += gui # for QDesktopServices +QT += network testlib + +CONFIG += release + +# Input +SOURCES += tst_qnetworkdiskcache.cpp + + diff --git a/tests/benchmarks/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp b/tests/benchmarks/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp new file mode 100644 index 0000000..55cbf55 --- /dev/null +++ b/tests/benchmarks/network/access/qnetworkdiskcache/tst_qnetworkdiskcache.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 <QNetworkDiskCache> +#include <QNetworkCacheMetaData> +#include <QDir> +#include <QBuffer> +#include <QTextStream> +#include <QDebug> +#include <QtTest/QtTest> +#include <QIODevice> +#include <QDesktopServices> + + + +enum Numbers { NumFakeCacheObjects = 200, //entries in pre-populated cache + NumInsertions = 100, //insertions to be timed + NumRemovals = 100, //removals to be timed + NumReadContent = 100, //meta requests to be timed + HugeCacheLimit = 50*1024*1024, // max size for a big cache + TinyCacheLimit = 1*512*1024}; // max size for a tiny cache + +const QString fakeURLbase = "http://127.0.0.1/fake/"; +//fake HTTP body aka payload +const QByteArray payload("Qt rocks!"); + +class tst_qnetworkdiskcache : public QObject +{ + Q_OBJECT +private: + void injectFakeData(); + void insertOneItem(); + bool isUrlCached(quint32 id); + void cleanRecursive(QString &path); + void cleanupCacheObject(); + void initCacheObject(); + QString cacheDir; + QNetworkDiskCache *cache; + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + + void timeInsertion_data(); + void timeInsertion(); + void timeRead_data(); + void timeRead(); + void timeRemoval_data(); + void timeRemoval(); + + void timeExpiration_data(); + void timeExpiration(); +}; + + +void tst_qnetworkdiskcache::initTestCase() +{ + cache = 0; +} + + +void tst_qnetworkdiskcache::cleanupTestCase() +{ + cleanupCacheObject(); + cleanRecursive(cacheDir); +} + +void tst_qnetworkdiskcache::timeInsertion_data() +{ + QTest::addColumn<QString>("cacheRootDirectory"); + + QString cacheLoc = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); + QTest::newRow("QDesktopServices Cache Location") << cacheLoc; +#ifdef Q_OS_SYMBIAN + if (QDir::drives().contains(QFileInfo("E:\\"))) + QTest::newRow("Symbian E: drive") << cacheLoc.replace(0, 1, QString("E")); +#endif + +} + +//This functions times an insert() operation. +//You can run it after populating the cache with +//fake data so that more realistic performance +//estimates are obtained. +void tst_qnetworkdiskcache::timeInsertion() +{ + + QFETCH(QString, cacheRootDirectory); + + cacheDir = QString( cacheRootDirectory + QDir::separator() + "man_qndc"); + QDir d; + qDebug() << "Setting cache directory to = " << d.absoluteFilePath(cacheDir); + + //Housekeeping + cleanRecursive(cacheDir); // slow op. + initCacheObject(); + + cache->setCacheDirectory(cacheDir); + cache->setMaximumCacheSize(qint64(HugeCacheLimit)); + cache->clear(); + + //populate some fake data to simulate partially full cache + injectFakeData(); // SLOW + + //Sanity-check that the first URL that we insert below isn't already in there. + QVERIFY(isUrlCached(NumFakeCacheObjects) == false); + + // IMPORTANT: max cache size should be HugeCacheLimit, to avoid evictions below + //time insertion of previously-uncached URLs. + QBENCHMARK_ONCE { + for (quint32 i = NumFakeCacheObjects; i < (NumFakeCacheObjects + NumInsertions); i++) { + //prepare metata for url + QNetworkCacheMetaData meta; + QString fakeURL; + QTextStream stream(&fakeURL); + stream << fakeURLbase << i; + QUrl url(fakeURL); + meta.setUrl(url); + meta.setSaveToDisk(true); + + //commit payload and metadata to disk + QIODevice *device = cache->prepare(meta); + device->write(payload); + cache->insert(device); + } + } + + //SLOW cleanup + cleanupCacheObject(); + cleanRecursive(cacheDir); + +} + +void tst_qnetworkdiskcache::timeRead_data() +{ + QTest::addColumn<QString>("cacheRootDirectory"); + + QString cacheLoc = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); + QTest::newRow("QDesktopServices Cache Location") << cacheLoc; +#ifdef Q_OS_SYMBIAN + if (QDir::drives().contains(QFileInfo("E:\\"))) + QTest::newRow("Symbian E: drive") << cacheLoc.replace(0, 1, QString("E")); +#endif + +} + +//Times metadata as well payload lookup +// i.e metaData(), rawHeaders() and data() +void tst_qnetworkdiskcache::timeRead() +{ + + QFETCH(QString, cacheRootDirectory); + + cacheDir = QString( cacheRootDirectory + QDir::separator() + "man_qndc"); + QDir d; + qDebug() << "Setting cache directory to = " << d.absoluteFilePath(cacheDir); + + //Housekeeping + cleanRecursive(cacheDir); // slow op. + initCacheObject(); + cache->setCacheDirectory(cacheDir); + cache->setMaximumCacheSize(qint64(HugeCacheLimit)); + cache->clear(); + + //populate some fake data to simulate partially full cache + injectFakeData(); + + //Entries in the cache should be > what we try to remove + QVERIFY(NumFakeCacheObjects > NumReadContent); + + //time metadata lookup of previously inserted URL. + QBENCHMARK_ONCE { + for (quint32 i = 0; i < NumReadContent; i++) { + QString fakeURL; + QTextStream stream(&fakeURL); + stream << fakeURLbase << i; + QUrl url(fakeURL); + + QNetworkCacheMetaData qndc = cache->metaData(url); + QVERIFY(qndc.isValid()); // we must have read the metadata + + QNetworkCacheMetaData::RawHeaderList raw(qndc.rawHeaders()); + QVERIFY(raw.size()); // we must have parsed the headers from the meta + + QIODevice *iodevice(cache->data(url)); + QVERIFY(iodevice); //must not be NULL + iodevice->close(); + delete iodevice; + } + } + + //Cleanup (slow) + cleanupCacheObject(); + cleanRecursive(cacheDir); + +} + +void tst_qnetworkdiskcache::timeRemoval_data() +{ + QTest::addColumn<QString>("cacheRootDirectory"); + + QString cacheLoc = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); + QTest::newRow("QDesktopServices Cache Location") << cacheLoc; +#ifdef Q_OS_SYMBIAN + if (QDir::drives().contains(QFileInfo("E:\\"))) + QTest::newRow("Symbian E: drive") << cacheLoc.replace(0, 1, QString("E")); +#endif + +} + +void tst_qnetworkdiskcache::timeRemoval() +{ + + QFETCH(QString, cacheRootDirectory); + + cacheDir = QString( cacheRootDirectory + QDir::separator() + "man_qndc"); + QDir d; + qDebug() << "Setting cache directory to = " << d.absoluteFilePath(cacheDir); + + //Housekeeping + initCacheObject(); + cleanRecursive(cacheDir); // slow op. + cache->setCacheDirectory(cacheDir); + // Make max cache size HUGE, so that evictions don't happen below + cache->setMaximumCacheSize(qint64(HugeCacheLimit)); + cache->clear(); + + //populate some fake data to simulate partially full cache + injectFakeData(); + + //Sanity-check that the URL is already in there somewhere + QVERIFY(isUrlCached(NumRemovals-1) == true); + //Entries in the cache should be > what we try to remove + QVERIFY(NumFakeCacheObjects > NumRemovals); + + //time removal of previously-inserted URL. + QBENCHMARK_ONCE { + for (quint32 i = 0; i < NumRemovals; i++) { + QString fakeURL; + QTextStream stream(&fakeURL); + stream << fakeURLbase << i; + QUrl url(fakeURL); + cache->remove(url); + } + } + + //Cleanup (slow) + cleanupCacheObject(); + cleanRecursive(cacheDir); + +} + +void tst_qnetworkdiskcache::timeExpiration_data() +{ + QTest::addColumn<QString>("cacheRootDirectory"); + + QString cacheLoc = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); + QTest::newRow("QDesktopServices Cache Location") << cacheLoc; +#ifdef Q_OS_SYMBIAN + if (QDir::drives().contains(QFileInfo("E:\\"))) + QTest::newRow("Symbian E: drive") << cacheLoc.replace(0, 1, QString("E")); +#endif + +} +void tst_qnetworkdiskcache::timeExpiration() +{ + + QFETCH(QString, cacheRootDirectory); + + cacheDir = QString( cacheRootDirectory + QDir::separator() + "man_qndc"); + QDir d; + qDebug() << "Setting cache directory to = " << d.absoluteFilePath(cacheDir); + + //Housekeeping + initCacheObject(); + cleanRecursive(cacheDir); // slow op. + cache->setCacheDirectory(cacheDir); + // Make max cache size HUGE, so that evictions don't happen below + cache->setMaximumCacheSize(qint64(HugeCacheLimit)); + cache->clear(); + + //populate some fake data to simulate partially full cache + injectFakeData(); + + //Sanity-check that the URL is already in there somewhere + QVERIFY(isUrlCached(NumRemovals-1) == true); + //Entries in the cache should be > what we try to remove + QVERIFY(NumFakeCacheObjects > NumRemovals); + + + //Set cache limit lower, so this force 1 round of eviction + cache->setMaximumCacheSize(qint64(TinyCacheLimit)); + + //time insertions of additional content, which is likely to internally cause evictions + QBENCHMARK_ONCE { + for (quint32 i = NumFakeCacheObjects; i < (NumFakeCacheObjects + NumInsertions); i++) { + //prepare metata for url + QNetworkCacheMetaData meta; + QString fakeURL; + QTextStream stream(&fakeURL); + stream << fakeURLbase << i;//codescanner::leave + QUrl url(fakeURL); + meta.setUrl(url); + meta.setSaveToDisk(true); + + //commit payload and metadata to disk + QIODevice *device = cache->prepare(meta); + device->write(payload); + cache->insert(device); // this should trigger evictions, if TinyCacheLimit is small enough + } + } + + //Cleanup (slow) + cleanupCacheObject(); + cleanRecursive(cacheDir); + +} +// This function simulates a partially or fully occupied disk cache +// like a normal user of a cache might encounter is real-life browsing. +// The point of this is to trigger degradation in file-system and media performance +// that occur due to the quantity and layout of data. +void tst_qnetworkdiskcache::injectFakeData() +{ + + QNetworkCacheMetaData::RawHeaderList headers; + headers.append(qMakePair(QByteArray("X-TestHeader"),QByteArray("HeaderValue"))); + + + //Prep cache dir with fake data using QNetworkDiskCache APIs + for (quint32 i = 0; i < NumFakeCacheObjects; i++) { + + //prepare metata for url + QNetworkCacheMetaData meta; + QString fakeURL; + QTextStream stream(&fakeURL); + stream << fakeURLbase << i; + QUrl url(fakeURL); + meta.setUrl(url); + meta.setRawHeaders(headers); + meta.setSaveToDisk(true); + + //commit payload and metadata to disk + QIODevice *device = cache->prepare(meta); + device->write(payload); + cache->insert(device); + } + +} + + +// Checks if the fake URL #id is already cached or not. +bool tst_qnetworkdiskcache::isUrlCached(quint32 id) +{ + QString str; + QTextStream stream(&str); + stream << fakeURLbase << id; + QUrl url(str); + QIODevice *iod = cache->data(url); + return ((iod == 0) ? false : true) ; + +} + + +// Utility function for recursive directory cleanup. +void tst_qnetworkdiskcache::cleanRecursive(QString &path) +{ + QDirIterator it(path, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (it.hasNext()) { + QFile f(it.next()); + bool err = f.remove(); + Q_UNUSED(err); + } + + QDirIterator it2(path, QDir::AllDirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (it2.hasNext()) { + QString s(it2.next()); + QDir dir(s); + dir.rmdir(s); + } +} + +void tst_qnetworkdiskcache::cleanupCacheObject() +{ + delete cache; + cache = 0; +} + +void tst_qnetworkdiskcache::initCacheObject() +{ + + cache = new QNetworkDiskCache(); + +} +QTEST_MAIN(tst_qnetworkdiskcache) +#include "tst_qnetworkdiskcache.moc" diff --git a/tests/benchmarks/script/script.pro b/tests/benchmarks/script/script.pro index 80278d0..5da05e7 100644 --- a/tests/benchmarks/script/script.pro +++ b/tests/benchmarks/script/script.pro @@ -14,7 +14,6 @@ TRUSTED_BENCHMARKS += \ qscriptclass \ qscriptvalue \ qscriptengine \ - qscriptobject \ - context2d + qscriptqobject include(../trusted-benchmarks.pri) diff --git a/tests/manual/qlocale/calendar.cpp b/tests/manual/qlocale/calendar.cpp new file mode 100644 index 0000000..bd4756e --- /dev/null +++ b/tests/manual/qlocale/calendar.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "calendar.h" + +CalendarWidget::CalendarWidget() +{ + createPreviewGroupBox(); + createGeneralOptionsGroupBox(); + createDatesGroupBox(); + createTextFormatsGroupBox(); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(previewGroupBox, 0, 0); + layout->addWidget(generalOptionsGroupBox, 0, 1); + layout->addWidget(datesGroupBox, 1, 0); + layout->addWidget(textFormatsGroupBox, 1, 1); + layout->setSizeConstraint(QLayout::SetFixedSize); + setLayout(layout); + + previewLayout->setRowMinimumHeight(0, calendar->sizeHint().height()); + previewLayout->setColumnMinimumWidth(0, calendar->sizeHint().width()); + + setWindowTitle(tr("Calendar Widget")); +} + +void CalendarWidget::localeChanged(QLocale locale) +{ + calendar->setLocale(locale); + firstDayCombo->setCurrentIndex(locale.firstDayOfWeek()-1); + updateWeekendDays(); +} + +void CalendarWidget::firstDayChanged(int index) +{ + calendar->setFirstDayOfWeek(Qt::DayOfWeek( + firstDayCombo->itemData(index).toInt())); +} + +void CalendarWidget::selectionModeChanged(int index) +{ + calendar->setSelectionMode(QCalendarWidget::SelectionMode( + selectionModeCombo->itemData(index).toInt())); +} + +void CalendarWidget::horizontalHeaderChanged(int index) +{ + calendar->setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat( + horizontalHeaderCombo->itemData(index).toInt())); +} + +void CalendarWidget::verticalHeaderChanged(int index) +{ + calendar->setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat( + verticalHeaderCombo->itemData(index).toInt())); +} + +void CalendarWidget::selectedDateChanged() +{ + currentDateEdit->setDate(calendar->selectedDate()); +} + +void CalendarWidget::minimumDateChanged(const QDate &date) +{ + calendar->setMinimumDate(date); + maximumDateEdit->setDate(calendar->maximumDate()); +} + +void CalendarWidget::maximumDateChanged(const QDate &date) +{ + calendar->setMaximumDate(date); + minimumDateEdit->setDate(calendar->minimumDate()); +} + +bool CalendarWidget::isWeekendDay(Qt::DayOfWeek day) { + QList<Qt::DayOfWeek> week = calendar->locale().weekdays(); + return !week.contains(day); +} + +void CalendarWidget::updateWeekendDays() { + QTextCharFormat weekFormat, weekendFormat; + weekFormat.setForeground(qvariant_cast<QColor>( + weekdayColorCombo->itemData(weekdayColorCombo->currentIndex()))); + weekendFormat.setForeground(qvariant_cast<QColor>( + weekendColorCombo->itemData(weekendColorCombo->currentIndex()))); + + calendar->setWeekdayTextFormat(Qt::Monday, isWeekendDay(Qt::Monday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Tuesday, isWeekendDay(Qt::Tuesday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Wednesday, isWeekendDay(Qt::Wednesday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Thursday, isWeekendDay(Qt::Thursday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Friday, isWeekendDay(Qt::Friday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Saturday, isWeekendDay(Qt::Saturday) ? weekendFormat : weekFormat); + calendar->setWeekdayTextFormat(Qt::Sunday, isWeekendDay(Qt::Sunday) ? weekendFormat : weekFormat); +} + +void CalendarWidget::weekdayFormatChanged() +{ + updateWeekendDays(); +} + +void CalendarWidget::weekendFormatChanged() +{ + updateWeekendDays(); +} + +void CalendarWidget::reformatHeaders() +{ + QString text = headerTextFormatCombo->currentText(); + QTextCharFormat format; + + if (text == tr("Bold")) { + format.setFontWeight(QFont::Bold); + } else if (text == tr("Italic")) { + format.setFontItalic(true); + } else if (text == tr("Green")) { + format.setForeground(Qt::green); + } + calendar->setHeaderTextFormat(format); +} + +void CalendarWidget::reformatCalendarPage() +{ + if (firstFridayCheckBox->isChecked()) { + QDate firstFriday(calendar->yearShown(), calendar->monthShown(), 1); + while (firstFriday.dayOfWeek() != Qt::Friday) + firstFriday = firstFriday.addDays(1); + QTextCharFormat firstFridayFormat; + firstFridayFormat.setForeground(Qt::blue); + calendar->setDateTextFormat(firstFriday, firstFridayFormat); + } + + //May First in Red takes precedence + if (mayFirstCheckBox->isChecked()) { + const QDate mayFirst(calendar->yearShown(), 5, 1); + QTextCharFormat mayFirstFormat; + mayFirstFormat.setForeground(Qt::red); + calendar->setDateTextFormat(mayFirst, mayFirstFormat); + } +} + +void CalendarWidget::createPreviewGroupBox() +{ + previewGroupBox = new QGroupBox(tr("Preview")); + + calendar = new QCalendarWidget; + calendar->setMinimumDate(QDate(1900, 1, 1)); + calendar->setMaximumDate(QDate(3000, 1, 1)); + calendar->setGridVisible(true); + + connect(calendar, SIGNAL(currentPageChanged(int,int)), + this, SLOT(reformatCalendarPage())); + + previewLayout = new QGridLayout; + previewLayout->addWidget(calendar, 0, 0, Qt::AlignCenter); + previewGroupBox->setLayout(previewLayout); +} + +void CalendarWidget::createGeneralOptionsGroupBox() +{ + generalOptionsGroupBox = new QGroupBox(tr("General Options")); + + firstDayCombo = new QComboBox; + firstDayCombo->addItem(tr("Monday"), Qt::Monday); + firstDayCombo->addItem(tr("Tuesday"), Qt::Tuesday); + firstDayCombo->addItem(tr("Wednesday"), Qt::Wednesday); + firstDayCombo->addItem(tr("Thursday"), Qt::Thursday); + firstDayCombo->addItem(tr("Friday"), Qt::Friday); + firstDayCombo->addItem(tr("Saturday"), Qt::Saturday); + firstDayCombo->addItem(tr("Sunday"), Qt::Sunday); + + firstDayLabel = new QLabel(tr("Wee&k starts on:")); + firstDayLabel->setBuddy(firstDayCombo); + + selectionModeCombo = new QComboBox; + selectionModeCombo->addItem(tr("Single selection"), + QCalendarWidget::SingleSelection); + selectionModeCombo->addItem(tr("None"), QCalendarWidget::NoSelection); + + selectionModeLabel = new QLabel(tr("&Selection mode:")); + selectionModeLabel->setBuddy(selectionModeCombo); + + gridCheckBox = new QCheckBox(tr("&Grid")); + gridCheckBox->setChecked(calendar->isGridVisible()); + + navigationCheckBox = new QCheckBox(tr("&Navigation bar")); + navigationCheckBox->setChecked(true); + + horizontalHeaderCombo = new QComboBox; + horizontalHeaderCombo->addItem(tr("Single letter day names"), + QCalendarWidget::SingleLetterDayNames); + horizontalHeaderCombo->addItem(tr("Short day names"), + QCalendarWidget::ShortDayNames); + horizontalHeaderCombo->addItem(tr("None"), + QCalendarWidget::NoHorizontalHeader); + horizontalHeaderCombo->setCurrentIndex(1); + + horizontalHeaderLabel = new QLabel(tr("&Horizontal header:")); + horizontalHeaderLabel->setBuddy(horizontalHeaderCombo); + + verticalHeaderCombo = new QComboBox; + verticalHeaderCombo->addItem(tr("ISO week numbers"), + QCalendarWidget::ISOWeekNumbers); + verticalHeaderCombo->addItem(tr("None"), QCalendarWidget::NoVerticalHeader); + + verticalHeaderLabel = new QLabel(tr("&Vertical header:")); + verticalHeaderLabel->setBuddy(verticalHeaderCombo); + + connect(firstDayCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(firstDayChanged(int))); + connect(selectionModeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(selectionModeChanged(int))); + connect(gridCheckBox, SIGNAL(toggled(bool)), + calendar, SLOT(setGridVisible(bool))); + connect(navigationCheckBox, SIGNAL(toggled(bool)), + calendar, SLOT(setNavigationBarVisible(bool))); + connect(horizontalHeaderCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(horizontalHeaderChanged(int))); + connect(verticalHeaderCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(verticalHeaderChanged(int))); + + QHBoxLayout *checkBoxLayout = new QHBoxLayout; + checkBoxLayout->addWidget(gridCheckBox); + checkBoxLayout->addStretch(); + checkBoxLayout->addWidget(navigationCheckBox); + + QGridLayout *outerLayout = new QGridLayout; + outerLayout->addWidget(firstDayLabel, 0, 0); + outerLayout->addWidget(firstDayCombo, 0, 1); + outerLayout->addWidget(selectionModeLabel, 1, 0); + outerLayout->addWidget(selectionModeCombo, 1, 1); + outerLayout->addLayout(checkBoxLayout, 2, 0, 1, 2); + outerLayout->addWidget(horizontalHeaderLabel, 3, 0); + outerLayout->addWidget(horizontalHeaderCombo, 3, 1); + outerLayout->addWidget(verticalHeaderLabel, 4, 0); + outerLayout->addWidget(verticalHeaderCombo, 4, 1); + generalOptionsGroupBox->setLayout(outerLayout); + + firstDayChanged(firstDayCombo->currentIndex()); + selectionModeChanged(selectionModeCombo->currentIndex()); + horizontalHeaderChanged(horizontalHeaderCombo->currentIndex()); + verticalHeaderChanged(verticalHeaderCombo->currentIndex()); +} + +void CalendarWidget::createDatesGroupBox() +{ + datesGroupBox = new QGroupBox(tr("Dates")); + + minimumDateEdit = new QDateEdit; + minimumDateEdit->setDisplayFormat("MMM d yyyy"); + minimumDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + minimumDateEdit->setDate(calendar->minimumDate()); + + minimumDateLabel = new QLabel(tr("&Minimum Date:")); + minimumDateLabel->setBuddy(minimumDateEdit); + + currentDateEdit = new QDateEdit; + currentDateEdit->setDisplayFormat("MMM d yyyy"); + currentDateEdit->setDate(calendar->selectedDate()); + currentDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + + currentDateLabel = new QLabel(tr("&Current Date:")); + currentDateLabel->setBuddy(currentDateEdit); + + maximumDateEdit = new QDateEdit; + maximumDateEdit->setDisplayFormat("MMM d yyyy"); + maximumDateEdit->setDateRange(calendar->minimumDate(), + calendar->maximumDate()); + maximumDateEdit->setDate(calendar->maximumDate()); + + maximumDateLabel = new QLabel(tr("Ma&ximum Date:")); + maximumDateLabel->setBuddy(maximumDateEdit); + + connect(currentDateEdit, SIGNAL(dateChanged(QDate)), + calendar, SLOT(setSelectedDate(QDate))); + connect(calendar, SIGNAL(selectionChanged()), + this, SLOT(selectedDateChanged())); + connect(minimumDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(minimumDateChanged(QDate))); + connect(maximumDateEdit, SIGNAL(dateChanged(QDate)), + this, SLOT(maximumDateChanged(QDate))); + + QGridLayout *dateBoxLayout = new QGridLayout; + dateBoxLayout->addWidget(currentDateLabel, 1, 0); + dateBoxLayout->addWidget(currentDateEdit, 1, 1); + dateBoxLayout->addWidget(minimumDateLabel, 0, 0); + dateBoxLayout->addWidget(minimumDateEdit, 0, 1); + dateBoxLayout->addWidget(maximumDateLabel, 2, 0); + dateBoxLayout->addWidget(maximumDateEdit, 2, 1); + dateBoxLayout->setRowStretch(3, 1); + + datesGroupBox->setLayout(dateBoxLayout); +} + +void CalendarWidget::createTextFormatsGroupBox() +{ + textFormatsGroupBox = new QGroupBox(tr("Text Formats")); + + weekdayColorCombo = createColorComboBox(); + weekdayColorCombo->setCurrentIndex( + weekdayColorCombo->findText(tr("Black"))); + + weekdayColorLabel = new QLabel(tr("&Weekday color:")); + weekdayColorLabel->setBuddy(weekdayColorCombo); + + weekendColorCombo = createColorComboBox(); + weekendColorCombo->setCurrentIndex( + weekendColorCombo->findText(tr("Red"))); + + weekendColorLabel = new QLabel(tr("Week&end color:")); + weekendColorLabel->setBuddy(weekendColorCombo); + + headerTextFormatCombo = new QComboBox; + headerTextFormatCombo->addItem(tr("Bold")); + headerTextFormatCombo->addItem(tr("Italic")); + headerTextFormatCombo->addItem(tr("Plain")); + + headerTextFormatLabel = new QLabel(tr("&Header text:")); + headerTextFormatLabel->setBuddy(headerTextFormatCombo); + + firstFridayCheckBox = new QCheckBox(tr("&First Friday in blue")); + + mayFirstCheckBox = new QCheckBox(tr("May &1 in red")); + + connect(weekdayColorCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(weekdayFormatChanged())); + connect(weekendColorCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(weekendFormatChanged())); + connect(headerTextFormatCombo, SIGNAL(currentIndexChanged(QString)), + this, SLOT(reformatHeaders())); + connect(firstFridayCheckBox, SIGNAL(toggled(bool)), + this, SLOT(reformatCalendarPage())); + connect(mayFirstCheckBox, SIGNAL(toggled(bool)), + this, SLOT(reformatCalendarPage())); + + QHBoxLayout *checkBoxLayout = new QHBoxLayout; + checkBoxLayout->addWidget(firstFridayCheckBox); + checkBoxLayout->addStretch(); + checkBoxLayout->addWidget(mayFirstCheckBox); + + QGridLayout *outerLayout = new QGridLayout; + outerLayout->addWidget(weekdayColorLabel, 0, 0); + outerLayout->addWidget(weekdayColorCombo, 0, 1); + outerLayout->addWidget(weekendColorLabel, 1, 0); + outerLayout->addWidget(weekendColorCombo, 1, 1); + outerLayout->addWidget(headerTextFormatLabel, 2, 0); + outerLayout->addWidget(headerTextFormatCombo, 2, 1); + outerLayout->addLayout(checkBoxLayout, 3, 0, 1, 2); + textFormatsGroupBox->setLayout(outerLayout); + + weekdayFormatChanged(); + weekendFormatChanged(); + reformatHeaders(); + reformatCalendarPage(); +} + +QComboBox *CalendarWidget::createColorComboBox() +{ + QComboBox *comboBox = new QComboBox; + comboBox->addItem(tr("Red"), Qt::red); + comboBox->addItem(tr("Blue"), Qt::blue); + comboBox->addItem(tr("Black"), Qt::black); + comboBox->addItem(tr("Magenta"), Qt::magenta); + return comboBox; +} diff --git a/tests/manual/qlocale/calendar.h b/tests/manual/qlocale/calendar.h new file mode 100644 index 0000000..b5bb3c9 --- /dev/null +++ b/tests/manual/qlocale/calendar.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CALENDAR_H +#define CALENDAR_H + +#include <QtGui> + +class CalendarWidget : public QWidget +{ + Q_OBJECT + +public: + CalendarWidget(); + +private slots: + void localeChanged(QLocale locale); + void firstDayChanged(int index); + void selectionModeChanged(int index); + void horizontalHeaderChanged(int index); + void verticalHeaderChanged(int index); + void selectedDateChanged(); + void minimumDateChanged(const QDate &date); + void maximumDateChanged(const QDate &date); + void updateWeekendDays(); + void weekdayFormatChanged(); + void weekendFormatChanged(); + void reformatHeaders(); + void reformatCalendarPage(); + +private: + bool isWeekendDay(Qt::DayOfWeek); + void createPreviewGroupBox(); + void createGeneralOptionsGroupBox(); + void createDatesGroupBox(); + void createTextFormatsGroupBox(); + QComboBox *createColorComboBox(); + + QGroupBox *previewGroupBox; + QGridLayout *previewLayout; + QCalendarWidget *calendar; + + QGroupBox *generalOptionsGroupBox; + QLabel *localeLabel; + QLabel *firstDayLabel; + + QLabel *selectionModeLabel; + QLabel *horizontalHeaderLabel; + QLabel *verticalHeaderLabel; + QComboBox *localeCombo; + QComboBox *firstDayCombo; + QComboBox *selectionModeCombo; + QCheckBox *gridCheckBox; + QCheckBox *navigationCheckBox; + QComboBox *horizontalHeaderCombo; + QComboBox *verticalHeaderCombo; + + QGroupBox *datesGroupBox; + QLabel *currentDateLabel; + QLabel *minimumDateLabel; + QLabel *maximumDateLabel; + QDateEdit *currentDateEdit; + QDateEdit *minimumDateEdit; + QDateEdit *maximumDateEdit; + + QGroupBox *textFormatsGroupBox; + QLabel *weekdayColorLabel; + QLabel *weekendColorLabel; + QLabel *headerTextFormatLabel; + QComboBox *weekdayColorCombo; + QComboBox *weekendColorCombo; + QComboBox *headerTextFormatCombo; + + QCheckBox *firstFridayCheckBox; + QCheckBox *mayFirstCheckBox; +}; + +#endif diff --git a/tests/manual/qlocale/currency.cpp b/tests/manual/qlocale/currency.cpp new file mode 100644 index 0000000..4ef157c --- /dev/null +++ b/tests/manual/qlocale/currency.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "currency.h" + +CurrencyWidget::CurrencyWidget() +{ + QGridLayout *l = new QGridLayout; + + currencySymbolLabel = new QLabel("Symbol:"); + currencySymbol = new QLineEdit; + currencyISOLabel = new QLabel("ISO Code:"); + currencyISO = new QLineEdit; + currencyNameLabel = new QLabel("Display name:"); + currencyName = new QLineEdit; + currencyFormattingLabel = new QLabel("Currency formatting:"); + currencyFormattingValue = new QLineEdit(QString::number(1234.56, 'f', 2)); + currencyFormattingSymbolLabel = new QLabel("currency:"); + currencyFormattingSymbol = new QLineEdit; + currencyFormatting = new QLineEdit; + + currencyFormattingValue->setFixedWidth(150); + currencyFormattingSymbol->setFixedWidth(50); + + l->addWidget(currencySymbolLabel, 0, 0); + l->addWidget(currencySymbol, 0, 1, 1, 4); + l->addWidget(currencyISOLabel, 1, 0); + l->addWidget(currencyISO, 1, 1, 1, 4); + l->addWidget(currencyNameLabel, 2, 0); + l->addWidget(currencyName, 2, 1, 1, 4); + l->addWidget(currencyFormattingLabel, 3, 0); + l->addWidget(currencyFormattingValue, 3, 1); + l->addWidget(currencyFormattingSymbolLabel, 3, 2); + l->addWidget(currencyFormattingSymbol, 3, 3); + l->addWidget(currencyFormatting, 3, 4); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); + + connect(currencyFormattingSymbol, SIGNAL(textChanged(QString)), + this, SLOT(updateCurrencyFormatting())); + connect(currencyFormattingValue, SIGNAL(textChanged(QString)), + this, SLOT(updateCurrencyFormatting())); +} + +void CurrencyWidget::updateCurrencyFormatting() +{ + QString result; + bool ok; + QString symbol = currencyFormattingSymbol->text(); + QString value = currencyFormattingValue->text(); + int i = value.toInt(&ok); + if (ok) { + result = locale().toCurrencyString(i, symbol); + } else { + double d = value.toDouble(&ok); + if (ok) + result = locale().toCurrencyString(d, symbol); + } + currencyFormatting->setText(result); +} + +void CurrencyWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + currencySymbol->setText(locale.currencySymbol()); + currencyISO->setText(locale.currencySymbol(QLocale::CurrencyIsoCode)); + currencyName->setText(locale.currencySymbol(QLocale::CurrencyDisplayName)); + updateCurrencyFormatting(); +} + diff --git a/tests/manual/qlocale/currency.h b/tests/manual/qlocale/currency.h new file mode 100644 index 0000000..3a12553 --- /dev/null +++ b/tests/manual/qlocale/currency.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CURRENCY_H +#define CURRENCY_H + +#include <QtGui> + +class CurrencyWidget : public QWidget +{ + Q_OBJECT +public: + CurrencyWidget(); + +private: + QLabel *currencySymbolLabel; + QLineEdit *currencySymbol; + QLabel *currencyISOLabel; + QLineEdit *currencyISO; + QLabel *currencyNameLabel; + QLineEdit *currencyName; + QLabel *currencyFormattingLabel; + QLineEdit *currencyFormattingValue; + QLabel *currencyFormattingSymbolLabel; + QLineEdit *currencyFormattingSymbol; + QLineEdit *currencyFormatting; + +private slots: + void localeChanged(QLocale locale); + void updateCurrencyFormatting(); +}; + +#endif diff --git a/tests/manual/qlocale/dateformats.cpp b/tests/manual/qlocale/dateformats.cpp new file mode 100644 index 0000000..25b3e7a --- /dev/null +++ b/tests/manual/qlocale/dateformats.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dateformats.h" + +DateFormatsWidget::DateFormatsWidget() +{ + scrollArea = new QScrollArea; + scrollAreaWidget = new QWidget; + scrollArea->setWidget(scrollAreaWidget); + scrollArea->setWidgetResizable(true); + layout = new QGridLayout(scrollAreaWidget); + QVBoxLayout *l = new QVBoxLayout(this); + l->addWidget(scrollArea); + + shortDateFormat = addItem("Date format (short):"); + longDateFormat = addItem("Date format (long):"); + shortTimeFormat = addItem("Time format (short):"); + longTimeFormat = addItem("Time format (long):"); + shortDateTimeFormat = addItem("DateTime format (short):"); + longDateTimeFormat = addItem("DateTime format (long):"); + amText = addItem("Before noon:"); + pmText = addItem("After noon:"); + firstDayOfWeek = addItem("First day of week:"); + + monthNamesShort = new QComboBox; + monthNamesLong = new QComboBox; + standaloneMonthNamesShort = new QComboBox; + standaloneMonthNamesLong = new QComboBox; + dayNamesShort = new QComboBox; + dayNamesLong = new QComboBox; + standaloneDayNamesShort = new QComboBox; + standaloneDayNamesLong = new QComboBox; + + int row = layout->rowCount(); + layout->addWidget(new QLabel("Month names [short/long]:"), row, 0); + layout->addWidget(monthNamesShort, row, 1); + layout->addWidget(monthNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Standalone month names [short/long]:"), row, 0); + layout->addWidget(standaloneMonthNamesShort, row, 1); + layout->addWidget(standaloneMonthNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Day names [short/long]:"), row, 0); + layout->addWidget(dayNamesShort, row, 1); + layout->addWidget(dayNamesLong, row, 2); + row = layout->rowCount(); + layout->addWidget(new QLabel("Standalone day names [short/long]:"), row, 0); + layout->addWidget(standaloneDayNamesShort, row, 1); + layout->addWidget(standaloneDayNamesLong, row, 2); +} + +QString toString(Qt::DayOfWeek dow) +{ + static const char *names[] = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + return QString::fromLatin1(names[dow-1]); +} + +void DateFormatsWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + QDateTime now = QDateTime::currentDateTime(); + shortDateFormat->setText(locale.toString(now.date(), QLocale::ShortFormat)); + shortDateFormat->setToolTip(locale.dateFormat(QLocale::ShortFormat)); + longDateFormat->setText(locale.toString(now.date(), QLocale::LongFormat)); + longDateFormat->setToolTip(locale.dateFormat(QLocale::LongFormat)); + shortTimeFormat->setText(locale.toString(now.time(), QLocale::ShortFormat)); + shortTimeFormat->setToolTip(locale.timeFormat(QLocale::ShortFormat)); + longTimeFormat->setText(locale.toString(now.time(), QLocale::LongFormat)); + longTimeFormat->setToolTip(locale.timeFormat(QLocale::LongFormat)); + shortDateTimeFormat->setText(locale.toString(now, QLocale::ShortFormat)); + shortDateTimeFormat->setToolTip(locale.dateTimeFormat(QLocale::ShortFormat)); + longDateTimeFormat->setText(locale.toString(now, QLocale::LongFormat)); + longDateTimeFormat->setToolTip(locale.dateTimeFormat(QLocale::LongFormat)); + amText->setText(locale.amText()); + pmText->setText(locale.pmText()); + firstDayOfWeek->setText(toString(locale.firstDayOfWeek())); + + int mns = monthNamesShort->currentIndex(); + int mnl = monthNamesLong->currentIndex(); + int smns = standaloneMonthNamesShort->currentIndex(); + int smnl = standaloneMonthNamesLong->currentIndex(); + int dnl = dayNamesLong->currentIndex(); + int dns = dayNamesShort->currentIndex(); + int sdnl = standaloneDayNamesLong->currentIndex(); + int sdns = standaloneDayNamesShort->currentIndex(); + + monthNamesShort->clear(); + monthNamesLong->clear(); + standaloneMonthNamesShort->clear(); + standaloneMonthNamesLong->clear(); + dayNamesLong->clear(); + dayNamesShort->clear(); + standaloneDayNamesLong->clear(); + standaloneDayNamesShort->clear(); + + for (int i = 1; i <= 12; ++i) + monthNamesShort->addItem(locale.monthName(i, QLocale::ShortFormat)); + monthNamesShort->setCurrentIndex(mns >= 0 ? mns : 0); + for (int i = 1; i <= 12; ++i) + monthNamesLong->addItem(locale.monthName(i, QLocale::LongFormat)); + monthNamesLong->setCurrentIndex(mnl >= 0 ? mnl : 0); + + for (int i = 1; i <= 12; ++i) + standaloneMonthNamesShort->addItem(locale.standaloneMonthName(i, QLocale::ShortFormat)); + standaloneMonthNamesShort->setCurrentIndex(smns >= 0 ? smns : 0); + for (int i = 1; i <= 12; ++i) + standaloneMonthNamesLong->addItem(locale.standaloneMonthName(i, QLocale::LongFormat)); + standaloneMonthNamesLong->setCurrentIndex(smnl >= 0 ? smnl : 0); + + for (int i = 1; i <= 7; ++i) + dayNamesLong->addItem(locale.dayName(i, QLocale::LongFormat)); + dayNamesLong->setCurrentIndex(dnl >= 0 ? dnl : 0); + for (int i = 1; i <= 7; ++i) + dayNamesShort->addItem(locale.dayName(i, QLocale::ShortFormat)); + dayNamesShort->setCurrentIndex(dns >= 0 ? dns : 0); + + for (int i = 1; i <= 7; ++i) + standaloneDayNamesLong->addItem(locale.standaloneDayName(i, QLocale::LongFormat)); + standaloneDayNamesLong->setCurrentIndex(sdnl >= 0 ? sdnl : 0); + for (int i = 1; i <= 7; ++i) + standaloneDayNamesShort->addItem(locale.standaloneDayName(i, QLocale::ShortFormat)); + standaloneDayNamesShort->setCurrentIndex(sdns >= 0 ? sdns : 0); +} + +void DateFormatsWidget::addItem(const QString &label, QWidget *w) +{ + QLabel *lbl = new QLabel(label); + int row = layout->rowCount(); + layout->addWidget(lbl, row, 0); + layout->addWidget(w, row, 1, 1, 2); +} + +QLineEdit *DateFormatsWidget::addItem(const QString &label) +{ + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + addItem(label, le); + return le; +} diff --git a/tests/manual/qlocale/dateformats.h b/tests/manual/qlocale/dateformats.h new file mode 100644 index 0000000..f05ad2a --- /dev/null +++ b/tests/manual/qlocale/dateformats.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DATEFORMATS_H +#define DATEFORMATS_H + +#include <QtGui> + +class DateFormatsWidget : public QWidget +{ + Q_OBJECT +public: + DateFormatsWidget(); + +private: + void addItem(const QString &label, QWidget *); + QLineEdit *addItem(const QString &label); + + QScrollArea *scrollArea; + QWidget *scrollAreaWidget; + QGridLayout *layout; + + QLineEdit *shortDateFormat; + QLineEdit *longDateFormat; + QLineEdit *shortTimeFormat; + QLineEdit *longTimeFormat; + QLineEdit *shortDateTimeFormat; + QLineEdit *longDateTimeFormat; + QLineEdit *amText; + QLineEdit *pmText; + QLineEdit *firstDayOfWeek; + QComboBox *monthNamesShort, *monthNamesLong; + QComboBox *standaloneMonthNamesShort, *standaloneMonthNamesLong; + QComboBox *dayNamesShort, *dayNamesLong; + QComboBox *standaloneDayNamesShort, *standaloneDayNamesLong; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/info.cpp b/tests/manual/qlocale/info.cpp new file mode 100644 index 0000000..a4f6adf --- /dev/null +++ b/tests/manual/qlocale/info.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "info.h" + +InfoWidget::InfoWidget() +{ + scrollArea = new QScrollArea; + scrollAreaWidget = new QWidget; + scrollArea->setWidget(scrollAreaWidget); + scrollArea->setWidgetResizable(true); + layout = new QGridLayout(); + QVBoxLayout *v = new QVBoxLayout(scrollAreaWidget); + v->addLayout(layout); + v->addStretch(); + + QVBoxLayout *l = new QVBoxLayout(this); + l->addWidget(scrollArea); + + name = addItem("Name:"); + bcp47Name = addItem("Bcp47 name:"); + languageName = addItem("Language name:"); + nativeLanguageName = addItem("Native language name:"); + scriptName = addItem("Script name:"); + countryName = addItem("Country name:"); + nativeCountryName = addItem("Native country name:"); +} + +void InfoWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + name->setText(locale.name()); + bcp47Name->setText(locale.bcp47Name()); + languageName->setText(QLocale::languageToString(locale.language())); + nativeLanguageName->setText(locale.nativeLanguageName()); + scriptName->setText(QLocale::scriptToString(locale.script())); + countryName->setText(QLocale::countryToString(locale.country())); + nativeCountryName->setText(locale.nativeCountryName()); +} + +void InfoWidget::addItem(const QString &label, QWidget *w) +{ + QLabel *lbl = new QLabel(label); + int row = layout->rowCount(); + layout->addWidget(lbl, row, 0); + layout->addWidget(w, row, 1, 1, 2); +} + +QLineEdit *InfoWidget::addItem(const QString &label) +{ + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + addItem(label, le); + return le; +} diff --git a/tests/manual/qlocale/info.h b/tests/manual/qlocale/info.h new file mode 100644 index 0000000..b23ecf5 --- /dev/null +++ b/tests/manual/qlocale/info.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INFO_H +#define INFO_H + +#include <QtGui> + +class InfoWidget : public QWidget +{ + Q_OBJECT +public: + InfoWidget(); + +private: + void addItem(const QString &label, QWidget *); + QLineEdit *addItem(const QString &label); + + QScrollArea *scrollArea; + QWidget *scrollAreaWidget; + QGridLayout *layout; + + QLineEdit *name; + QLineEdit *bcp47Name; + QLineEdit *languageName; + QLineEdit *nativeLanguageName; + QLineEdit *scriptName; + QLineEdit *countryName; + QLineEdit *nativeCountryName; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/languages.cpp b/tests/manual/qlocale/languages.cpp new file mode 100644 index 0000000..18d72d7 --- /dev/null +++ b/tests/manual/qlocale/languages.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "languages.h" + +LanguagesWidget::LanguagesWidget() +{ + QVBoxLayout *l = new QVBoxLayout(this); + + languagesLabel = new QLabel("Preferred languages:"); + languagesList = new QListWidget; + + l->addWidget(languagesLabel); + l->addWidget(languagesList); + + localeChanged(QLocale()); +} + +void LanguagesWidget::localeChanged(QLocale locale) +{ + languagesList->clear(); + foreach (const QString &lang, locale.uiLanguages()) { + QListWidgetItem *item = new QListWidgetItem(lang, languagesList); + QLocale l(lang); + if (l.language() != QLocale::C) { + QString language = QLocale::languageToString(l.language()); + QString country = QLocale::countryToString(l.country()); + QString tooltip = QString(QLatin1String("%1: %2/%3")).arg(l.name(), language, country); + item->setToolTip(tooltip); + } + } +} + + diff --git a/tests/manual/qlocale/languages.h b/tests/manual/qlocale/languages.h new file mode 100644 index 0000000..18e503f --- /dev/null +++ b/tests/manual/qlocale/languages.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LANGUAGES_H +#define LANGUAGES_H + +#include <QtGui> + +class LanguagesWidget : public QWidget +{ + Q_OBJECT +public: + LanguagesWidget(); + +private: + QLocale currentLocale; + + QLabel *languagesLabel; + QListWidget *languagesList; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/main.cpp b/tests/manual/qlocale/main.cpp new file mode 100644 index 0000000..c85bd19 --- /dev/null +++ b/tests/manual/qlocale/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "window.h" + +int main(int argv, char *args[]) +{ + QApplication app(argv, args); + Window window; +#if !defined(Q_OS_SYMBIAN) + window.show(); +#else + window.showFullScreen(); +#endif + return app.exec(); +} diff --git a/tests/manual/qlocale/miscellaneous.cpp b/tests/manual/qlocale/miscellaneous.cpp new file mode 100644 index 0000000..89c80dc --- /dev/null +++ b/tests/manual/qlocale/miscellaneous.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "miscellaneous.h" + +MiscWidget::MiscWidget() +{ + QGridLayout *l = new QGridLayout; + + createLineEdit("Text to quote:", &textToQuoteLabel, &textToQuote); + createLineEdit("Standard quotes:", &standardQuotedTextLabel, &standardQuotedText); + createLineEdit("Alternate quotes:", &alternateQuotedTextLabel, &alternateQuotedText); + textToQuote->setText("some text"); + createLineEdit("Text direction:", &textDirectionLabel, &textDirection); + createLineEdit("List to separated string:", &listToSeparatedStringLabel, &listToSeparatedStringText); + + l->addWidget(textToQuoteLabel, 0, 0); + l->addWidget(textToQuote, 0, 1); + l->addWidget(standardQuotedTextLabel, 0, 2); + l->addWidget(standardQuotedText, 0, 3); + l->addWidget(alternateQuotedTextLabel, 1, 2); + l->addWidget(alternateQuotedText, 1, 3); + l->addWidget(textDirectionLabel, 2, 0); + l->addWidget(textDirection, 2, 1, 1, 3); + l->addWidget(listToSeparatedStringLabel, 3, 0); + l->addWidget(listToSeparatedStringText, 3, 1, 1, 3); + + connect(textToQuote, SIGNAL(textChanged(QString)), this, SLOT(updateQuotedText(QString))); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); +} + +void MiscWidget::updateQuotedText(QString str) +{ + standardQuotedText->setText(locale().quoteString(str)); + alternateQuotedText->setText(locale().quoteString(str, QLocale::AlternateQuotation)); +} + +void MiscWidget::updateListToSeparatedStringText() +{ + QStringList test; + test << "aaa" << "bbb" << "ccc" << "ddd"; + listToSeparatedStringText->setText(locale().createSeparatedList(test)); +} + +void MiscWidget::localeChanged(QLocale locale) +{ + setLocale(locale); + updateQuotedText(textToQuote->text()); + updateListToSeparatedStringText(); + textDirection->setText(locale.textDirection() == Qt::LeftToRight ? "Left To Right" : "Right To Left"); +} + +void MiscWidget::createLineEdit(const QString &label, QLabel **labelWidget, QLineEdit **lineEditWidget) +{ + QLabel *lbl = new QLabel(label); + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + lbl->setBuddy(le); + if (labelWidget) + *labelWidget = lbl; + if (lineEditWidget) + *lineEditWidget = le; +} diff --git a/tests/manual/qlocale/miscellaneous.h b/tests/manual/qlocale/miscellaneous.h new file mode 100644 index 0000000..3b635b8 --- /dev/null +++ b/tests/manual/qlocale/miscellaneous.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MISCELLANEOUS_H +#define MISCELLANEOUS_H + +#include <QtGui> + +class MiscWidget : public QWidget +{ + Q_OBJECT +public: + MiscWidget(); + +private: + void createLineEdit(const QString &label, QLabel **labelWidget = 0, QLineEdit **lineEditWidget = 0); + + QLabel *textToQuoteLabel; + QLabel *standardQuotedTextLabel; + QLabel *alternateQuotedTextLabel; + QLabel *textDirectionLabel; + QLabel *listToSeparatedStringLabel; + QLineEdit *textToQuote; + QLineEdit *standardQuotedText; + QLineEdit *alternateQuotedText; + QLineEdit *textDirection; + QLineEdit *listToSeparatedStringText; + +private slots: + void localeChanged(QLocale locale); + void updateQuotedText(QString str); + void updateListToSeparatedStringText(); +}; + +#endif // MISCELLANEOUS_H diff --git a/tests/manual/qlocale/numberformats.cpp b/tests/manual/qlocale/numberformats.cpp new file mode 100644 index 0000000..7b5fce4 --- /dev/null +++ b/tests/manual/qlocale/numberformats.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "numberformats.h" + +NumberFormatsWidget::NumberFormatsWidget() +{ + QGridLayout *l = new QGridLayout; + + QLabel *numbersLabel = new QLabel("Numbers:"); + number1 = createLineEdit(); + number2 = createLineEdit(); + number3 = createLineEdit(); + + measurementLabel = new QLabel("Measurement units:"); + measurementSystem = createLineEdit(); + + l->addWidget(numbersLabel, 0, 0); + l->addWidget(number1, 0, 1); + l->addWidget(number2, 0, 2); + l->addWidget(number3, 0, 3); + + l->addWidget(measurementLabel, 1, 0); + l->addWidget(measurementSystem, 1, 1, 1, 3); + + QVBoxLayout *v = new QVBoxLayout(this); + v->addLayout(l); + v->addStretch(); +} + +void NumberFormatsWidget::localeChanged(QLocale locale) +{ + number1->setText(locale.toString(-123456)); + number2->setText(locale.toString(1234.56, 'f', 2)); + number3->setText(locale.toString(1234.56, 'e', 4)); + + measurementSystem->setText( + locale.measurementSystem() == QLocale::ImperialSystem ? "US" : "Metric"); +} + +QLineEdit *NumberFormatsWidget::createLineEdit() +{ + QLineEdit *le = new QLineEdit; + le->setReadOnly(true); + return le; +} diff --git a/tests/manual/qlocale/numberformats.h b/tests/manual/qlocale/numberformats.h new file mode 100644 index 0000000..4a3ab36 --- /dev/null +++ b/tests/manual/qlocale/numberformats.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NUMBERFORMATS_H +#define NUMBERFORMATS_H + +#include <QtGui> + +class NumberFormatsWidget : public QWidget +{ + Q_OBJECT +public: + NumberFormatsWidget(); + +private: + QLineEdit *createLineEdit(); + + QLineEdit *number1, *number2, *number3; + QLabel *measurementLabel; + QLineEdit *measurementSystem; + +private slots: + void localeChanged(QLocale locale); +}; + +#endif diff --git a/tests/manual/qlocale/qlocale.pro b/tests/manual/qlocale/qlocale.pro new file mode 100644 index 0000000..e9f17f4 --- /dev/null +++ b/tests/manual/qlocale/qlocale.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += currency.h calendar.h dateformats.h numberformats.h languages.h window.h miscellaneous.h info.h +SOURCES += currency.cpp main.cpp calendar.cpp dateformats.cpp numberformats.cpp languages.cpp window.cpp miscellaneous.cpp info.cpp diff --git a/tests/manual/qlocale/window.cpp b/tests/manual/qlocale/window.cpp new file mode 100644 index 0000000..775023e --- /dev/null +++ b/tests/manual/qlocale/window.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" + +Window::Window() +{ + localeCombo = new QComboBox; + + localeCombo->addItem("System", QLocale::system()); + + QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); + foreach (const QLocale &locale, locales) { + QString label = QLocale::languageToString(locale.language()); + label += QLatin1Char('/'); + if (locale.script() != QLocale::AnyScript) { + label += QLocale::scriptToString(locale.script()); + label += QLatin1Char('/'); + } + label += QLocale::countryToString(locale.country()); + localeCombo->addItem(label, locale); + } + + connect(localeCombo, SIGNAL(currentIndexChanged(int)), + this, SLOT(localeChanged(int))); + + tabWidget = new QTabWidget; + info = new InfoWidget; + connect(this, SIGNAL(localeChanged(QLocale)), info, SLOT(localeChanged(QLocale))); + calendar = new CalendarWidget; + connect(this, SIGNAL(localeChanged(QLocale)), calendar, SLOT(localeChanged(QLocale))); + currency = new CurrencyWidget; + connect(this, SIGNAL(localeChanged(QLocale)), currency, SLOT(localeChanged(QLocale))); + languages = new LanguagesWidget; + connect(this, SIGNAL(localeChanged(QLocale)), languages, SLOT(localeChanged(QLocale))); + dateFormats = new DateFormatsWidget; + connect(this, SIGNAL(localeChanged(QLocale)), dateFormats, SLOT(localeChanged(QLocale))); + numberFormats = new NumberFormatsWidget; + connect(this, SIGNAL(localeChanged(QLocale)), numberFormats, SLOT(localeChanged(QLocale))); + miscellaneous = new MiscWidget; + connect(this, SIGNAL(localeChanged(QLocale)), miscellaneous, SLOT(localeChanged(QLocale))); + + localeName = new QLabel("Locale: foo_BAR"); + + QWidget *w = new QWidget; + QHBoxLayout *headerLayout = new QHBoxLayout(w); + headerLayout->addWidget(localeCombo); + headerLayout->addWidget(localeName); + + QWidget *central = new QWidget; + QVBoxLayout *l = new QVBoxLayout(central); + l->addWidget(w); + l->addWidget(tabWidget); + + tabWidget->addTab(info, "Info"); + tabWidget->addTab(calendar, "Calendar"); + tabWidget->addTab(currency, "Currency"); + tabWidget->addTab(languages, "Languages"); + tabWidget->addTab(dateFormats, "Date Formats"); + tabWidget->addTab(numberFormats, "Number Formats"); + tabWidget->addTab(miscellaneous, "Text"); + + localeCombo->setCurrentIndex(0); + systemLocaleChanged(); + + setCentralWidget(central); +} + +void Window::systemLocaleChanged() +{ + QLocale l = QLocale::system(); + QString lang = QLocale::languageToString(l.language()); + QString script = QLocale::scriptToString(l.script()); + QString country = QLocale::countryToString(l.country()); + if (l.script() != QLocale::AnyScript) + localeCombo->setItemText(0, QString("System: %1-%2-%3").arg(lang, script, country)); + else + localeCombo->setItemText(0, QString("System: %1-%2").arg(lang, country)); + emit localeChanged(0); +} + +void Window::localeChanged(int idx) +{ + QLocale locale = localeCombo->itemData(idx).toLocale(); + localeName->setText(QString("Locale: %1 (%2)").arg(locale.bcp47Name(), locale.name())); + emit localeChanged(locale); +} + +bool Window::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::LocaleChange: { + if (localeCombo->currentIndex() == 0) + systemLocaleChanged(); + return true; + } + default: + break; + } + return QMainWindow::event(event); +} diff --git a/tests/manual/qlocale/window.h b/tests/manual/qlocale/window.h new file mode 100644 index 0000000..aee728f --- /dev/null +++ b/tests/manual/qlocale/window.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include <QtGui> + +#include "calendar.h" +#include "currency.h" +#include "languages.h" +#include "dateformats.h" +#include "numberformats.h" +#include "miscellaneous.h" +#include "info.h" + +class Window : public QMainWindow +{ + Q_OBJECT +public: + Window(); + + QLabel *localeName; + QComboBox *localeCombo; + QTabWidget *tabWidget; + CalendarWidget *calendar; + CurrencyWidget *currency; + LanguagesWidget *languages; + DateFormatsWidget *dateFormats; + NumberFormatsWidget *numberFormats; + MiscWidget *miscellaneous; + InfoWidget *info; + +private: + bool event(QEvent *); + void systemLocaleChanged(); + +signals: + void localeChanged(QLocale); + +private slots: + void localeChanged(int); +}; + +#endif diff --git a/tests/manual/socketengine/main.cpp b/tests/manual/socketengine/main.cpp new file mode 100644 index 0000000..2f017a0 --- /dev/null +++ b/tests/manual/socketengine/main.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 <QDebug> +#include <qtest.h> +#include <QtTest/QtTest> +#include <QtNetwork/qnetworkreply.h> +#include <QtNetwork/qnetworkrequest.h> +#include <QtNetwork/qnetworkaccessmanager.h> +#include "../../auto/network-settings.h" +#include <QtNetwork> +#include <QDebug> +#include <private/qabstractsocketengine_p.h> +#include <cstdio> +#include <strings.h> +#include <QNetworkConfigurationManager> +#include <QNetworkConfiguration> +#include <QNetworkSession> +#include <QCoreApplication> + +const int bufsize = 16*1024; +char buf[bufsize]; + +int main(int argc, char**argv) +{ + QCoreApplication app(argc, argv); + +#ifdef Q_OS_SYMBIAN + QNetworkConfigurationManager configurationManager; + QNetworkConfiguration configuration = configurationManager.defaultConfiguration(); + if (!configuration.isValid()) { + qDebug() << "Got an invalid session configuration"; + exit(1); + } + + qDebug() << "Opening session..."; + QNetworkSession *session = new QNetworkSession(configuration); + + // Does not work: +// session->open(); +// session->waitForOpened(); + + // works: + QEventLoop loop; + QObject::connect(session, SIGNAL(opened()), &loop, SLOT(quit()), Qt::QueuedConnection); + QMetaObject::invokeMethod(session, "open", Qt::QueuedConnection); + loop.exec(); + + + if (session->isOpen()) { + qDebug() << "session opened"; + } else { + qDebug() << "session could not be opened -" << session->errorString(); + exit(1); + } +#endif + + // create it + QAbstractSocketEngine *socketEngine = + QAbstractSocketEngine::createSocketEngine(QAbstractSocket::TcpSocket, QNetworkProxy(QNetworkProxy::NoProxy), 0); + if (!socketEngine) { + qDebug() << "could not create engine"; + exit(1); + } + + // initialize it + bool initialized = socketEngine->initialize(QAbstractSocket::TcpSocket, QAbstractSocket::IPv4Protocol); + if (!initialized) { + qDebug() << "not able to initialize engine"; + exit(1); + } + + // wait for connected + int r = socketEngine->connectToHost(QHostAddress("74.125.77.99"), 80); // google + bool readyToRead = false; + bool readyToWrite = false; + socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, true, 10*1000); + if (r <= 0) //timeout or error + exit(1); + if (readyToWrite) { + // write the request + QByteArray request("GET /robots.txt HTTP/1.0\r\n\r\n"); + int ret = socketEngine->write(request.constData(), request.length()); + if (ret == request.length()) { + // read the response in a loop + do { + bool waitReadResult = socketEngine->waitForRead(10*1000); + int available = socketEngine->bytesAvailable(); + if (waitReadResult == true && available == 0) { + // disconnected + exit(0); + } + bzero(buf, bufsize); + ret = socketEngine->read(buf, available); + if (ret > 0) { +#ifdef Q_OS_SYMBIAN + qDebug() << buf; //printf goes only to screen, this goes to remote debug channel +#else + printf("%s", buf); +#endif + } else { + // some failure when reading + exit(1); + } + } while (1); + } else { + qDebug() << "failed writing"; + } + } else { + qDebug() << "failed connecting"; + } + delete socketEngine; +} + diff --git a/tests/manual/socketengine/socketengine.pro b/tests/manual/socketengine/socketengine.pro new file mode 100644 index 0000000..76a40be --- /dev/null +++ b/tests/manual/socketengine/socketengine.pro @@ -0,0 +1,15 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_socketengine +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui +QT += network + +CONFIG += release + +symbian: TARGET.CAPABILITY = NetworkServices + +# Input +SOURCES += main.cpp |