From 5a9fd4f49ec48c91c70699fc40af8f843c51b4ab Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 28 Feb 2017 15:55:39 +0100 Subject: V4 Debugger: Don't crash when stepping to the end of a script The last instruction is a return, which leads to an invalid context. Don't try to save that context, but rather clear the current one. Change-Id: I468b7420c4ca0842209c9b00478f99cc4dc69726 Reviewed-by: Simon Hausmann --- .../qml/debugger/qv4debugger/tst_qv4debugger.cpp | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 6793596174..7668c8b016 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -176,6 +176,7 @@ public: , m_captureContextInfo(false) , m_thrownValue(-1) , collector(engine) + , m_resumeSpeed(QV4Debugger::FullThrottle) , m_debugger(0) { } @@ -214,7 +215,7 @@ public slots: if (m_captureContextInfo) captureContextInfo(debugger); - debugger->resume(QV4Debugger::FullThrottle); + debugger->resume(m_resumeSpeed); } public: @@ -280,6 +281,7 @@ public: int context; }; QVector m_expressionRequests; + QV4Debugger::Speed m_resumeSpeed; QList m_expressionResults; QList m_expressionRefs; QV4Debugger *m_debugger; @@ -324,6 +326,7 @@ private slots: void breakInWith(); void evaluateExpression(); + void stepToEndOfScript(); private: QV4Debugger *debugger() const @@ -758,6 +761,31 @@ void tst_qv4debugger::evaluateExpression() } } +void tst_qv4debugger::stepToEndOfScript() +{ + QString script = + "var ret = 0;\n" + "ret += 4;\n" + "ret += 1;\n" + "ret += 5;\n"; + + debugger()->addBreakPoint("toEnd", 1); + m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver; + evaluateJavaScript(script, "toEnd"); + QVERIFY(m_debuggerAgent->m_wasPaused); + QCOMPARE(m_debuggerAgent->m_pauseReason, QV4Debugger::Step); + QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 5); + for (int i = 0; i < 4; ++i) { + QV4Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.at(i); + QCOMPARE(state.fileName, QString("toEnd")); + QCOMPARE(state.lineNumber, i + 1); + } + + QV4Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.at(4); + QCOMPARE(state.fileName, QString("toEnd")); + QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number. +} + QTEST_MAIN(tst_qv4debugger) #include "tst_qv4debugger.moc" -- cgit v1.2.3 From c67d33db5b4e78027181be492d4757ac786e5c1f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 28 Feb 2017 15:07:42 +0100 Subject: Add a source location to the final Jump in a for loop Otherwise it will assume the last statement as the location of the jump, and that might be a statement that is never hit. Task-number: QTBUG-59204 Change-Id: I66019a284b061358939b23e649ca0832b5442388 Reviewed-by: hjk Reviewed-by: Simon Hausmann --- .../qml/debugger/qv4debugger/tst_qv4debugger.cpp | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 7668c8b016..8362cb9ed6 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -327,6 +327,7 @@ private slots: void evaluateExpression(); void stepToEndOfScript(); + void lastLineOfLoop(); private: QV4Debugger *debugger() const @@ -786,6 +787,31 @@ void tst_qv4debugger::stepToEndOfScript() QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number. } +void tst_qv4debugger::lastLineOfLoop() +{ + QString script = + "var ret = 0;\n" + "for (var i = 0; i < 10; ++i) {\n" + " if (i == 2)\n" + " ret += 4;\n" // breakpoint, then step over + " else \n" + " ret += 1;\n" + "}\n"; // after step over + + debugger()->addBreakPoint("trueBranch", 4); + m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver; + evaluateJavaScript(script, "trueBranch"); + QVERIFY(m_debuggerAgent->m_wasPaused); + QCOMPARE(m_debuggerAgent->m_pauseReason, QV4Debugger::Step); + QVERIFY(m_debuggerAgent->m_statesWhenPaused.count() > 1); + QV4Debugger::ExecutionState firstState = m_debuggerAgent->m_statesWhenPaused.first(); + QCOMPARE(firstState.fileName, QString("trueBranch")); + QCOMPARE(firstState.lineNumber, 4); + QV4Debugger::ExecutionState secondState = m_debuggerAgent->m_statesWhenPaused.at(1); + QCOMPARE(secondState.fileName, QString("trueBranch")); + QCOMPARE(secondState.lineNumber, 7); +} + QTEST_MAIN(tst_qv4debugger) #include "tst_qv4debugger.moc" -- cgit v1.2.3 From 71a2dbed467be0041b6793dda868655b2632e830 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 5 Jan 2017 16:16:43 +0100 Subject: When stealing a touchpoint as synth. mouse, ungrab touch If you use MultiPointTouchArea to make a button component, or if you do something similar by subclassing QQuickItem and handling touch events, and you place such a component inside a Flickable, when the user presses on the button and then drags far enough that the Flickable steals the grab, the MPTA or custom item did not receive the touchUngrabEvent() callback. Now it does, so now the button will go back to released state as a result of having the grab stolen. The situation here is special in that it's the only place where a touch event is transformed to be treated as mouse in the future, usually it's either treated as touch or mouse from the start. When this happens, it's not enough to call setMouseGrabber because that doesn't send touch cancel to the previous grabber. Instead we need to explicitly call touchUngrabEvent to notify the touch handling item. The explicit setting of the grabber which was there previously is not needed, since grabMouse will update the grab based on touchMouseId. tst_QQuickMultiPointTouchArea::inFlickable2 was already testing the pressed state of the touchpoint when the grab is stolen, but it was changed in 468626e99a90d6ac21cb311cde05c658ccb3b781; now that can be restored, and we can also un-blacklist inFlickable, which was deemed unstable in 6d163779711d4601931ae0f82910794fb2498136 [ChangeLog][QtQuick] MultiPointTouchArea, and any custom Item, will now properly receive touchUngrabEvent() when the touch grab is stolen by a filtering parent Item, such as a Flickable. Task-number: QTBUG-57910 Change-Id: I4e1b23ed099f01e7eca2e8a0e7ab4c652ef00cfa Reviewed-by: Frederik Gladhorn Reviewed-by: Shawn Rutledge --- .../auto/quick/qquickmultipointtoucharea/BLACKLIST | 2 - .../tst_qquickmultipointtoucharea.cpp | 2 +- tests/auto/quick/touchmouse/tst_touchmouse.cpp | 76 ++++++++++++++++++++-- 3 files changed, 73 insertions(+), 7 deletions(-) delete mode 100644 tests/auto/quick/qquickmultipointtoucharea/BLACKLIST (limited to 'tests') diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST deleted file mode 100644 index 1777af9e0c..0000000000 --- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[inFlickable] -* diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index 2872556a94..87acd67f6a 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -800,7 +800,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable2() QVERIFY(flickable->contentY() < 0); QVERIFY(flickable->isMoving()); - QCOMPARE(point11->pressed(), true); + QCOMPARE(point11->pressed(), false); QTest::touchEvent(window.data(), device).release(0, p1); QQuickTouchUtils::flush(window.data()); diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 032e682137..671cefd6f5 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -71,7 +71,7 @@ Q_SIGNALS: public: EventItem(QQuickItem *parent = 0) - : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1) + : QQuickItem(parent), touchUngrabCount(0), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1) { setAcceptedMouseButtons(Qt::LeftButton); } @@ -111,11 +111,17 @@ public: eventList.append(Event(QEvent::UngrabMouse, QPoint(0,0), QPoint(0,0))); } + void touchUngrabEvent() + { + ++touchUngrabCount; + } + bool event(QEvent *event) { return QQuickItem::event(event); } QList eventList; + int touchUngrabCount; bool acceptMouse; bool acceptTouch; bool filterTouch; // when used as event filter @@ -158,6 +164,7 @@ private slots: void mouseOverTouch(); void buttonOnFlickable(); + void touchButtonOnFlickable(); void buttonOnDelayedPressFlickable_data(); void buttonOnDelayedPressFlickable(); void buttonOnTouch(); @@ -568,9 +575,10 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1); QCOMPARE(window->mouseGrabberItem(), eventItem1); - p1 += QPoint(0, -10); - QPoint p2 = p1 + QPoint(0, -10); - QPoint p3 = p2 + QPoint(0, -10); + int dragDelta = -qApp->styleHints()->startDragDistance(); + p1 += QPoint(0, dragDelta); + QPoint p2 = p1 + QPoint(0, dragDelta); + QPoint p3 = p2 + QPoint(0, dragDelta); QQuickTouchUtils::flush(window.data()); QTest::touchEvent(window.data(), device).move(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); @@ -593,6 +601,66 @@ void tst_TouchMouse::buttonOnFlickable() QQuickTouchUtils::flush(window.data()); } +void tst_TouchMouse::touchButtonOnFlickable() +{ + // flickable - height 500 / 1000 + // - eventItem1 y: 100, height 100 + // - eventItem2 y: 300, height 100 + + QScopedPointer window(createView()); + window->setSource(testFileUrl("buttononflickable.qml")); + window->show(); + QQuickViewTestUtil::centerOnScreen(window.data()); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + QVERIFY(window->rootObject() != 0); + + QQuickFlickable *flickable = window->rootObject()->findChild("flickable"); + QVERIFY(flickable); + + EventItem *eventItem2 = window->rootObject()->findChild("eventItem2"); + QVERIFY(eventItem2); + QCOMPARE(eventItem2->eventList.size(), 0); + eventItem2->acceptTouch = true; + + // press via touch, then drag: check that flickable moves and that the button gets ungrabbed + QCOMPARE(eventItem2->eventList.size(), 0); + QPoint p1 = QPoint(10, 310); + QTest::touchEvent(window.data(), device).press(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QCOMPARE(eventItem2->eventList.size(), 1); + QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); + + QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data()); + QVERIFY(windowPriv->touchMouseId == -1); + auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); + QCOMPARE(pointerEvent->point(0)->grabber(), eventItem2); + QCOMPARE(window->mouseGrabberItem(), nullptr); + + int dragDelta = qApp->styleHints()->startDragDistance() * -0.7; + p1 += QPoint(0, dragDelta); + QPoint p2 = p1 + QPoint(0, dragDelta); + QPoint p3 = p2 + QPoint(0, dragDelta); + + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p2, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); + + QVERIFY(eventItem2->eventList.size() > 2); + QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate); + QCOMPARE(eventItem2->touchUngrabCount, 1); + QCOMPARE(window->mouseGrabberItem(), flickable); + QVERIFY(windowPriv->touchMouseId != -1); + QCOMPARE(pointerEvent->point(0)->grabber(), flickable); + QVERIFY(flickable->isMovingVertically()); + + QTest::touchEvent(window.data(), device).release(0, p3, window.data()); + QQuickTouchUtils::flush(window.data()); +} + void tst_TouchMouse::buttonOnDelayedPressFlickable_data() { QTest::addColumn("scrollBeforeDelayIsOver"); -- cgit v1.2.3 From 408620ea99606f8b27ebf237fa3800e40e2c9cd3 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 2 Mar 2017 11:41:47 +0100 Subject: Fix building with -no-feature-process Drop an unused include, don't try to build qmlplugindump in this case, and add some guards around QProcess includes and usages. Change-Id: I6ce5985a8dd1967f146016a7acd1ea31fb3bda2a Reviewed-by: Simon Hausmann --- tests/auto/qml/qmlmin/tst_qmlmin.cpp | 8 +++++--- .../auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp | 2 ++ tests/auto/quick/examples/tst_examples.cpp | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index 3ed0aa7446..90868d2ead 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -29,7 +29,9 @@ #include #include #include +#if QT_CONFIG(process) #include +#endif #include #include #include @@ -42,7 +44,7 @@ public: private slots: void initTestCase(); -#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled +#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void qmlMinify_data(); void qmlMinify(); #endif @@ -166,7 +168,7 @@ Examples are any .qml files under the examples/ directory that start with a lower case letter. */ -#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled +#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void tst_qmlmin::qmlMinify_data() { QTest::addColumn("file"); @@ -183,7 +185,7 @@ void tst_qmlmin::qmlMinify_data() } #endif -#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled +#if QT_CONFIG(process) && !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled void tst_qmlmin::qmlMinify() { QFETCH(QString, file); diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp index 98b92e5fab..f2754d636b 100644 --- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp +++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp @@ -29,7 +29,9 @@ #include "../../shared/util.h" #include #include +#if QT_CONFIG(process) #include +#endif #include class tst_qqmlapplicationengine : public QQmlDataTest diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp index 1ca809c05f..ffb7fb5789 100644 --- a/tests/auto/quick/examples/tst_examples.cpp +++ b/tests/auto/quick/examples/tst_examples.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 13335bdee5482ae04d5b0d4c933ca328a1100cb6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 6 Mar 2017 13:49:42 +0100 Subject: Fix build with -no-feature-library The versionUriList() function is unused in this case, and we cannot build the extension plugins test. Change-Id: I6c2ea1c2d078e508b0752efb45f4ccdfdbcbf22e Reviewed-by: Simon Hausmann --- tests/auto/qml/qml.pro | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 7d182b7255..b347b603bb 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -70,14 +70,17 @@ qtHaveModule(widgets) { qjsvalue } -SUBDIRS += $$PUBLICTESTS \ - qqmlextensionplugin +SUBDIRS += $$PUBLICTESTS SUBDIRS += $$METATYPETESTS qtConfig(process) { !contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger SUBDIRS += qmllint qmlplugindump } +qtConfig(library) { + SUBDIRS += qqmlextensionplugin +} + qtConfig(private_tests): \ SUBDIRS += $$PRIVATETESTS -- cgit v1.2.3 From d5d12e1d6fb9aaa5a8cee7924555f0d4d19ffabc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 1 Mar 2017 10:42:47 +0100 Subject: Set source location for all loop body-to-front jumps Task-number: QTBUG-59204 Change-Id: Id1a73b228cd3386c7fcc7712c2485f387238b65e Reviewed-by: hjk Reviewed-by: Erik Verbruggen --- .../qml/debugger/qv4debugger/tst_qv4debugger.cpp | 23 ++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 8362cb9ed6..56320b8365 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -327,8 +327,9 @@ private slots: void evaluateExpression(); void stepToEndOfScript(); - void lastLineOfLoop(); + void lastLineOfLoop_data(); + void lastLineOfLoop(); private: QV4Debugger *debugger() const { @@ -787,16 +788,30 @@ void tst_qv4debugger::stepToEndOfScript() QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number. } +void tst_qv4debugger::lastLineOfLoop_data() +{ + QTest::addColumn("loopHead"); + QTest::addColumn("loopTail"); + + QTest::newRow("for") << "for (var i = 0; i < 10; ++i) {\n" << "}\n"; + QTest::newRow("for..in") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}\n"; + QTest::newRow("while") << "while (ret < 10) {\n" << "}\n"; + QTest::newRow("do..while") << "do {\n" << "} while (ret < 10);\n"; +} + void tst_qv4debugger::lastLineOfLoop() { + QFETCH(QString, loopHead); + QFETCH(QString, loopTail); + QString script = "var ret = 0;\n" - "for (var i = 0; i < 10; ++i) {\n" - " if (i == 2)\n" + + loopHead + + " if (ret == 2)\n" " ret += 4;\n" // breakpoint, then step over " else \n" " ret += 1;\n" - "}\n"; // after step over + + loopTail; debugger()->addBreakPoint("trueBranch", 4); m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver; -- cgit v1.2.3 From 84a07bebc94e9f92d4d596550317a89403ed291f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 6 Mar 2017 15:06:59 +0100 Subject: Fix crash when loading cache files generated ahead of time The offset of the runtimeStrings array differed between a V4_BOOTSTRAP build and the regular library build. This is an intermediate fix until QTBUG-58666 is fixed properly. Change-Id: Id1310ffa82f1079c1acef7730db41186fa62610f Reviewed-by: hjk Reviewed-by: Lars Knoll --- tests/auto/toolsupport/tst_toolsupport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/toolsupport/tst_toolsupport.cpp b/tests/auto/toolsupport/tst_toolsupport.cpp index 9a11a67e65..526ba8f375 100644 --- a/tests/auto/toolsupport/tst_toolsupport.cpp +++ b/tests/auto/toolsupport/tst_toolsupport.cpp @@ -109,7 +109,7 @@ void tst_toolsupport::offsets_data() = QTest::newRow("CompiledData::CompilationUnit::runtimeStrings") << pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::runtimeStrings); - data << 16 << 32; + data << 12 << 24; } { -- cgit v1.2.3 From 25555238cde42daf5a73669234e737c90ef9ea5f Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 21 Jan 2016 11:40:18 +0100 Subject: Fix copied QDragMoveEvent drop action to propagate to original event Trying to set the drop action and the accepted state in a overridden dragMoveEvent handler, does not get propagated to the original QDragMoveEvent, because the event passed to the handler is a copy. This does not allow canceling the drop action in the move handler, or change the proposed action to a different one. Changing these values in the move handler is important to allow modifying the cursor when moving / hovering above a possible drop item, depending on user conditions. Fix consists in copying the drop action and accepted values to the original event, as well as removing the hard-coded setAccepted (true) call. Task-number: QTBUG-58260 Change-Id: I7a4bd4e68ee1023a36a63d3e835c282077e4187c Reviewed-by: Shawn Rutledge --- tests/auto/quick/qquickwindow/tst_qquickwindow.cpp | 258 +++++++++++++++++++++ 1 file changed, 258 insertions(+) (limited to 'tests') diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index dd00154935..1d6547c5be 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -372,6 +373,8 @@ private slots: void grabContentItemToImage(); + void testDragEventPropertyPropagation(); + private: QTouchDevice *touchDevice; QTouchDevice *touchDeviceWithVelocity; @@ -2573,6 +2576,261 @@ void tst_qquickwindow::grabContentItemToImage() QTRY_COMPARE(created->property("success").toInt(), 1); } +class TestDropTarget : public QQuickItem +{ + Q_OBJECT +public: + TestDropTarget(QQuickItem *parent = 0) + : QQuickItem(parent) + , enterDropAction(Qt::CopyAction) + , moveDropAction(Qt::CopyAction) + , dropDropAction(Qt::CopyAction) + , enterAccept(true) + , moveAccept(true) + , dropAccept(true) + { + setFlags(ItemAcceptsDrops); + } + + void reset() + { + enterDropAction = Qt::CopyAction; + moveDropAction = Qt::CopyAction; + dropDropAction = Qt::CopyAction; + enterAccept = true; + moveAccept = true; + dropAccept = true; + } + + void dragEnterEvent(QDragEnterEvent *event) + { + event->setAccepted(enterAccept); + event->setDropAction(enterDropAction); + } + + void dragMoveEvent(QDragMoveEvent *event) + { + event->setAccepted(moveAccept); + event->setDropAction(moveDropAction); + } + + void dropEvent(QDropEvent *event) + { + event->setAccepted(dropAccept); + event->setDropAction(dropDropAction); + } + + Qt::DropAction enterDropAction; + Qt::DropAction moveDropAction; + Qt::DropAction dropDropAction; + bool enterAccept; + bool moveAccept; + bool dropAccept; +}; + +class DragEventTester { +public: + DragEventTester() + : pos(60, 60) + , actions(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction) + , buttons(Qt::LeftButton) + , modifiers(Qt::NoModifier) + { + } + + ~DragEventTester() { + qDeleteAll(events); + events.clear(); + enterEvent = 0; + moveEvent = 0; + dropEvent = 0; + leaveEvent = 0; + } + + void addEnterEvent() + { + enterEvent = new QDragEnterEvent(pos, actions, &data, buttons, modifiers); + events.append(enterEvent); + } + + void addMoveEvent() + { + moveEvent = new QDragMoveEvent(pos, actions, &data, buttons, modifiers, QEvent::DragMove); + events.append(moveEvent); + } + + void addDropEvent() + { + dropEvent = new QDropEvent(pos, actions, &data, buttons, modifiers, QEvent::Drop); + events.append(dropEvent); + } + + void addLeaveEvent() + { + leaveEvent = new QDragLeaveEvent(); + events.append(leaveEvent); + } + + void sendDragEventSequence(QQuickWindow *window) const { + for (int i = 0; i < events.size(); ++i) { + QCoreApplication::sendEvent(window, events[i]); + } + } + + // Used for building events. + QMimeData data; + QPoint pos; + Qt::DropActions actions; + Qt::MouseButtons buttons; + Qt::KeyboardModifiers modifiers; + + // Owns events. + QList events; + + // Non-owner pointers for easy acccess. + QDragEnterEvent *enterEvent; + QDragMoveEvent *moveEvent; + QDropEvent *dropEvent; + QDragLeaveEvent *leaveEvent; +}; + +void tst_qquickwindow::testDragEventPropertyPropagation() +{ + QQuickWindow window; + TestDropTarget dropTarget(window.contentItem()); + + // Setting the size is important because the QQuickWindow checks if the drag happened inside + // the drop target. + dropTarget.setSize(QSizeF(100, 100)); + + // Test enter events property propagation. + // For enter events, only isAccepted gets propagated. + { + DragEventTester builder; + dropTarget.enterAccept = false; + dropTarget.enterDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragEnterEvent* enterEvent = builder.enterEvent; + QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept); + } + { + DragEventTester builder; + dropTarget.enterAccept = false; + dropTarget.enterDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragEnterEvent* enterEvent = builder.enterEvent; + QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept); + } + { + DragEventTester builder; + dropTarget.enterAccept = true; + dropTarget.enterDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragEnterEvent* enterEvent = builder.enterEvent; + QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept); + } + { + DragEventTester builder; + dropTarget.enterAccept = true; + dropTarget.enterDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragEnterEvent* enterEvent = builder.enterEvent; + QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept); + } + + // Test move events property propagation. + // For move events, both isAccepted and dropAction get propagated. + dropTarget.reset(); + { + DragEventTester builder; + dropTarget.moveAccept = false; + dropTarget.moveDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragMoveEvent* moveEvent = builder.moveEvent; + QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept); + QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction); + } + { + DragEventTester builder; + dropTarget.moveAccept = false; + dropTarget.moveDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragMoveEvent* moveEvent = builder.moveEvent; + QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept); + QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction); + } + { + DragEventTester builder; + dropTarget.moveAccept = true; + dropTarget.moveDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragMoveEvent* moveEvent = builder.moveEvent; + QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept); + QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction); + } + { + DragEventTester builder; + dropTarget.moveAccept = true; + dropTarget.moveDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent(); + builder.sendDragEventSequence(&window); + QDragMoveEvent* moveEvent = builder.moveEvent; + QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept); + QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction); + } + + // Test drop events property propagation. + // For drop events, both isAccepted and dropAction get propagated. + dropTarget.reset(); + { + DragEventTester builder; + dropTarget.dropAccept = false; + dropTarget.dropDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent(); + builder.sendDragEventSequence(&window); + QDropEvent* dropEvent = builder.dropEvent; + QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept); + QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction); + } + { + DragEventTester builder; + dropTarget.dropAccept = false; + dropTarget.dropDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent(); + builder.sendDragEventSequence(&window); + QDropEvent* dropEvent = builder.dropEvent; + QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept); + QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction); + } + { + DragEventTester builder; + dropTarget.dropAccept = true; + dropTarget.dropDropAction = Qt::IgnoreAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent(); + builder.sendDragEventSequence(&window); + QDropEvent* dropEvent = builder.dropEvent; + QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept); + QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction); + } + { + DragEventTester builder; + dropTarget.dropAccept = true; + dropTarget.dropDropAction = Qt::CopyAction; + builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent(); + builder.sendDragEventSequence(&window); + QDropEvent* dropEvent = builder.dropEvent; + QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept); + QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction); + } +} + QTEST_MAIN(tst_qquickwindow) #include "tst_qquickwindow.moc" -- cgit v1.2.3 From 5b94de09cc738837d1539e28b3c0dccd17c18d29 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Mar 2017 15:24:59 +0100 Subject: Fix caching of QML singleton types When a QML file depends on a QML singleton, we failed to include it in the dependency hash. Thus changes to the QML singleton did not result in a re-creation of the caches of files that use it. The list of singletons comes from random-ordered hashes in the qml import handling. We provide an order to the direct dependencies by sorting by the singleton type names. Task-number: QTBUG-58486 Change-Id: Ie7e9d006f9bf3a60af1f819ee439c29bc234bd8a Reviewed-by: Lars Knoll --- tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index b265607fd1..9494e3a7fd 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -58,6 +58,7 @@ private slots: void localAliases(); void cacheResources(); void stableOrderOfDependentCompositeTypes(); + void singletonDependency(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -737,6 +738,58 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes() } } +void tst_qmldiskcache::singletonDependency() +{ + QScopedPointer engine(new QQmlEngine); + + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + writeTempFile("MySingleton.qml", "import QtQml 2.0\npragma Singleton\nQtObject { property int value: 42 }"); + writeTempFile("qmldir", "singleton MySingleton 1.0 MySingleton.qml"); + const QString testFilePath = writeTempFile("main.qml", "import QtQml 2.0\nimport \".\"\nQtObject {\n" + " property int value: MySingleton.value\n" + "}"); + + { + CleanlyLoadingComponent component(engine.data(), QUrl::fromLocalFile(testFilePath)); + QScopedPointer obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("value").toInt(), 42); + } + + const QString testFileCachePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(testFileCachePath)); + QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); + + engine.reset(new QQmlEngine); + waitForFileSystem(); + + writeTempFile("MySingleton.qml", "import QtQml 2.0\npragma Singleton\nQtObject { property int value: 100 }"); + waitForFileSystem(); + + { + CleanlyLoadingComponent component(engine.data(), QUrl::fromLocalFile(testFilePath)); + QScopedPointer obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("value").toInt(), 100); + } + + { + QVERIFY(QFile::exists(testFileCachePath)); + QDateTime newCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); + QVERIFY2(newCacheTimeStamp > initialCacheTimeStamp, qPrintable(newCacheTimeStamp.toString())); + } +} + QTEST_MAIN(tst_qmldiskcache) #include "tst_qmldiskcache.moc" -- cgit v1.2.3 From ffe538a565e2f14ad276078891f18ec90d09be82 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 9 Mar 2017 18:53:23 +0100 Subject: QV4DebugService: Reduce unnecessary recursion and redundancy Large parts of the protocol are unnecessary. There is no reason to send a separate chunk of "handles" with almost every reply. The refs are given as part of the regular data and if the client wants to find out more, it can do further lookups. Also, it makes no sense to encode the function and script names as objects, as they are in fact not JavaScript objects. Unfortunately these cleanups require some cooperation from the client. Older clients will misbehave if we just drop the redundancy. Therefore, we introduce parameters which the client can explicitly set with the "connect" message. redundantRefs tells the service if redundant references are required, namesAsObjects tells it if script and function names have to be sent as objects/ Once we can require clients that support these options, we can drop the code that generates redundant data. Also, fix tst_qv4debugger::evaluateExpression() to actually check all the expressions evaluated, not only the first and second one. Task-number: QTBUG-42435 Change-Id: If93d2a2b9d0b8035f85dbef871bc1b03f199171d Reviewed-by: hjk Reviewed-by: Simon Hausmann --- .../qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp | 118 ++++++++++++++++----- .../qml/debugger/qv4debugger/tst_qv4debugger.cpp | 82 ++++++++------ 2 files changed, 140 insertions(+), 60 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp index 31b8d63ec2..d248cf9708 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp @@ -257,7 +257,7 @@ public: stringify = jsEngine.evaluate(QLatin1String("JSON.stringify")); } - void connect(); + void connect(bool redundantRefs = false, bool namesAsObjects = false); void interrupt(); void continueDebugging(StepAction stepAction); @@ -304,9 +304,13 @@ public: }; -void QJSDebugClient::connect() +void QJSDebugClient::connect(bool redundantRefs, bool namesAsObjects) { - sendMessage(packMessage(CONNECT)); + QJSValue jsonVal = parser.call(QJSValueList() << QLatin1String("{}")); + jsonVal.setProperty("redundantRefs", QJSValue(redundantRefs)); + jsonVal.setProperty("namesAsObjects", QJSValue(namesAsObjects)); + sendMessage(packMessage(CONNECT, + stringify.call(QJSValueList() << jsonVal).toString().toUtf8())); } void QJSDebugClient::interrupt() @@ -870,8 +874,10 @@ void tst_QQmlDebugJS::interrupt() //void connect() QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene); - client->connect(); + client->connect(redundantRefs, namesAsObjects); client->interrupt(); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested()))); @@ -882,8 +888,10 @@ void tst_QQmlDebugJS::getVersion() //void version() QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(connected()))); client->version(); @@ -894,9 +902,11 @@ void tst_QQmlDebugJS::getVersionWhenAttaching() { //void version() QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene, QLatin1String(TIMER_QMLFILE), false); - client->connect(); + client->connect(redundantRefs, namesAsObjects); client->version(); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); @@ -907,8 +917,10 @@ void tst_QQmlDebugJS::disconnect() //void disconnect() QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene); - client->connect(); + client->connect(redundantRefs, namesAsObjects); client->disconnect(); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); @@ -918,12 +930,14 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, ONCOMPLETED_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); QString jsonString(client->response); @@ -939,12 +953,14 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, CREATECOMPONENT_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); QString jsonString(client->response); @@ -959,10 +975,12 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated() void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback() { QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 35; init(qmlscene, TIMER_QMLFILE); - client->connect(); + client->connect(redundantRefs, namesAsObjects); //We can set the breakpoint after connect() here because the timer is repeating and if we miss //its first iteration we can still catch the second one. client->setBreakpoint(QLatin1String(TIMER_QMLFILE), sourceLine, -1, true); @@ -981,12 +999,14 @@ void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 31; init(qmlscene, LOADJSFILE_QMLFILE); client->setBreakpoint(QLatin1String(TEST_JSFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); QString jsonString(client->response); @@ -1002,13 +1022,15 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComment() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; int actualLine = 36; init(qmlscene, BREAKPOINTRELOCATION_QMLFILE); client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1)); @@ -1025,13 +1047,15 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 35; int actualLine = 36; init(qmlscene, BREAKPOINTRELOCATION_QMLFILE); client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QEXPECT_FAIL("", "Relocation of breakpoints is disabled right now", Abort); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()), 1)); @@ -1048,12 +1072,14 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding() { //void setBreakpoint(QString type, QString target, int line = -1, int column = -1, bool enabled = false, QString condition = QString(), int ignoreCount = -1) QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 39; init(qmlscene, BREAKPOINTRELOCATION_QMLFILE); client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); QString jsonString(client->response); @@ -1068,11 +1094,13 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding() void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() { QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int out = 10; int sourceLine = 37; init(qmlscene, CONDITION_QMLFILE); - client->connect(); + client->connect(redundantRefs, namesAsObjects); //The breakpoint is in a timer loop so we can set it after connect(). client->setBreakpoint(QLatin1String(CONDITION_QMLFILE), sourceLine, 1, true, QLatin1String("a > 10")); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); @@ -1105,12 +1133,14 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition() void tst_QQmlDebugJS::setBreakpointInScriptThatQuits() { QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene, QUIT_QMLFILE); int sourceLine = 36; client->setBreakpoint(QLatin1String(QUIT_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); QString jsonString(client->response); @@ -1147,12 +1177,14 @@ void tst_QQmlDebugJS::clearBreakpoint() { //void clearBreakpoint(int breakpoint); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine1 = 37; int sourceLine2 = 38; init(qmlscene, CHANGEBREAKPOINT_QMLFILE); - client->connect(); + client->connect(redundantRefs, namesAsObjects); //The breakpoints are in a timer loop so we can set them after connect(). //Furthermore the breakpoints should be hit in the right order because setting of breakpoints //can only occur in the QML event loop. (see QCOMPARE for sourceLine2 below) @@ -1195,10 +1227,12 @@ void tst_QQmlDebugJS::setExceptionBreak() { //void setExceptionBreak(QString type, bool enabled = false); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene, EXCEPTION_QMLFILE); client->setExceptionBreak(QJSDebugClient::All,true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); } @@ -1206,12 +1240,14 @@ void tst_QQmlDebugJS::stepNext() { //void continueDebugging(StepAction stepAction, int stepCount = 1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 37; init(qmlscene, STEPACTION_QMLFILE); client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->continueDebugging(QJSDebugClient::Next); @@ -1230,13 +1266,15 @@ void tst_QQmlDebugJS::stepIn() { //void continueDebugging(StepAction stepAction, int stepCount = 1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 41; int actualLine = 37; init(qmlscene, STEPACTION_QMLFILE); client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->continueDebugging(QJSDebugClient::In); @@ -1255,13 +1293,15 @@ void tst_QQmlDebugJS::stepOut() { //void continueDebugging(StepAction stepAction, int stepCount = 1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 37; int actualLine = 41; init(qmlscene, STEPACTION_QMLFILE); client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->continueDebugging(QJSDebugClient::Out); @@ -1280,6 +1320,8 @@ void tst_QQmlDebugJS::continueDebugging() { //void continueDebugging(StepAction stepAction, int stepCount = 1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine1 = 41; int sourceLine2 = 38; @@ -1287,7 +1329,7 @@ void tst_QQmlDebugJS::continueDebugging() client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true); client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->continueDebugging(QJSDebugClient::Continue); @@ -1306,12 +1348,14 @@ void tst_QQmlDebugJS::backtrace() { //void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, ONCOMPLETED_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->backtrace(); @@ -1322,12 +1366,14 @@ void tst_QQmlDebugJS::getFrameDetails() { //void frame(int number = -1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, ONCOMPLETED_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->frame(); @@ -1338,12 +1384,14 @@ void tst_QQmlDebugJS::getScopeDetails() { //void scope(int number = -1, int frameNumber = -1); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, ONCOMPLETED_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->scope(); @@ -1374,11 +1422,13 @@ void tst_QQmlDebugJS::evaluateInLocalScope() //void evaluate(QString expr, bool global = false, bool disableBreak = false, int frame = -1, const QVariantMap &addContext = QVariantMap()); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); int sourceLine = 34; init(qmlscene, ONCOMPLETED_QMLFILE); client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->frame(); @@ -1461,10 +1511,12 @@ void tst_QQmlDebugJS::getScripts() //void scripts(int types = -1, QList ids = QList(), bool includeSource = false, QVariant filter = QVariant()); QFETCH(bool, qmlscene); + QFETCH(bool, redundantRefs); + QFETCH(bool, namesAsObjects); init(qmlscene); client->setBreakpoint(QString(TEST_QMLFILE), 35, -1, true); - client->connect(); + client->connect(redundantRefs, namesAsObjects); QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped()))); client->scripts(); @@ -1482,8 +1534,16 @@ void tst_QQmlDebugJS::getScripts() void tst_QQmlDebugJS::targetData() { QTest::addColumn("qmlscene"); - QTest::newRow("custom") << false; - QTest::newRow("qmlscene") << true; + QTest::addColumn("redundantRefs"); + QTest::addColumn("namesAsObjects"); + QTest::newRow("custom / redundant / objects") << false << true << true; + QTest::newRow("qmlscene / redundant / objects") << true << true << true; + QTest::newRow("custom / redundant / strings") << false << true << false; + QTest::newRow("qmlscene / redundant / strings") << true << true << false; + QTest::newRow("custom / sparse / objects") << false << false << true; + QTest::newRow("qmlscene / sparse / objects") << true << false << true; + QTest::newRow("custom / sparse / strings") << false << false << false; + QTest::newRow("qmlscene / sparse / strings") << true << false << false; } QTEST_MAIN(tst_QQmlDebugJS) diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 56320b8365..6d0d884ed7 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -120,7 +120,6 @@ public: typedef QV4DataCollector::Refs Refs; typedef QV4DataCollector::Ref Ref; struct NamedRefs { - QJsonArray refs; QJsonObject scope; int size() const { @@ -131,15 +130,6 @@ public: return scope.contains(name); } - QJsonObject resolveRef(int ref) const { - foreach (const QJsonValue &val, refs) { - QJsonObject obj = val.toObject(); - if (obj.value(QLatin1String("handle")).toInt() == ref) - return obj; - } - return QJsonObject(); - } - #define DUMP_JSON(x) {\ QJsonDocument doc(x);\ qDebug() << #x << "=" << doc.toJson(QJsonDocument::Indented);\ @@ -209,7 +199,6 @@ public slots: request.expression, &collector); debugger->runInEngine(&job); m_expressionResults << job.returnValue(); - m_expressionRefs << job.refs(); } if (m_captureContextInfo) @@ -235,24 +224,17 @@ public: ScopeJob job(&collector, i, 0); debugger->runInEngine(&job); NamedRefs &refs = m_capturedScope.last(); - refs.refs = job.refs(); QJsonObject object = job.returnValue(); object = object.value(QLatin1String("object")).toObject(); - int ref = object.value(QLatin1String("ref")).toInt(); - object = refs.resolveRef(ref); + if (object.contains("ref") && !object.contains("properties")) { + QVERIFY(collector.redundantRefs()); + object = collector.lookupRef(object.value("ref").toInt(), true); + QVERIFY(object.contains("properties")); + } foreach (const QJsonValue &value, object.value(QLatin1String("properties")).toArray()) { QJsonObject property = value.toObject(); QString name = property.value(QLatin1String("name")).toString(); property.remove(QLatin1String("name")); - if (property.contains(QLatin1String("ref"))) { - int childRef = property.value(QLatin1String("ref")).toInt(); - if (childRef >= 0 && refs.refs.size() > childRef) { - property.remove(QLatin1String("ref")); - property.insert(QLatin1String("properties"), - refs.resolveRef(childRef).value( - QLatin1String("properties")).toArray()); - } - } refs.scope.insert(name, property); } } @@ -283,7 +265,6 @@ public: QVector m_expressionRequests; QV4Debugger::Speed m_resumeSpeed; QList m_expressionResults; - QList m_expressionRefs; QV4Debugger *m_debugger; // Utility methods: @@ -315,9 +296,13 @@ private slots: void conditionalBreakPointInQml(); // context access: + void readArguments_data() { redundancy_data(); } void readArguments(); + void readLocals_data() { redundancy_data(); } void readLocals(); + void readObject_data() { redundancy_data(); } void readObject(); + void readContextInAllFrames_data() { redundancy_data(); } void readContextInAllFrames(); // exceptions: @@ -325,7 +310,9 @@ private slots: void breakInCatch(); void breakInWith(); + void evaluateExpression_data() { redundancy_data(); } void evaluateExpression(); + void stepToEndOfScript_data() { redundancy_data(); } void stepToEndOfScript(); void lastLineOfLoop_data(); @@ -343,6 +330,8 @@ private: waitForSignal(m_engine, SIGNAL(evaluateFinished()), /*timeout*/0); } + void redundancy_data(); + TestEngine *m_engine; QV4::ExecutionEngine *m_v4; TestAgent *m_debuggerAgent; @@ -537,6 +526,9 @@ void tst_qv4debugger::conditionalBreakPointInQml() void tst_qv4debugger::readArguments() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + m_debuggerAgent->m_captureContextInfo = true; QString script = "function f(a, b, c, d) {\n" @@ -560,6 +552,9 @@ void tst_qv4debugger::readArguments() void tst_qv4debugger::readLocals() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + m_debuggerAgent->m_captureContextInfo = true; QString script = "function f(a, b) {\n" @@ -583,6 +578,9 @@ void tst_qv4debugger::readLocals() void tst_qv4debugger::readObject() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + m_debuggerAgent->m_captureContextInfo = true; QString script = "function f(a) {\n" @@ -599,6 +597,12 @@ void tst_qv4debugger::readObject() QVERIFY(frame0.contains("b")); QCOMPARE(frame0.type("b"), QStringLiteral("object")); QJsonObject b = frame0.rawValue("b"); + QVERIFY(b.contains(QStringLiteral("ref"))); + QVERIFY(b.contains(QStringLiteral("value"))); + QVERIFY(!b.contains(QStringLiteral("properties"))); + QVERIFY(b.value("value").isDouble()); + QCOMPARE(b.value("value").toInt(), 2); + b = m_debuggerAgent->collector.lookupRef(b.value("ref").toInt(), true); QVERIFY(b.contains(QStringLiteral("properties"))); QVERIFY(b.value("properties").isArray()); QJsonArray b_props = b.value("properties").toArray(); @@ -614,7 +618,8 @@ void tst_qv4debugger::readObject() QCOMPARE(b_tail.value("name").toString(), QStringLiteral("tail")); QVERIFY(b_tail.contains("ref")); - QJsonObject b_tail_value = m_debuggerAgent->collector.lookupRef(b_tail.value("ref").toInt()); + QJsonObject b_tail_value = m_debuggerAgent->collector.lookupRef(b_tail.value("ref").toInt(), + true); QCOMPARE(b_tail_value.value("type").toString(), QStringLiteral("object")); QVERIFY(b_tail_value.contains("properties")); QJsonArray b_tail_props = b_tail_value.value("properties").toArray(); @@ -631,6 +636,9 @@ void tst_qv4debugger::readObject() void tst_qv4debugger::readContextInAllFrames() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + m_debuggerAgent->m_captureContextInfo = true; QString script = "function fact(n) {\n" @@ -678,7 +686,8 @@ void tst_qv4debugger::pauseOnThrow() QCOMPARE(m_debuggerAgent->m_pauseReason, QV4Debugger::Throwing); QCOMPARE(m_debuggerAgent->m_stackTrace.size(), 2); QVERIFY(m_debuggerAgent->m_thrownValue >= qint64(0)); - QJsonObject exception = m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_thrownValue); + QJsonObject exception = m_debuggerAgent->collector.lookupRef(m_debuggerAgent->m_thrownValue, + true); // DUMP_JSON(exception); QCOMPARE(exception.value("type").toString(), QStringLiteral("string")); QCOMPARE(exception.value("value").toString(), QStringLiteral("hard")); @@ -722,6 +731,9 @@ void tst_qv4debugger::breakInWith() void tst_qv4debugger::evaluateExpression() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + QString script = "function testFunction() {\n" " var x = 10\n" @@ -750,14 +762,12 @@ void tst_qv4debugger::evaluateExpression() evaluateJavaScript(script, "evaluateExpression"); - QCOMPARE(m_debuggerAgent->m_expressionRefs.count(), 4); - QCOMPARE(m_debuggerAgent->m_expressionRefs[0].size(), 1); - QJsonObject result0 = m_debuggerAgent->m_expressionRefs[0].first().toObject(); + QCOMPARE(m_debuggerAgent->m_expressionResults.count(), 4); + QJsonObject result0 = m_debuggerAgent->m_expressionResults[0]; QCOMPARE(result0.value("type").toString(), QStringLiteral("number")); QCOMPARE(result0.value("value").toInt(), 10); for (int i = 1; i < 4; ++i) { - QCOMPARE(m_debuggerAgent->m_expressionRefs[i].size(), 1); - QJsonObject result1 = m_debuggerAgent->m_expressionRefs[1].first().toObject(); + QJsonObject result1 = m_debuggerAgent->m_expressionResults[i]; QCOMPARE(result1.value("type").toString(), QStringLiteral("number")); QCOMPARE(result1.value("value").toInt(), 20); } @@ -765,6 +775,9 @@ void tst_qv4debugger::evaluateExpression() void tst_qv4debugger::stepToEndOfScript() { + QFETCH(bool, redundantRefs); + m_debuggerAgent->collector.setRedundantRefs(redundantRefs); + QString script = "var ret = 0;\n" "ret += 4;\n" @@ -827,6 +840,13 @@ void tst_qv4debugger::lastLineOfLoop() QCOMPARE(secondState.lineNumber, 7); } +void tst_qv4debugger::redundancy_data() +{ + QTest::addColumn("redundantRefs"); + QTest::addRow("redundant") << true; + QTest::addRow("sparse") << false; +} + QTEST_MAIN(tst_qv4debugger) #include "tst_qv4debugger.moc" -- cgit v1.2.3 From af9536deeaf1123aaae5ce78cee7b4014a01d595 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 15 Mar 2017 13:29:24 +0100 Subject: Fix QQmlMetaType::prettyTypeName to deal with malformed type names We can have QML type names that are empty or end in '/'. In those cases use the QMetaObject to retrieve a more meaningful type name. Change-Id: I4dd0841de13d4e7524a104f0bbc08cb854484cfe Reviewed-by: Simon Hausmann --- tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp | 28 +++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index 9fbd719d7b..30e517c8f9 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -52,6 +52,7 @@ private slots: void qmlPropertyValueInterceptorCast(); void qmlType(); void invalidQmlTypeName(); + void prettyTypeName(); void registrationType(); void compositeType(); void externalEnums(); @@ -72,6 +73,16 @@ public: }; QML_DECLARE_TYPE(TestType); +class TestType2 : public QObject +{ + Q_OBJECT +}; + +class TestType3 : public QObject +{ + Q_OBJECT +}; + class ExternalEnums : public QObject { Q_OBJECT @@ -214,13 +225,28 @@ void tst_qqmlmetatype::invalidQmlTypeName() { QStringList currFailures = QQmlMetaType::typeRegistrationFailures(); QCOMPARE(qmlRegisterType("TestNamespace", 1, 0, "Test$Type"), -1); // should fail due to invalid QML type name. + QCOMPARE(qmlRegisterType("Test", 1, 0, "EndingInSlash/"), -1); QStringList nowFailures = QQmlMetaType::typeRegistrationFailures(); foreach (const QString &f, currFailures) nowFailures.removeOne(f); - QCOMPARE(nowFailures.size(), 1); + QCOMPARE(nowFailures.size(), 2); QCOMPARE(nowFailures.at(0), QStringLiteral("Invalid QML element name \"Test$Type\"")); + QCOMPARE(nowFailures.at(1), QStringLiteral("Invalid QML element name \"EndingInSlash/\"")); +} + +void tst_qqmlmetatype::prettyTypeName() +{ + TestType2 obj2; + QCOMPARE(QQmlMetaType::prettyTypeName(&obj2), QString("TestType2")); + QVERIFY(qmlRegisterType("Test", 1, 0, "") >= 0); + QCOMPARE(QQmlMetaType::prettyTypeName(&obj2), QString("TestType2")); + + TestType3 obj3; + QCOMPARE(QQmlMetaType::prettyTypeName(&obj3), QString("TestType3")); + QVERIFY(qmlRegisterType("Test", 1, 0, "OtherName") >= 0); + QCOMPARE(QQmlMetaType::prettyTypeName(&obj3), QString("OtherName")); } void tst_qqmlmetatype::isList() -- cgit v1.2.3 From 34ff6c40c1a03f51bc259e57cffb02ad69c7663b Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 18 Jan 2017 16:26:43 +0100 Subject: qml: Override the new Object::instanceOf hook to allow QML type checking [ChangeLog][QtQml] The instanceof keyword in JavaScript has been extended to work on QML types and instances. This means that you are now able to use it to verify that a var is indeed the type you expect (e.g. someVar instanceof Rectangle). Note that one of the added tests revealed a slight shortcoming in the QML type system (QTBUG-58477). For now, we should keep consistency and work to address the problem universally in the future. Change-Id: I7d9bf9b64cfd037908de1ae51b01065eacb95abe Task-number: QTBUG-24799 Reviewed-by: Simon Hausmann --- .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 2 + .../data/instanceOf/CustomMouseArea.qml | 6 + .../data/instanceOf/CustomRectangle.qml | 4 + .../data/instanceOf/CustomRectangleWithProp.qml | 6 + tests/auto/qml/qqmllanguage/data/instanceOf/qmldir | 2 + .../qml/qqmllanguage/data/instanceof_qtqml.qml | 13 ++ .../data/instanceof_qtqml_qualified.qml | 13 ++ .../qml/qqmllanguage/data/instanceof_qtquick.qml | 14 ++ .../data/instanceof_qtquick_composite.qml | 26 +++ .../instanceof_qtquick_composite_qualified.qml | 27 +++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 199 ++++++++++++++++++++- 11 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceOf/qmldir create mode 100644 tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml create mode 100644 tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml (limited to 'tests') diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 91ceed7697..6c9cb331a2 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -8170,6 +8170,8 @@ void tst_qqmlecmascript::stringify_qtbug_50592() QCOMPARE(obj->property("source").toString(), QString::fromLatin1("http://example.org/some_nonexistant_image.png")); } +// Tests for the JS-only instanceof. Tests for the QML extensions for +// instanceof belong in tst_qqmllanguage! void tst_qqmlecmascript::instanceof_data() { QTest::addColumn("setupCode"); diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml new file mode 100644 index 0000000000..f6ec5848c1 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomMouseArea.qml @@ -0,0 +1,6 @@ +import QtQuick 2.6 + +MouseArea { + +} + diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml new file mode 100644 index 0000000000..b3fa43a671 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangle.qml @@ -0,0 +1,4 @@ +import QtQuick 2.6 + +Rectangle { +} diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml new file mode 100644 index 0000000000..cf566b9315 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceOf/CustomRectangleWithProp.qml @@ -0,0 +1,6 @@ +import QtQuick 2.6 + +Rectangle { + property int somethingCustom: 0 +} + diff --git a/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir b/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir new file mode 100644 index 0000000000..144c93d8e3 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceOf/qmldir @@ -0,0 +1,2 @@ +CustomRectangle 1.0 CustomRectangle.qml +CustomMouseArea 1.0 CustomMouseArea.qml diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml new file mode 100644 index 0000000000..d74b172cf8 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml.qml @@ -0,0 +1,13 @@ +import QtQml 2.0 + +QtObject { + id: qtobjectInstance + + property Timer aTimer: Timer { + id: timerInstance + } + + property Connections aConnections: Connections { + id: connectionsInstance + } +} diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml new file mode 100644 index 0000000000..a8e303363e --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtqml_qualified.qml @@ -0,0 +1,13 @@ +import QtQml 2.0 as QmlImport + +QmlImport.QtObject { + id: qtobjectInstance + + property QmlImport.Timer aTimer: QmlImport.Timer { + id: timerInstance + } + + property QmlImport.Connections aConnections: QmlImport.Connections { + id: connectionsInstance + } +} diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml new file mode 100644 index 0000000000..9c1808d515 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + id: itemInstance + + Rectangle { + id: rectangleInstance + } + + MouseArea { + id: mouseAreaInstance + } +} + diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml new file mode 100644 index 0000000000..78fc112805 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 +import "instanceOf" + +Item { + id: itemInstance + + Rectangle { + id: rectangleInstance + } + + MouseArea { + id: mouseAreaInstance + } + + CustomRectangle { + id: customRectangleInstance + } + CustomRectangleWithProp { + id: customRectangleWithPropInstance + } + CustomMouseArea { + id: customMouseAreaInstance + } +} + + diff --git a/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml new file mode 100644 index 0000000000..97361b7334 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/instanceof_qtquick_composite_qualified.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 as QuickImport +import "instanceOf" as CustomImport + +QuickImport.Item { + id: itemInstance + + QuickImport.Rectangle { + id: rectangleInstance + } + + QuickImport.MouseArea { + id: mouseAreaInstance + } + + CustomImport.CustomRectangle { + id: customRectangleInstance + } + CustomImport.CustomRectangleWithProp { + id: customRectangleWithPropInstance + } + CustomImport.CustomMouseArea { + id: customMouseAreaInstance + } +} + + + diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 750c32cc3c..e67fa18309 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -263,6 +263,9 @@ private slots: void qmlTypeCanBeResolvedByName_data(); void qmlTypeCanBeResolvedByName(); + void instanceof_data(); + void instanceof(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -309,7 +312,7 @@ private: if (!errorfile) { \ if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \ qWarning() << "Unexpected Errors:" << component.errors(); \ - QVERIFY(!component.isError()); \ + QVERIFY2(!component.isError(), qPrintable(component.errorString())); \ QVERIFY(component.errors().isEmpty()); \ } else { \ DETERMINE_ERRORS(errorfile,expected,actual);\ @@ -4338,6 +4341,200 @@ void tst_qqmllanguage::qmlTypeCanBeResolvedByName() QVERIFY(!o.isNull()); } +// Tests for the QML-only extensions of instanceof. Tests for the regular JS +// instanceof belong in tst_qqmlecmascript! +void tst_qqmllanguage::instanceof_data() +{ + QTest::addColumn("documentToTestIn"); + QTest::addColumn("expectedValue"); + + // so the way this works is that the name of the test tag defines the test + // to run. + // + // the expectedValue is either a boolean true or false for whether the two + // operands are indeed an instanceof each other, or a string for the + // expected error message. + + // assert that basic types don't convert to QObject + QTest::newRow("1 instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + QTest::newRow("true instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + QTest::newRow("\"foobar\" instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + + // assert that Managed don't either + QTest::newRow("new String(\"foobar\") instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + QTest::newRow("new Object() instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + QTest::newRow("new Date() instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant("TypeError: Type error"); + + // test that simple QtQml comparisons work + QTest::newRow("qtobjectInstance instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(true); + QTest::newRow("qtobjectInstance instanceof Timer") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(false); + QTest::newRow("timerInstance instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(true); + QTest::newRow("timerInstance instanceof Timer") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(true); + QTest::newRow("connectionsInstance instanceof QtObject") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(true); + QTest::newRow("connectionsInstance instanceof Timer") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(false); + QTest::newRow("connectionsInstance instanceof Connections") + << testFileUrl("instanceof_qtqml.qml") + << QVariant(true); + + // make sure they still work when imported with a qualifier + QTest::newRow("qtobjectInstance instanceof QmlImport.QtObject") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(true); + QTest::newRow("qtobjectInstance instanceof QmlImport.Timer") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(false); + QTest::newRow("timerInstance instanceof QmlImport.QtObject") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(true); + QTest::newRow("timerInstance instanceof QmlImport.Timer") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(true); + QTest::newRow("connectionsInstance instanceof QmlImport.QtObject") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(true); + QTest::newRow("connectionsInstance instanceof QmlImport.Timer") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(false); + QTest::newRow("connectionsInstance instanceof QmlImport.Connections") + << testFileUrl("instanceof_qtqml_qualified.qml") + << QVariant(true); + + // test that Quick C++ types work ok + QTest::newRow("itemInstance instanceof QtObject") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(true); + QTest::newRow("itemInstance instanceof Timer") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(false); + QTest::newRow("itemInstance instanceof Rectangle") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(false); + QTest::newRow("rectangleInstance instanceof Item") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(true); + QTest::newRow("rectangleInstance instanceof Rectangle") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(true); + QTest::newRow("rectangleInstance instanceof MouseArea") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(false); + QTest::newRow("mouseAreaInstance instanceof Item") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(true); + QTest::newRow("mouseAreaInstance instanceof Rectangle") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(false); + QTest::newRow("mouseAreaInstance instanceof MouseArea") + << testFileUrl("instanceof_qtquick.qml") + << QVariant(true); + + // test that unqualified quick composite types work ok + QTest::newRow("rectangleInstance instanceof CustomRectangle") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(false); + QTest::newRow("customRectangleInstance instanceof Rectangle") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(true); + QTest::newRow("customRectangleInstance instanceof Item") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(true); + QTest::newRow("customRectangleWithPropInstance instanceof CustomRectangleWithProp") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(true); + QTest::newRow("customRectangleWithPropInstance instanceof CustomRectangle") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(false); // ### XXX: QTBUG-58477 + QTest::newRow("customRectangleWithPropInstance instanceof Rectangle") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(true); + QTest::newRow("customRectangleInstance instanceof MouseArea") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(false); + QTest::newRow("customMouseAreaInstance instanceof MouseArea") + << testFileUrl("instanceof_qtquick_composite.qml") + << QVariant(true); + + // test that they still work when qualified + QTest::newRow("rectangleInstance instanceof CustomImport.CustomRectangle") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(false); + QTest::newRow("customRectangleInstance instanceof QuickImport.Rectangle") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(true); + QTest::newRow("customRectangleInstance instanceof QuickImport.Item") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(true); + QTest::newRow("customRectangleWithPropInstance instanceof CustomImport.CustomRectangleWithProp") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(true); + QTest::newRow("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(false); // ### XXX: QTBUG-58477 + QTest::newRow("customRectangleWithPropInstance instanceof QuickImport.Rectangle") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(true); + QTest::newRow("customRectangleInstance instanceof QuickImport.MouseArea") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(false); + QTest::newRow("customMouseAreaInstance instanceof QuickImport.MouseArea") + << testFileUrl("instanceof_qtquick_composite_qualified.qml") + << QVariant(true); +} + +void tst_qqmllanguage::instanceof() +{ + QFETCH(QUrl, documentToTestIn); + QFETCH(QVariant, expectedValue); + + QQmlEngine engine; + QQmlComponent component(&engine, documentToTestIn); + VERIFY_ERRORS(0); + + QScopedPointer o(component.create()); + QVERIFY(o != 0); + + QQmlExpression expr(engine.contextForObject(o.data()), 0, QString::fromLatin1(QTest::currentDataTag())); + QVariant ret = expr.evaluate(); + + if (expectedValue.type() == QVariant::Bool) { + // no error expected + QVERIFY2(!expr.hasError(), qPrintable(expr.error().description())); + bool returnValue = ret.toBool(); + + if (QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomRectangle") || + QTest::currentDataTag() == QLatin1String("customRectangleWithPropInstance instanceof CustomImport.CustomRectangle")) + QEXPECT_FAIL("", "QTBUG-58477: QML type rules are a little lax", Continue); + QCOMPARE(returnValue, expectedValue.toBool()); + } else { + QVERIFY(expr.hasError()); + QCOMPARE(expr.error().description(), expectedValue.toString()); + } +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" -- cgit v1.2.3 From 755250f2f991e81fe092db203f072968c0c8f396 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 14 Mar 2017 11:26:14 -0700 Subject: QHash: use the public functions to set the global hash seed Task-number: QTBUG-47566 Change-Id: I4a7dc1fe14154695b968fffd14abd2e3189c6ad2 Reviewed-by: Simon Hausmann --- tests/auto/qml/v4misc/tst_v4misc.cpp | 10 +++------- tests/manual/scenegraph_lancelot/scenegrabber/main.cpp | 5 ++--- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp index 88b6ae92a8..55a1f65608 100644 --- a/tests/auto/qml/v4misc/tst_v4misc.cpp +++ b/tests/auto/qml/v4misc/tst_v4misc.cpp @@ -26,6 +26,7 @@ ** ****************************************************************************/ +#include #include #define V4_AUTOTEST @@ -46,17 +47,12 @@ private slots: void moveMapping_2(); }; -QT_BEGIN_NAMESPACE -// Avoid QHash randomization so that the temp numbering is stable. -extern Q_CORE_EXPORT QBasicAtomicInt qt_qhash_seed; // from qhash.cpp -QT_END_NAMESPACE - using namespace QT_PREPEND_NAMESPACE(QV4::IR); void tst_v4misc::initTestCase() { - qt_qhash_seed.store(0); - QCOMPARE(qt_qhash_seed.load(), 0); + qSetGlobalQHashSeed(0); + QCOMPARE(qGlobalQHashSeed(), 0); } // split between two ranges diff --git a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp index 886cfc6599..6da0799bbc 100644 --- a/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp +++ b/tests/manual/scenegraph_lancelot/scenegrabber/main.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -134,11 +135,9 @@ private: }; -Q_CORE_EXPORT extern QBasicAtomicInt qt_qhash_seed; - int main(int argc, char *argv[]) { - qt_qhash_seed = 0; + qSetGlobalQHashSeed(0); QGuiApplication a(argc, argv); -- cgit v1.2.3 From 4b445c487d00cc85b01ff92b554e3c1cce2de32d Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 17 Feb 2017 23:57:40 +0100 Subject: QRegExp include cleanup This patch adds missing include statement where the QRegExp class is used. Change-Id: I02d2995dd380f1e4db3777ae9759098c0e7757bd Reviewed-by: Robin Burchell --- tests/benchmarks/qml/holistic/testtypes.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/benchmarks/qml/holistic/testtypes.h b/tests/benchmarks/qml/holistic/testtypes.h index 0736982373..a752a8585b 100644 --- a/tests/benchmarks/qml/holistic/testtypes.h +++ b/tests/benchmarks/qml/holistic/testtypes.h @@ -43,6 +43,7 @@ #include #include #include +#include class MyQmlAttachedObject : public QObject { -- cgit v1.2.3 From 94b52fd93b8ec31981b097af0b29f39b6b294ce7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 14 Mar 2017 15:31:06 +0100 Subject: Protect CompilationUnit member usage against word size differences Currently we only use the runtimeStrings offset in JIT generated code, so move that into a standard layout base class and use that instead. Task-number: QTBUG-58666 Change-Id: Id933ba5df3a6990e89886c2b328e9e814ec5e413 Reviewed-by: Lars Knoll --- tests/auto/toolsupport/tst_toolsupport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/auto/toolsupport/tst_toolsupport.cpp b/tests/auto/toolsupport/tst_toolsupport.cpp index 526ba8f375..6ee1db805a 100644 --- a/tests/auto/toolsupport/tst_toolsupport.cpp +++ b/tests/auto/toolsupport/tst_toolsupport.cpp @@ -101,7 +101,7 @@ void tst_toolsupport::offsets_data() = QTest::newRow("CompiledData::CompilationUnit::data") << pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::data); - data << 8 << 16; + data << 12 << 24; } { @@ -109,7 +109,7 @@ void tst_toolsupport::offsets_data() = QTest::newRow("CompiledData::CompilationUnit::runtimeStrings") << pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::runtimeStrings); - data << 12 << 24; + data << 0 << 0; } { -- cgit v1.2.3 From 59d8fa914d5d72a7973b91e67235e6fdf9686d7d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 13 Mar 2017 18:33:58 +0100 Subject: Remove QSGDistanceFieldGlyphCacheManager After the previous cleanups, it became clear that this didn't serve much of a purpose, so let's remove it and simplify the implementation as a result. Change-Id: Iae2ff9c46762f0c7bdf4225a2c4df93bc8253902 Reviewed-by: Yoann Lopes --- tests/auto/quick/nokeywords/tst_nokeywords.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/quick/nokeywords/tst_nokeywords.cpp b/tests/auto/quick/nokeywords/tst_nokeywords.cpp index ad77743ddd..e6655589a3 100644 --- a/tests/auto/quick/nokeywords/tst_nokeywords.cpp +++ b/tests/auto/quick/nokeywords/tst_nokeywords.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #endif #include #include -- cgit v1.2.3 From db51441a955f63abba41b80198969df38c3d4a10 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 20 Mar 2017 15:39:00 +0100 Subject: Allow info messages in debug message service QtInfoMsg > QtFatalMsg, and it was added later. Change-Id: If565ebd491aba57b162c7f8ddb5534e416f7ab44 Reviewed-by: Simon Hausmann --- .../auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp index 8be82c30f9..f193d3928a 100644 --- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp +++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp @@ -135,7 +135,7 @@ void QQmlDebugMsgClient::messageReceived(const QByteArray &data) QVERIFY(ds.atEnd()); QVERIFY(type >= QtDebugMsg); - QVERIFY(type <= QtFatalMsg); + QVERIFY(type <= QtInfoMsg); QVERIFY(timestamp > 0); LogEntry entry((QtMsgType)type, QString::fromUtf8(message)); -- cgit v1.2.3 From 5bd11b5a8c2f627bc9c9f1b6c02602772ad67dae Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 16 Mar 2017 09:44:50 +0100 Subject: Avoid an extra stat() on the source .qml file when loading cache For timestamp comparison it is not necessary to create another QFileInfo() object and call exists() and lastModified(), when we can pass that information through from the type loader. Change-Id: I225cd36e672f1f390bddb4e6ebfafa3fc1269795 Reviewed-by: Lars Knoll --- tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index b265607fd1..17aa6087d2 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -174,7 +174,7 @@ struct TestCompiler { QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); QQmlRefPointer unit = v4->iselFactory->createUnitForLoading(); - return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), v4->iselFactory.data(), &lastErrorString); + return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath), QFileInfo(testFilePath).lastModified(), v4->iselFactory.data(), &lastErrorString); } void closeMapping() -- cgit v1.2.3 From 3cb86b26e532398d078f9dcb47c4910bb3c777f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Thu, 9 Mar 2017 14:50:58 +0200 Subject: Blacklist a qmltest::ListView test in macOS 10.12 Precise name of blacklisted test: qmltest::ListView::test_listInteractiveCurrentIndexEnforce() Task-number: QTBUG-58971 Change-Id: Iac01f0a5c31c91b08438fd6d7601bdb2ced41ac6 Reviewed-by: Liang Qi --- tests/auto/qmltest/BLACKLIST | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/auto/qmltest/BLACKLIST b/tests/auto/qmltest/BLACKLIST index c38347b42a..d324e9da5d 100644 --- a/tests/auto/qmltest/BLACKLIST +++ b/tests/auto/qmltest/BLACKLIST @@ -9,3 +9,4 @@ linux linux [ListView::test_listInteractiveCurrentIndexEnforce] linux +macos-10.12 -- cgit v1.2.3 From 8bed5de48c3ec24f9ad335e5398d92d0a60c448c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 3 Feb 2017 10:28:28 +0100 Subject: Run ES5 tests on Linux/x86-64 This requires including the test suite as a submodule by default and bumping the module to a new sha1 that removes some particularly long paths. Also force the test suite to run under a US locale, as tests like ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A1_T11 cannot deal with locale dependent output for date formatting. The test harness now returns a non-zero exit code when a test fails. This is used by the QTestLib wrapper to determine success or failure. The tests with JIT are run, but the tests with the interpreter are omitted at the moment until the last failure is fixed. The tests add about 10-15 minutes extra time to the total time it takes to run tests on Linux in the CI. Change-Id: Id01fd3b41350f9c9a6ce9e43236f51f7f0fb71c8 Reviewed-by: Robin Burchell --- tests/auto/qml/ecmascripttests/TestExpectations | 31 ++ tests/auto/qml/ecmascripttests/ecmascripttests.pro | 20 + tests/auto/qml/ecmascripttests/test262 | 1 + tests/auto/qml/ecmascripttests/test262.py | 600 +++++++++++++++++++++ .../qml/ecmascripttests/tst_ecmascripttests.cpp | 77 +++ tests/auto/qml/qml.pro | 3 +- tests/auto/qml/qmlmin/tst_qmlmin.cpp | 1 + tests/manual/v4/TestExpectations | 31 -- tests/manual/v4/test262 | 1 - tests/manual/v4/test262.py | 595 -------------------- tests/manual/v4/tests.pro | 15 - 11 files changed, 732 insertions(+), 643 deletions(-) create mode 100644 tests/auto/qml/ecmascripttests/TestExpectations create mode 100644 tests/auto/qml/ecmascripttests/ecmascripttests.pro create mode 160000 tests/auto/qml/ecmascripttests/test262 create mode 100755 tests/auto/qml/ecmascripttests/test262.py create mode 100644 tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp delete mode 100644 tests/manual/v4/TestExpectations delete mode 160000 tests/manual/v4/test262 delete mode 100755 tests/manual/v4/test262.py delete mode 100644 tests/manual/v4/tests.pro (limited to 'tests') diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations new file mode 100644 index 0000000000..49f107452a --- /dev/null +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -0,0 +1,31 @@ +# wrong tests +# uses octal number +15.2.3.6-2-17-1 failing + +# these fail after the update to Unicode 6.3. +# the reason is that u+180e changed type from whitespace to control +S9.3.1_A2 +S9.3.1_A3_T1 +S9.3.1_A3_T2 +S15.1.2.2_A2_T10 +S15.1.2.3_A2_T10 +15.5.4.20-3-2 +15.5.4.20-3-3 +15.5.4.20-3-4 +15.5.4.20-3-5 +15.5.4.20-3-6 + +10.4.3-1-106 failing +11.2.3-3_3 failing +S13_A15_T4 failing +S15.4.4.3_A1_T1 failing +S15.4.4.3_A3_T1 failing +S15.5.4.11_A5_T1 failing +S15.2.4.4_A14 failing + +# Function declarations in conditionals. We allow them, because the real +# world requires them. +Sbp_12.5_A9_T3 failing +Sbp_12.6.1_A13_T3 failing +Sbp_12.6.2_A13_T3 failing +Sbp_12.6.4_A13_T3 failing diff --git a/tests/auto/qml/ecmascripttests/ecmascripttests.pro b/tests/auto/qml/ecmascripttests/ecmascripttests.pro new file mode 100644 index 0000000000..6d3ee12307 --- /dev/null +++ b/tests/auto/qml/ecmascripttests/ecmascripttests.pro @@ -0,0 +1,20 @@ +CONFIG += testcase +TARGET = tst_ecmascripttests +QT += testlib +macos:CONFIG -= app_bundle +SOURCES += tst_ecmascripttests.cpp +DEFINES += SRCDIR=\\\"$$PWD\\\" + +TESTSCRIPT=$$PWD/test262.py +isEmpty(V4CMD): V4CMD = qmljs + +checkjittarget.target = check-jit +checkjittarget.commands = python $$TESTSCRIPT --command=$$V4CMD --parallel --with-test-expectations --update-expectations +checkjittarget.depends = all +QMAKE_EXTRA_TARGETS += checkjittarget + +checkmothtarget.target = check-interpreter +checkmothtarget.commands = python $$TESTSCRIPT --command=\"$$V4CMD --interpret\" --parallel --with-test-expectations +checkmothtarget.depends = all +QMAKE_EXTRA_TARGETS += checkmothtarget + diff --git a/tests/auto/qml/ecmascripttests/test262 b/tests/auto/qml/ecmascripttests/test262 new file mode 160000 index 0000000000..d60c4ed97e --- /dev/null +++ b/tests/auto/qml/ecmascripttests/test262 @@ -0,0 +1 @@ +Subproject commit d60c4ed97e69639bc5bc1db43a98828debf80c8a diff --git a/tests/auto/qml/ecmascripttests/test262.py b/tests/auto/qml/ecmascripttests/test262.py new file mode 100755 index 0000000000..99f029cffd --- /dev/null +++ b/tests/auto/qml/ecmascripttests/test262.py @@ -0,0 +1,600 @@ +#!/usr/bin/env python +############################################################################# +## +## Copyright (C) 2015 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the test suite module 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 The Qt Company Ltd 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$ +## +############################################################################# + +# Copyright 2009 the Sputnik authors. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +# This is derived from sputnik.py, the Sputnik console test runner, +# with elements from packager.py, which is separately +# copyrighted. TODO: Refactor so there is less duplication between +# test262.py and packager.py. + +import sys +from os import path +rootDir = path.dirname(path.realpath(__file__)) +sys.path.insert(0, path.abspath(rootDir + "/test262/tools/packaging")) + +import logging +import optparse +import os +import platform +import re +import subprocess +import tempfile +import time +import xml.dom.minidom +import datetime +import shutil +import json +import stat +import multiprocessing +import signal + + +from parseTestRecord import parseTestRecord, stripHeader + +from packagerConfig import * + +# ############# Helpers needed for parallel multi-process test execution ############ + +def runTest(case, args): + return case.Run(args) + +def runTestVarArgs(args): + return runTest(*args) + +def initWorkerProcess(): + signal.signal(signal.SIGINT, signal.SIG_IGN) + +# ############# + +class Test262Error(Exception): + def __init__(self, message): + self.message = message + +def ReportError(s): + raise Test262Error(s) + + +class TestExpectations: + def __init__(self, enabled): + self.testsToSkip = [] + self.failingTests = [] + f = open(rootDir + "/TestExpectations") + if not enabled: + return + for line in f.read().splitlines(): + line = line.strip() + if len(line) == 0 or line[0] == "#": + continue + record = line.split() + if len(record) == 1: + self.testsToSkip.append(record[0]) + else: + test = record[0] + expectation = record[1] + if expectation == "failing": + self.failingTests.append(test) + f.close() + + def update(self, progress): + unexpectedPasses = [c.case.name[-1] for c in progress.failed_tests if c.case.IsNegative()] + + # If a test fails that we expected to fail, then it actually passed unexpectedly. + failures = [c.case.name[-1] for c in progress.failed_tests if not c.case.IsNegative()] + for failure in failures: + if failure in self.failingTests: + unexpectedPasses.append(failure) + + f = open(rootDir + "/TestExpectations") + lines = f.read().splitlines() + oldLen = len(lines) + for result in unexpectedPasses: + expectationLine = result + " failing" + try: + lines.remove(expectationLine) + except ValueError: + pass + + f.close() + if len(lines) != oldLen: + f = open(rootDir + "/TestExpectations", "w") + f.write("\n".join(lines)) + f.close() + print "Changes to TestExpectations written!" + + +if not os.path.exists(EXCLUDED_FILENAME): + print "Cannot generate (JSON) test262 tests without a file," + \ + " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME + sys.exit(1) +EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME) +EXCLUDE_LIST = EXCLUDE_LIST.getElementsByTagName("test") +EXCLUDE_LIST = [x.getAttribute("id") for x in EXCLUDE_LIST] + + +def BuildOptions(): + result = optparse.OptionParser() + result.add_option("--command", default="qmljs", help="The command-line to run") + result.add_option("--tests", default=path.abspath(rootDir + '/test262'), + help="Path to the tests") + result.add_option("--cat", default=False, action="store_true", + help="Print packaged test code that would be run") + result.add_option("--summary", default=True, action="store_true", + help="Print summary after running tests") + result.add_option("--full-summary", default=False, action="store_true", + help="Print summary and test output after running tests") + result.add_option("--strict_only", default=False, action="store_true", + help="Test only strict mode") + result.add_option("--non_strict_only", default=False, action="store_true", + help="Test only non-strict mode") + result.add_option("--parallel", default=False, action="store_true", + help="Run tests in parallel") + result.add_option("--with-test-expectations", default=False, action="store_true", + help="Parse TestExpectations to deal with tests known to fail") + result.add_option("--update-expectations", default=False, action="store_true", + help="Update test expectations fail when a test passes that was expected to fail") + # TODO: Once enough tests are made strict compat, change the default + # to "both" + result.add_option("--unmarked_default", default="non_strict", + help="default mode for tests of unspecified strictness") + return result + + +def ValidateOptions(options): + if not options.command: + ReportError("A --command must be specified.") + if not path.exists(options.tests): + ReportError("Couldn't find test path '%s'" % options.tests) + + +placeHolderPattern = re.compile(r"\{\{(\w+)\}\}") + + +def IsWindows(): + p = platform.system() + return (p == 'Windows') or (p == 'Microsoft') + + +class TempFile(object): + + def __init__(self, suffix="", prefix="tmp", text=False): + self.suffix = suffix + self.prefix = prefix + self.text = text + self.fd = None + self.name = None + self.is_closed = False + self.Open() + + def Open(self): + (self.fd, self.name) = tempfile.mkstemp( + suffix = self.suffix, + prefix = self.prefix, + text = self.text) + + def Write(self, str): + os.write(self.fd, str) + + def Read(self): + f = file(self.name) + result = f.read() + f.close() + return result + + def Close(self): + if not self.is_closed: + self.is_closed = True + os.close(self.fd) + + def Dispose(self): + try: + self.Close() + os.unlink(self.name) + except OSError, e: + logging.error("Error disposing temp file: %s", str(e)) + + +class TestResult(object): + + def __init__(self, exit_code, stdout, stderr, case): + self.exit_code = exit_code + self.stdout = stdout + self.stderr = stderr + self.case = case + + def ReportOutcome(self, long_format): + name = self.case.GetName() + mode = self.case.GetMode() + if self.HasUnexpectedOutcome(): + if self.case.IsNegative(): + print "=== %s was expected to fail in %s, but didn't ===" % (name, mode) + else: + if long_format: + print "=== %s failed in %s ===" % (name, mode) + else: + print "%s in %s: " % (name, mode) + out = self.stdout.strip() + if len(out) > 0: + print "--- output ---" + print out + err = self.stderr.strip() + if len(err) > 0: + print "--- errors ---" + print err + if long_format: + print "===" + elif self.case.IsNegative(): + print "%s failed in %s as expected" % (name, mode) + else: + print "%s passed in %s" % (name, mode) + + def HasFailed(self): + return self.exit_code != 0 + + def HasUnexpectedOutcome(self): + if self.case.IsNegative(): + return not self.HasFailed() + else: + return self.HasFailed() + + +class TestCase(object): + + def __init__(self, suite, name, full_path, strict_mode): + self.suite = suite + self.name = name + self.full_path = full_path + self.strict_mode = strict_mode + f = open(self.full_path) + self.contents = f.read() + f.close() + testRecord = parseTestRecord(self.contents, name) + self.test = testRecord["test"] + del testRecord["test"] + del testRecord["header"] + del testRecord["commentary"] + self.testRecord = testRecord; + + + def GetName(self): + return path.join(*self.name) + + def GetMode(self): + if self.strict_mode: + return "strict mode" + else: + return "non-strict mode" + + def GetPath(self): + return self.name + + def NegateResult(self): + if self.IsNegative(): + del self.testRecord['negative'] + else: + self.testRecord['negative'] = "Some failure"; + + def IsNegative(self): + return 'negative' in self.testRecord + + def IsOnlyStrict(self): + return 'onlyStrict' in self.testRecord + + def IsNoStrict(self): + return 'noStrict' in self.testRecord + + def GetSource(self): + # "var testDescrip = " + str(self.testRecord) + ';\n\n' + \ + source = self.suite.GetInclude("cth.js") + \ + self.suite.GetInclude("sta.js") + \ + self.suite.GetInclude("ed.js") + \ + self.suite.GetInclude("testBuiltInObject.js") + \ + self.suite.GetInclude("testIntl.js") + \ + self.test + '\n' + + if self.strict_mode: + source = '"use strict";\nvar strict_mode = true;\n' + source + else: + source = "var strict_mode = false; \n" + source + return source + + def InstantiateTemplate(self, template, params): + def GetParameter(match): + key = match.group(1) + return params.get(key, match.group(0)) + return placeHolderPattern.sub(GetParameter, template) + + def Execute(self, command): + if IsWindows(): + args = '%s' % command + else: + args = command.split(" ") + stdout = TempFile(prefix="test262-out-") + stderr = TempFile(prefix="test262-err-") + try: + logging.info("exec: %s", str(args)) + process = subprocess.Popen( + args, + shell = IsWindows(), + stdout = stdout.fd, + stderr = stderr.fd + ) + code = process.wait() + out = stdout.Read() + err = stderr.Read() + finally: + stdout.Dispose() + stderr.Dispose() + return (code, out, err) + + def RunTestIn(self, command_template, tmp): + tmp.Write(self.GetSource()) + tmp.Close() + command = self.InstantiateTemplate(command_template, { + 'path': tmp.name + }) + (code, out, err) = self.Execute(command) + return TestResult(code, out, err, self) + + def Run(self, command_template): + tmp = TempFile(suffix=".js", prefix="test262-", text=True) + try: + result = self.RunTestIn(command_template, tmp) + finally: + tmp.Dispose() + return result + + def Print(self): + print self.GetSource() + + +class ProgressIndicator(object): + + def __init__(self, count): + self.count = count + self.succeeded = 0 + self.failed = 0 + self.failed_tests = [] + + def HasRun(self, result): + result.ReportOutcome(True) + if result.HasUnexpectedOutcome(): + self.failed += 1 + self.failed_tests.append(result) + else: + self.succeeded += 1 + + +def MakePlural(n): + if (n == 1): + return (n, "") + else: + return (n, "s") + + +class TestSuite(object): + + def __init__(self, root, strict_only, non_strict_only, unmarked_default, load_expectations): + # TODO: derive from packagerConfig.py + self.test_root = path.join(root, 'test', 'suite') + self.lib_root = path.join(root, 'test', 'harness') + self.strict_only = strict_only + self.non_strict_only = non_strict_only + self.unmarked_default = unmarked_default + self.include_cache = { } + self.expectations = TestExpectations(load_expectations) + + def Validate(self): + if not path.exists(self.test_root): + ReportError("No test repository found") + if not path.exists(self.lib_root): + ReportError("No test library found") + + def IsHidden(self, path): + return path.startswith('.') or path == 'CVS' + + def IsTestCase(self, path): + return path.endswith('.js') + + def ShouldRun(self, rel_path, tests): + if len(tests) == 0: + return True + for test in tests: + if test in rel_path: + return True + return False + + def GetInclude(self, name): + if not name in self.include_cache: + static = path.join(self.lib_root, name) + if path.exists(static): + f = open(static) + contents = stripHeader(f.read()) + contents = re.sub(r'\r\n', '\n', contents) + self.include_cache[name] = contents + "\n" + f.close() + else: + ReportError("Can't find: " + static) + return self.include_cache[name] + + def EnumerateTests(self, tests): + logging.info("Listing tests in %s", self.test_root) + cases = [] + for root, dirs, files in os.walk(self.test_root): + for f in [x for x in dirs if self.IsHidden(x)]: + dirs.remove(f) + dirs.sort() + for f in sorted(files): + if self.IsTestCase(f): + full_path = path.join(root, f) + if full_path.startswith(self.test_root): + rel_path = full_path[len(self.test_root)+1:] + else: + logging.warning("Unexpected path %s", full_path) + rel_path = full_path + if self.ShouldRun(rel_path, tests) and not rel_path.startswith("intl402" + os.sep): + basename = path.basename(full_path)[:-3] + name = rel_path.split(path.sep)[:-1] + [basename] + if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(basename) >= 1: + print 'Excluded: ' + basename + else: + if not self.non_strict_only: + strict_case = TestCase(self, name, full_path, True) + if self.expectations.failingTests.count(basename) >= 1: + strict_case.NegateResult() + if not strict_case.IsNoStrict(): + if strict_case.IsOnlyStrict() or \ + self.unmarked_default in ['both', 'strict']: + cases.append(strict_case) + if not self.strict_only: + non_strict_case = TestCase(self, name, full_path, False) + if self.expectations.failingTests.count(basename) >= 1: + non_strict_case.NegateResult() + if not non_strict_case.IsOnlyStrict(): + if non_strict_case.IsNoStrict() or \ + self.unmarked_default in ['both', 'non_strict']: + cases.append(non_strict_case) + logging.info("Done listing tests") + return cases + + def PrintSummary(self, progress): + print + print "=== Summary ===" + count = progress.count + succeeded = progress.succeeded + failed = progress.failed + print " - Ran %i test%s" % MakePlural(count) + if progress.failed == 0: + print " - All tests succeeded" + else: + percent = ((100.0 * succeeded) / count,) + print " - Passed %i test%s (%.1f%%)" % (MakePlural(succeeded) + percent) + percent = ((100.0 * failed) / count,) + print " - Failed %i test%s (%.1f%%)" % (MakePlural(failed) + percent) + positive = [c for c in progress.failed_tests if not c.case.IsNegative()] + negative = [c for c in progress.failed_tests if c.case.IsNegative()] + if len(positive) > 0: + print + print "Failed tests" + for result in positive: + print " %s in %s" % (result.case.GetName(), result.case.GetMode()) + if len(negative) > 0: + print + print "Expected to fail but passed ---" + for result in negative: + print " %s in %s" % (result.case.GetName(), result.case.GetMode()) + + def PrintFailureOutput(self, progress): + for result in progress.failed_tests: + print + result.ReportOutcome(False) + + def Run(self, command_template, tests, print_summary, full_summary, parallel, update_expectations): + if not "{{path}}" in command_template: + command_template += " {{path}}" + cases = self.EnumerateTests(tests) + if len(cases) == 0: + ReportError("No tests to run") + progress = ProgressIndicator(len(cases)) + + if parallel: + pool = multiprocessing.Pool(processes=multiprocessing.cpu_count(), initializer=initWorkerProcess) + results = pool.imap_unordered(func=runTestVarArgs, iterable=[(case, command_template) for case in cases], chunksize=multiprocessing.cpu_count() * 8) + for result in results: + progress.HasRun(result) + else: + for case in cases: + result = case.Run(command_template) + progress.HasRun(result) + if print_summary: + self.PrintSummary(progress) + if full_summary: + self.PrintFailureOutput(progress) + else: + print + print "Use --full-summary to see output from failed tests" + print + if update_expectations: + self.expectations.update(progress) + return progress.failed == 0 + + def Print(self, tests): + cases = self.EnumerateTests(tests) + if len(cases) > 0: + cases[0].Print() + + +def Main(): + # Some date tests rely on being run in pacific time. + # Uncomment the next line for more logging info. + #logging.basicConfig(level=logging.DEBUG) + os.environ["TZ"] = "PST8PDT" + os.environ["LANG"] = "en_US.UTF-8" + parser = BuildOptions() + (options, args) = parser.parse_args() + ValidateOptions(options) + test_suite = TestSuite(options.tests, + options.strict_only, + options.non_strict_only, + options.unmarked_default, + options.with_test_expectations) + test_suite.Validate() + if options.cat: + test_suite.Print(args) + return 0 + else: + if test_suite.Run(options.command, args, + options.summary or options.full_summary, + options.full_summary, + options.parallel, + options.update_expectations): + return 0 + else: + return 1 + + +if __name__ == '__main__': + try: + sys.exit(Main()) + except Test262Error, e: + print "Error: %s" % e.message + sys.exit(1) diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp new file mode 100644 index 0000000000..2ce0cfe210 --- /dev/null +++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include + +class tst_EcmaScriptTests : public QObject +{ + Q_OBJECT +private slots: + void runTests_data(); + void runTests(); +}; + +void tst_EcmaScriptTests::runTests_data() +{ + QTest::addColumn("qmljsParameter"); + + QTest::newRow("jit") << QStringLiteral("--jit"); + // Not passing yet: QTest::newRow("interpreter") << QStringLiteral("--interpret"); +} + +void tst_EcmaScriptTests::runTests() +{ +#if defined(Q_OS_LINUX) && defined(Q_PROCESSOR_X86_64) + QFETCH(QString, qmljsParameter); + + QProcess process; + process.setProcessChannelMode(QProcess::ForwardedChannels); + process.setWorkingDirectory(QLatin1String(SRCDIR)); + process.setProgram("python"); + process.setArguments(QStringList() << "test262.py" << "--command=" + QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmljs " + qmljsParameter << "--parallel" << "--with-test-expectations"); + + qDebug() << "Going to run" << process.program() << process.arguments() << "in" << process.workingDirectory(); + + process.start(); + QVERIFY(process.waitForStarted()); + const int timeoutInMSecs = 20 * 60 * 1000; + QVERIFY2(process.waitForFinished(timeoutInMSecs), "Tests did not terminate in time -- see output above for details"); + QVERIFY2(process.exitStatus() == QProcess::NormalExit, "Running the test harness failed -- see output above for details"); + QVERIFY2(process.exitCode() == 0, "Tests failed -- see output above for details"); +#else + QSKIP("Currently the ecmascript tests are only run on Linux/x86-64"); +#endif +} + +QTEST_MAIN(tst_EcmaScriptTests) + +#include "tst_ecmascripttests.moc" + diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index b347b603bb..a9b18e9f32 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -62,7 +62,8 @@ PRIVATETESTS += \ qqmlimport \ qqmlobjectmodel \ qmldiskcache \ - qv4mm + qv4mm \ + ecmascripttests qtHaveModule(widgets) { PUBLICTESTS += \ diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp index 90868d2ead..171c2bda8a 100644 --- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp +++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp @@ -84,6 +84,7 @@ void tst_qmlmin::initTestCase() excludedDirs << "doc/src/snippets/qtquick1/qtbinding"; excludedDirs << "doc/src/snippets/qtquick1/imports"; excludedDirs << "tests/manual/v4"; + excludedDirs << "tests/auto/qml/ecmascripttests"; excludedDirs << "tests/auto/qml/qmllint"; // Add invalid files (i.e. files with syntax errors) diff --git a/tests/manual/v4/TestExpectations b/tests/manual/v4/TestExpectations deleted file mode 100644 index 49f107452a..0000000000 --- a/tests/manual/v4/TestExpectations +++ /dev/null @@ -1,31 +0,0 @@ -# wrong tests -# uses octal number -15.2.3.6-2-17-1 failing - -# these fail after the update to Unicode 6.3. -# the reason is that u+180e changed type from whitespace to control -S9.3.1_A2 -S9.3.1_A3_T1 -S9.3.1_A3_T2 -S15.1.2.2_A2_T10 -S15.1.2.3_A2_T10 -15.5.4.20-3-2 -15.5.4.20-3-3 -15.5.4.20-3-4 -15.5.4.20-3-5 -15.5.4.20-3-6 - -10.4.3-1-106 failing -11.2.3-3_3 failing -S13_A15_T4 failing -S15.4.4.3_A1_T1 failing -S15.4.4.3_A3_T1 failing -S15.5.4.11_A5_T1 failing -S15.2.4.4_A14 failing - -# Function declarations in conditionals. We allow them, because the real -# world requires them. -Sbp_12.5_A9_T3 failing -Sbp_12.6.1_A13_T3 failing -Sbp_12.6.2_A13_T3 failing -Sbp_12.6.4_A13_T3 failing diff --git a/tests/manual/v4/test262 b/tests/manual/v4/test262 deleted file mode 160000 index 9741ac4655..0000000000 --- a/tests/manual/v4/test262 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9741ac4655808ac46c127e3d1d8ba3d27ada618e diff --git a/tests/manual/v4/test262.py b/tests/manual/v4/test262.py deleted file mode 100755 index 3b5bfa119a..0000000000 --- a/tests/manual/v4/test262.py +++ /dev/null @@ -1,595 +0,0 @@ -#!/usr/bin/env python -############################################################################# -## -## Copyright (C) 2015 The Qt Company Ltd. -## Contact: http://www.qt.io/licensing/ -## -## This file is part of the test suite module 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 The Qt Company Ltd 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$ -## -############################################################################# - -# Copyright 2009 the Sputnik authors. All rights reserved. -# This code is governed by the BSD license found in the LICENSE file. - -# This is derived from sputnik.py, the Sputnik console test runner, -# with elements from packager.py, which is separately -# copyrighted. TODO: Refactor so there is less duplication between -# test262.py and packager.py. - -import sys -from os import path -rootDir = path.dirname(path.realpath(__file__)) -sys.path.insert(0, path.abspath(rootDir + "/test262/tools/packaging")) - -import logging -import optparse -import os -import platform -import re -import subprocess -import tempfile -import time -import xml.dom.minidom -import datetime -import shutil -import json -import stat -import multiprocessing -import signal - - -from parseTestRecord import parseTestRecord, stripHeader - -from packagerConfig import * - -# ############# Helpers needed for parallel multi-process test execution ############ - -def runTest(case, args): - return case.Run(args) - -def runTestVarArgs(args): - return runTest(*args) - -def initWorkerProcess(): - signal.signal(signal.SIGINT, signal.SIG_IGN) - -# ############# - -class Test262Error(Exception): - def __init__(self, message): - self.message = message - -def ReportError(s): - raise Test262Error(s) - - -class TestExpectations: - def __init__(self, enabled): - self.testsToSkip = [] - self.failingTests = [] - f = open(rootDir + "/TestExpectations") - if not enabled: - return - for line in f.read().splitlines(): - line = line.strip() - if len(line) == 0 or line[0] == "#": - continue - record = line.split() - if len(record) == 1: - self.testsToSkip.append(record[0]) - else: - test = record[0] - expectation = record[1] - if expectation == "failing": - self.failingTests.append(test) - f.close() - - def update(self, progress): - unexpectedPasses = [c.case.name[-1] for c in progress.failed_tests if c.case.IsNegative()] - - # If a test fails that we expected to fail, then it actually passed unexpectedly. - failures = [c.case.name[-1] for c in progress.failed_tests if not c.case.IsNegative()] - for failure in failures: - if failure in self.failingTests: - unexpectedPasses.append(failure) - - f = open(rootDir + "/TestExpectations") - lines = f.read().splitlines() - oldLen = len(lines) - for result in unexpectedPasses: - expectationLine = result + " failing" - try: - lines.remove(expectationLine) - except ValueError: - pass - - f.close() - if len(lines) != oldLen: - f = open(rootDir + "/TestExpectations", "w") - f.write("\n".join(lines)) - f.close() - print "Changes to TestExpectations written!" - - -if not os.path.exists(EXCLUDED_FILENAME): - print "Cannot generate (JSON) test262 tests without a file," + \ - " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME - sys.exit(1) -EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME) -EXCLUDE_LIST = EXCLUDE_LIST.getElementsByTagName("test") -EXCLUDE_LIST = [x.getAttribute("id") for x in EXCLUDE_LIST] - - -def BuildOptions(): - result = optparse.OptionParser() - result.add_option("--command", default="qmljs", help="The command-line to run") - result.add_option("--tests", default=path.abspath(rootDir + '/test262'), - help="Path to the tests") - result.add_option("--cat", default=False, action="store_true", - help="Print packaged test code that would be run") - result.add_option("--summary", default=True, action="store_true", - help="Print summary after running tests") - result.add_option("--full-summary", default=False, action="store_true", - help="Print summary and test output after running tests") - result.add_option("--strict_only", default=False, action="store_true", - help="Test only strict mode") - result.add_option("--non_strict_only", default=False, action="store_true", - help="Test only non-strict mode") - result.add_option("--parallel", default=False, action="store_true", - help="Run tests in parallel") - result.add_option("--with-test-expectations", default=False, action="store_true", - help="Parse TestExpectations to deal with tests known to fail") - result.add_option("--update-expectations", default=False, action="store_true", - help="Update test expectations fail when a test passes that was expected to fail") - # TODO: Once enough tests are made strict compat, change the default - # to "both" - result.add_option("--unmarked_default", default="non_strict", - help="default mode for tests of unspecified strictness") - return result - - -def ValidateOptions(options): - if not options.command: - ReportError("A --command must be specified.") - if not path.exists(options.tests): - ReportError("Couldn't find test path '%s'" % options.tests) - - -placeHolderPattern = re.compile(r"\{\{(\w+)\}\}") - - -def IsWindows(): - p = platform.system() - return (p == 'Windows') or (p == 'Microsoft') - - -class TempFile(object): - - def __init__(self, suffix="", prefix="tmp", text=False): - self.suffix = suffix - self.prefix = prefix - self.text = text - self.fd = None - self.name = None - self.is_closed = False - self.Open() - - def Open(self): - (self.fd, self.name) = tempfile.mkstemp( - suffix = self.suffix, - prefix = self.prefix, - text = self.text) - - def Write(self, str): - os.write(self.fd, str) - - def Read(self): - f = file(self.name) - result = f.read() - f.close() - return result - - def Close(self): - if not self.is_closed: - self.is_closed = True - os.close(self.fd) - - def Dispose(self): - try: - self.Close() - os.unlink(self.name) - except OSError, e: - logging.error("Error disposing temp file: %s", str(e)) - - -class TestResult(object): - - def __init__(self, exit_code, stdout, stderr, case): - self.exit_code = exit_code - self.stdout = stdout - self.stderr = stderr - self.case = case - - def ReportOutcome(self, long_format): - name = self.case.GetName() - mode = self.case.GetMode() - if self.HasUnexpectedOutcome(): - if self.case.IsNegative(): - print "=== %s was expected to fail in %s, but didn't ===" % (name, mode) - else: - if long_format: - print "=== %s failed in %s ===" % (name, mode) - else: - print "%s in %s: " % (name, mode) - out = self.stdout.strip() - if len(out) > 0: - print "--- output ---" - print out - err = self.stderr.strip() - if len(err) > 0: - print "--- errors ---" - print err - if long_format: - print "===" - elif self.case.IsNegative(): - print "%s failed in %s as expected" % (name, mode) - else: - print "%s passed in %s" % (name, mode) - - def HasFailed(self): - return self.exit_code != 0 - - def HasUnexpectedOutcome(self): - if self.case.IsNegative(): - return not self.HasFailed() - else: - return self.HasFailed() - - -class TestCase(object): - - def __init__(self, suite, name, full_path, strict_mode): - self.suite = suite - self.name = name - self.full_path = full_path - self.strict_mode = strict_mode - f = open(self.full_path) - self.contents = f.read() - f.close() - testRecord = parseTestRecord(self.contents, name) - self.test = testRecord["test"] - del testRecord["test"] - del testRecord["header"] - del testRecord["commentary"] - self.testRecord = testRecord; - - - def GetName(self): - return path.join(*self.name) - - def GetMode(self): - if self.strict_mode: - return "strict mode" - else: - return "non-strict mode" - - def GetPath(self): - return self.name - - def NegateResult(self): - if self.IsNegative(): - del self.testRecord['negative'] - else: - self.testRecord['negative'] = "Some failure"; - - def IsNegative(self): - return 'negative' in self.testRecord - - def IsOnlyStrict(self): - return 'onlyStrict' in self.testRecord - - def IsNoStrict(self): - return 'noStrict' in self.testRecord - - def GetSource(self): - # "var testDescrip = " + str(self.testRecord) + ';\n\n' + \ - source = self.suite.GetInclude("cth.js") + \ - self.suite.GetInclude("sta.js") + \ - self.suite.GetInclude("ed.js") + \ - self.suite.GetInclude("testBuiltInObject.js") + \ - self.suite.GetInclude("testIntl.js") + \ - self.test + '\n' - - if self.strict_mode: - source = '"use strict";\nvar strict_mode = true;\n' + source - else: - source = "var strict_mode = false; \n" + source - return source - - def InstantiateTemplate(self, template, params): - def GetParameter(match): - key = match.group(1) - return params.get(key, match.group(0)) - return placeHolderPattern.sub(GetParameter, template) - - def Execute(self, command): - if IsWindows(): - args = '%s' % command - else: - args = command.split(" ") - stdout = TempFile(prefix="test262-out-") - stderr = TempFile(prefix="test262-err-") - try: - logging.info("exec: %s", str(args)) - process = subprocess.Popen( - args, - shell = IsWindows(), - stdout = stdout.fd, - stderr = stderr.fd - ) - code = process.wait() - out = stdout.Read() - err = stderr.Read() - finally: - stdout.Dispose() - stderr.Dispose() - return (code, out, err) - - def RunTestIn(self, command_template, tmp): - tmp.Write(self.GetSource()) - tmp.Close() - command = self.InstantiateTemplate(command_template, { - 'path': tmp.name - }) - (code, out, err) = self.Execute(command) - return TestResult(code, out, err, self) - - def Run(self, command_template): - tmp = TempFile(suffix=".js", prefix="test262-", text=True) - try: - result = self.RunTestIn(command_template, tmp) - finally: - tmp.Dispose() - return result - - def Print(self): - print self.GetSource() - - -class ProgressIndicator(object): - - def __init__(self, count): - self.count = count - self.succeeded = 0 - self.failed = 0 - self.failed_tests = [] - - def HasRun(self, result): - result.ReportOutcome(True) - if result.HasUnexpectedOutcome(): - self.failed += 1 - self.failed_tests.append(result) - else: - self.succeeded += 1 - - -def MakePlural(n): - if (n == 1): - return (n, "") - else: - return (n, "s") - - -class TestSuite(object): - - def __init__(self, root, strict_only, non_strict_only, unmarked_default, load_expectations): - # TODO: derive from packagerConfig.py - self.test_root = path.join(root, 'test', 'suite') - self.lib_root = path.join(root, 'test', 'harness') - self.strict_only = strict_only - self.non_strict_only = non_strict_only - self.unmarked_default = unmarked_default - self.include_cache = { } - self.expectations = TestExpectations(load_expectations) - - def Validate(self): - if not path.exists(self.test_root): - ReportError("No test repository found") - if not path.exists(self.lib_root): - ReportError("No test library found") - - def IsHidden(self, path): - return path.startswith('.') or path == 'CVS' - - def IsTestCase(self, path): - return path.endswith('.js') - - def ShouldRun(self, rel_path, tests): - if len(tests) == 0: - return True - for test in tests: - if test in rel_path: - return True - return False - - def GetInclude(self, name): - if not name in self.include_cache: - static = path.join(self.lib_root, name) - if path.exists(static): - f = open(static) - contents = stripHeader(f.read()) - contents = re.sub(r'\r\n', '\n', contents) - self.include_cache[name] = contents + "\n" - f.close() - else: - ReportError("Can't find: " + static) - return self.include_cache[name] - - def EnumerateTests(self, tests): - logging.info("Listing tests in %s", self.test_root) - cases = [] - for root, dirs, files in os.walk(self.test_root): - for f in [x for x in dirs if self.IsHidden(x)]: - dirs.remove(f) - dirs.sort() - for f in sorted(files): - if self.IsTestCase(f): - full_path = path.join(root, f) - if full_path.startswith(self.test_root): - rel_path = full_path[len(self.test_root)+1:] - else: - logging.warning("Unexpected path %s", full_path) - rel_path = full_path - if self.ShouldRun(rel_path, tests) and not rel_path.startswith("intl402" + os.sep): - basename = path.basename(full_path)[:-3] - name = rel_path.split(path.sep)[:-1] + [basename] - if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(basename) >= 1: - print 'Excluded: ' + basename - else: - if not self.non_strict_only: - strict_case = TestCase(self, name, full_path, True) - if self.expectations.failingTests.count(basename) >= 1: - strict_case.NegateResult() - if not strict_case.IsNoStrict(): - if strict_case.IsOnlyStrict() or \ - self.unmarked_default in ['both', 'strict']: - cases.append(strict_case) - if not self.strict_only: - non_strict_case = TestCase(self, name, full_path, False) - if self.expectations.failingTests.count(basename) >= 1: - non_strict_case.NegateResult() - if not non_strict_case.IsOnlyStrict(): - if non_strict_case.IsNoStrict() or \ - self.unmarked_default in ['both', 'non_strict']: - cases.append(non_strict_case) - logging.info("Done listing tests") - return cases - - def PrintSummary(self, progress): - print - print "=== Summary ===" - count = progress.count - succeeded = progress.succeeded - failed = progress.failed - print " - Ran %i test%s" % MakePlural(count) - if progress.failed == 0: - print " - All tests succeeded" - else: - percent = ((100.0 * succeeded) / count,) - print " - Passed %i test%s (%.1f%%)" % (MakePlural(succeeded) + percent) - percent = ((100.0 * failed) / count,) - print " - Failed %i test%s (%.1f%%)" % (MakePlural(failed) + percent) - positive = [c for c in progress.failed_tests if not c.case.IsNegative()] - negative = [c for c in progress.failed_tests if c.case.IsNegative()] - if len(positive) > 0: - print - print "Failed tests" - for result in positive: - print " %s in %s" % (result.case.GetName(), result.case.GetMode()) - if len(negative) > 0: - print - print "Expected to fail but passed ---" - for result in negative: - print " %s in %s" % (result.case.GetName(), result.case.GetMode()) - - def PrintFailureOutput(self, progress): - for result in progress.failed_tests: - print - result.ReportOutcome(False) - - def Run(self, command_template, tests, print_summary, full_summary, parallel, update_expectations): - if not "{{path}}" in command_template: - command_template += " {{path}}" - cases = self.EnumerateTests(tests) - if len(cases) == 0: - ReportError("No tests to run") - progress = ProgressIndicator(len(cases)) - - if parallel: - pool = multiprocessing.Pool(processes=multiprocessing.cpu_count(), initializer=initWorkerProcess) - results = pool.imap_unordered(func=runTestVarArgs, iterable=[(case, command_template) for case in cases], chunksize=multiprocessing.cpu_count() * 8) - for result in results: - progress.HasRun(result) - else: - for case in cases: - result = case.Run(command_template) - progress.HasRun(result) - if print_summary: - self.PrintSummary(progress) - if full_summary: - self.PrintFailureOutput(progress) - else: - print - print "Use --full-summary to see output from failed tests" - print - if update_expectations: - self.expectations.update(progress) - - def Print(self, tests): - cases = self.EnumerateTests(tests) - if len(cases) > 0: - cases[0].Print() - - -def Main(): - # Some date tests rely on being run in pacific time. - # Uncomment the next line for more logging info. - #logging.basicConfig(level=logging.DEBUG) - os.environ["TZ"] = "PST8PDT" - parser = BuildOptions() - (options, args) = parser.parse_args() - ValidateOptions(options) - test_suite = TestSuite(options.tests, - options.strict_only, - options.non_strict_only, - options.unmarked_default, - options.with_test_expectations) - test_suite.Validate() - if options.cat: - test_suite.Print(args) - else: - test_suite.Run(options.command, args, - options.summary or options.full_summary, - options.full_summary, - options.parallel, - options.update_expectations) - - -if __name__ == '__main__': - try: - Main() - sys.exit(0) - except Test262Error, e: - print "Error: %s" % e.message - sys.exit(1) diff --git a/tests/manual/v4/tests.pro b/tests/manual/v4/tests.pro deleted file mode 100644 index ce4a34f7a0..0000000000 --- a/tests/manual/v4/tests.pro +++ /dev/null @@ -1,15 +0,0 @@ -TEMPLATE = aux - -TESTSCRIPT=$$PWD/test262.py -isEmpty(V4CMD): V4CMD = qmljs - -checktarget.target = check -checktarget.commands = python $$TESTSCRIPT --command=$$V4CMD --parallel --with-test-expectations --update-expectations -checktarget.depends = all -QMAKE_EXTRA_TARGETS += checktarget - -checkmothtarget.target = check-interpreter -checkmothtarget.commands = python $$TESTSCRIPT --command=\"$$V4CMD --interpret\" --parallel --with-test-expectations -checkmothtarget.depends = all -QMAKE_EXTRA_TARGETS += checkmothtarget - -- cgit v1.2.3 From 09a62428cfdb1ced3767f38aba126cf466e37e30 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 24 Mar 2017 15:50:42 +0100 Subject: tst_qquickflickable: clean up touch event handling Use QTest::createTouchDevice now that it exists. No need for each test to create a device and pass it in to flickWithTouch Change-Id: I81131a13aaba01cfa0f04b25f334c80263625d12 Reviewed-by: Robin Burchell --- .../quick/qquickflickable/tst_qquickflickable.cpp | 26 ++++++++-------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 9ead271bfe..21d02ff5de 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -50,6 +50,9 @@ class tst_qquickflickable : public QQmlDataTest { Q_OBJECT public: + tst_qquickflickable() + : touchDevice(QTest::createTouchDevice()) + {} private slots: void create(); @@ -101,7 +104,8 @@ private slots: void overshoot_reentrant(); private: - void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to); + void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); + QTouchDevice *touchDevice; }; void tst_qquickflickable::cleanup() @@ -1530,12 +1534,6 @@ void tst_qquickflickable::clickAndDragWhenTransformed() void tst_qquickflickable::flickTwiceUsingTouches() { - QTouchDevice *touchDevice = new QTouchDevice; - touchDevice->setName("Fake Touchscreen"); - touchDevice->setType(QTouchDevice::TouchScreen); - touchDevice->setCapabilities(QTouchDevice::Position); - QWindowSystemInterface::registerTouchDevice(touchDevice); - QScopedPointer window(new QQuickView); window->setSource(testFileUrl("longList.qml")); QTRY_COMPARE(window->status(), QQuickView::Ready); @@ -1548,7 +1546,7 @@ void tst_qquickflickable::flickTwiceUsingTouches() QVERIFY(flickable != 0); QCOMPARE(flickable->contentY(), 0.0f); - flickWithTouch(window.data(), touchDevice, QPoint(100, 400), QPoint(100, 240)); + flickWithTouch(window.data(), QPoint(100, 400), QPoint(100, 240)); qreal contentYAfterFirstFlick = flickable->contentY(); qDebug() << "contentYAfterFirstFlick " << contentYAfterFirstFlick; @@ -1556,7 +1554,7 @@ void tst_qquickflickable::flickTwiceUsingTouches() // Wait until view stops moving QTRY_VERIFY(!flickable->isMoving()); - flickWithTouch(window.data(), touchDevice, QPoint(100, 400), QPoint(100, 240)); + flickWithTouch(window.data(), QPoint(100, 400), QPoint(100, 240)); // In the original bug, that second flick would cause Flickable to halt immediately qreal contentYAfterSecondFlick = flickable->contentY(); @@ -1564,7 +1562,7 @@ void tst_qquickflickable::flickTwiceUsingTouches() QTRY_VERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f)); } -void tst_qquickflickable::flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to) +void tst_qquickflickable::flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to) { QTest::touchEvent(window, touchDevice).press(0, from, window); QQuickTouchUtils::flush(window); @@ -1869,12 +1867,6 @@ void tst_qquickflickable::stopAtBounds() void tst_qquickflickable::nestedMouseAreaUsingTouch() { - QTouchDevice *touchDevice = new QTouchDevice; - touchDevice->setName("Fake Touchscreen"); - touchDevice->setType(QTouchDevice::TouchScreen); - touchDevice->setCapabilities(QTouchDevice::Position); - QWindowSystemInterface::registerTouchDevice(touchDevice); - QScopedPointer window(new QQuickView); window->setSource(testFileUrl("nestedmousearea.qml")); QTRY_COMPARE(window->status(), QQuickView::Ready); @@ -1887,7 +1879,7 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch() QVERIFY(flickable != 0); QCOMPARE(flickable->contentY(), 50.0f); - flickWithTouch(window.data(), touchDevice, QPoint(100, 300), QPoint(100, 200)); + flickWithTouch(window.data(), QPoint(100, 300), QPoint(100, 200)); // flickable should not have moved QCOMPARE(flickable->contentY(), 50.0); -- cgit v1.2.3 From 1f9c7b065f55f80f81b349ef64a718546dec4b49 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 24 Mar 2017 15:59:28 +0100 Subject: Add tst_qquickflickable::nestedSliderUsingTouch to verify that when a touch-handling component is inside the Flickable, it can control whether the flickable can steal the grab by means of setKeepTouchGrab. Task-number: QTBUG-59416 Task-number: QTBUG-59707 Change-Id: I93cf3abb07a96a69290c3b5b055b688a62fe8fff Reviewed-by: J-P Nurmi --- .../quick/qquickflickable/data/nestedSlider.qml | 36 +++++ .../quick/qquickflickable/tst_qquickflickable.cpp | 161 +++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 tests/auto/quick/qquickflickable/data/nestedSlider.qml (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/data/nestedSlider.qml b/tests/auto/quick/qquickflickable/data/nestedSlider.qml new file mode 100644 index 0000000000..2fd0cbfcc8 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/nestedSlider.qml @@ -0,0 +1,36 @@ +import QtQuick 2.0 +import Test 1.0 + +Flickable { + width: 240 + height: 320 + contentWidth: width * 1.5 + contentHeight: height * 1.5 + contentY: height * 0.25 + + Rectangle { + id: slider + width: 50 + height: 200 + color: "lightgray" + border.color: drag.active ? "green" : "black" + anchors.centerIn: parent + radius: 4 + + TouchDragArea { + id: drag + objectName: "drag" + anchors.fill: parent + } + + Rectangle { + width: parent.width - 2 + height: 20 + radius: 5 + color: "darkgray" + border.color: "black" + x: 1 + y: Math.min(slider.height - height, Math.max(0, drag.pos.y - height / 2)) + } + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 21d02ff5de..3ecebfb48f 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -46,6 +46,99 @@ using namespace QQuickViewTestUtil; using namespace QQuickVisualTestUtil; +// an abstract Slider which only handles touch events +class TouchDragArea : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos NOTIFY posChanged) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) + Q_PROPERTY(bool keepMouseGrab READ keepMouseGrab WRITE setKeepMouseGrab NOTIFY keepMouseGrabChanged) + Q_PROPERTY(bool keepTouchGrab READ keepTouchGrab WRITE setKeepTouchGrab NOTIFY keepTouchGrabChanged) + +public: + TouchDragArea(QQuickItem *parent = 0) + : QQuickItem(parent) + , touchEvents(0) + , touchUpdates(0) + , touchReleases(0) + , ungrabs(0) + , m_active(false) + { + setFlags(ItemAcceptsDrops); + } + + QPointF pos() const { return m_pos; } + + bool active() const { return m_active; } + + void setKeepMouseGrab(bool keepMouseGrab) + { + QQuickItem::setKeepMouseGrab(keepMouseGrab); + emit keepMouseGrabChanged(); + } + + void setKeepTouchGrab(bool keepTouchGrab) + { + QQuickItem::setKeepTouchGrab(keepTouchGrab); + emit keepTouchGrabChanged(); + } + + int touchEvents; + int touchUpdates; + int touchReleases; + int ungrabs; + QVector touchPointStates; + +protected: + void touchEvent(QTouchEvent *ev) override + { + QCOMPARE(ev->touchPoints().count(), 1); + auto touchpoint = ev->touchPoints().first(); + switch (touchpoint.state()) { + case Qt::TouchPointPressed: + QVERIFY(!m_active); + m_active = true; + emit activeChanged(); + grabTouchPoints(QVector() << touchpoint.id()); + break; + case Qt::TouchPointMoved: + ++touchUpdates; + break; + case Qt::TouchPointReleased: + QVERIFY(m_active); + m_active = false; + ++touchReleases; + emit activeChanged(); + case Qt::TouchPointStationary: + break; + } + touchPointStates << touchpoint.state(); + ++touchEvents; + m_pos = touchpoint.pos(); + emit posChanged(); + } + + void touchUngrabEvent() override + { + ++ungrabs; + QVERIFY(m_active); + emit ungrabbed(); + m_active = false; + emit activeChanged(); + } + +signals: + void ungrabbed(); + void posChanged(); + void keepMouseGrabChanged(); + void keepTouchGrabChanged(); + void activeChanged(); + +private: + QPointF m_pos; + bool m_active; +}; + class tst_qquickflickable : public QQmlDataTest { Q_OBJECT @@ -55,6 +148,7 @@ public: {} private slots: + void initTestCase() override; void create(); void horizontalViewportSize(); void verticalViewportSize(); @@ -92,6 +186,8 @@ private slots: void stopAtBounds(); void stopAtBounds_data(); void nestedMouseAreaUsingTouch(); + void nestedSliderUsingTouch(); + void nestedSliderUsingTouch_data(); void pressDelayWithLoader(); void movementFromProgrammaticFlick(); void cleanup(); @@ -108,6 +204,12 @@ private: QTouchDevice *touchDevice; }; +void tst_qquickflickable::initTestCase() +{ + QQmlDataTest::initTestCase(); + qmlRegisterType("Test",1,0,"TouchDragArea"); +} + void tst_qquickflickable::cleanup() { QVERIFY(QGuiApplication::topLevelWindows().isEmpty()); @@ -1889,6 +1991,65 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch() QVERIFY(nested->y() < 100.0); } +void tst_qquickflickable::nestedSliderUsingTouch_data() +{ + QTest::addColumn("keepMouseGrab"); + QTest::addColumn("keepTouchGrab"); + QTest::addColumn("updates"); + QTest::addColumn("releases"); + QTest::addColumn("ungrabs"); + + QTest::newRow("keepBoth") << true << true << 8 << 1 << 0; + QTest::newRow("keepMouse") << true << false << 8 << 1 << 0; + QTest::newRow("keepTouch") << false << true << 8 << 1 << 0; + QTest::newRow("keepNeither") << false << false << 6 << 0 << 1; +} + +void tst_qquickflickable::nestedSliderUsingTouch() +{ + QFETCH(bool, keepMouseGrab); + QFETCH(bool, keepTouchGrab); + QFETCH(int, updates); + QFETCH(int, releases); + QFETCH(int, ungrabs); + + QQuickView *window = new QQuickView; + QScopedPointer windowPtr(window); + windowPtr->setSource(testFileUrl("nestedSlider.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(window); + QQuickViewTestUtil::moveMouseAway(window); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(window->rootObject() != 0); + + QQuickFlickable *flickable = qobject_cast(window->rootObject()); + QVERIFY(flickable); + + TouchDragArea *tda = flickable->findChild("drag"); + QVERIFY(tda); + + // Drag down and a little to the right: flickable will steal the grab only if tda allows it + const int dragThreshold = qApp->styleHints()->startDragDistance(); + tda->setKeepMouseGrab(keepMouseGrab); + tda->setKeepTouchGrab(keepTouchGrab); + QPoint p0 = tda->mapToScene(QPoint(20, 20)).toPoint(); + QTest::touchEvent(window, touchDevice).press(0, p0, window); + QQuickTouchUtils::flush(window); + for (int i = 0; i < 8; ++i) { + p0 += QPoint(dragThreshold / 6, dragThreshold / 4); + QTest::touchEvent(window, touchDevice).move(0, p0, window); + QQuickTouchUtils::flush(window); + } + QCOMPARE(tda->active(), !ungrabs); + QTest::touchEvent(window, touchDevice).release(0, p0, window); + QQuickTouchUtils::flush(window); + QCOMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed); + QCOMPARE(tda->touchUpdates, updates); + QCOMPARE(tda->touchReleases, releases); + QCOMPARE(tda->ungrabs, ungrabs); +} + // QTBUG-31328 void tst_qquickflickable::pressDelayWithLoader() { -- cgit v1.2.3 From b82d5bb4186952d66ebd4a3f6a21c5d9e8705940 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 29 Mar 2017 08:36:06 +0200 Subject: tst_qquickimage::mirror(): Ensure screenshots are in the correct format Task-number: QTBUG-59787 Change-Id: I9ef1e6e5284cadc37bdac342b02cf93655346d57 Reviewed-by: Shawn Rutledge --- tests/auto/quick/qquickimage/tst_qquickimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 4699f947a1..e439db543f 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -373,7 +373,7 @@ void tst_qquickimage::mirror() } QImage img = expected.toImage(); - QCOMPARE(screenshots[fillMode], img); + QCOMPARE(screenshots[fillMode].convertToFormat(img.format()), img); } } -- cgit v1.2.3 From 0dbc575c1a8359534761167a5f5f1e29abedd51d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 22 Feb 2017 16:16:14 +0100 Subject: Make keyboard events work in QQuickWidget Right now many cases outside of text input fields are simply broken, e.g. one cannot use a TableView or other controls with the keyboard. Removing the seemingly unnecessary focusObject() solves all problems since this way key events get delivered to the QQuickWidget which in turn forwards to the QQuickWindow. Directly routing into the QQuickWindow's focusObject(), which can be any item in the scene is wrong since it skips a big part of QQuickWindow's event handling logic. Task-number: QTBUG-45757 Change-Id: Ie53b9003d156ab019fa4b9cf461e209990e738f7 Reviewed-by: Paul Olav Tvete --- .../quickwidgets/qquickwidget/tst_qquickwidget.cpp | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'tests') diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index 5e8f762e23..bd051ec990 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -58,6 +58,7 @@ private slots: void grabBeforeShow(); void reparentToNewWindow(); void nullEngine(); + void keyEvents(); }; @@ -337,6 +338,33 @@ void tst_qquickwidget::nullEngine() QVERIFY(widget.engine()); } +class KeyHandlingWidget : public QQuickWidget +{ +public: + void keyPressEvent(QKeyEvent *e) override { + if (e->key() == Qt::Key_A) + ok = true; + } + + bool ok = false; +}; + +void tst_qquickwidget::keyEvents() +{ + // A QQuickWidget should behave like a normal widget when it comes to event handling. + // Verify that key events actually reach the widget. (QTBUG-45757) + KeyHandlingWidget widget; + widget.setSource(testFileUrl("rectangle.qml")); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(widget.window(), 5000)); + + // Note: send the event to the QWindow, not the QWidget, in order + // to simulate the full event processing chain. + QTest::keyClick(widget.window()->windowHandle(), Qt::Key_A); + + QTRY_VERIFY(widget.ok); +} + QTEST_MAIN(tst_qquickwidget) #include "tst_qquickwidget.moc" -- cgit v1.2.3 From ea99d624558437db64e33df476cf7d43bb5c0099 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 29 Mar 2017 13:24:40 +0200 Subject: Minor cleanup: Don't require QtGui for ES6 tests We don't need a QGuiApplication to launch test262.py Change-Id: I3f8e200245a30d88f3c6ff578be414ec76bcfb9c Reviewed-by: Robin Burchell --- tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp index 2ce0cfe210..5d7009e7c8 100644 --- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp +++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp @@ -71,7 +71,7 @@ void tst_EcmaScriptTests::runTests() #endif } -QTEST_MAIN(tst_EcmaScriptTests) +QTEST_GUILESS_MAIN(tst_EcmaScriptTests) #include "tst_ecmascripttests.moc" -- cgit v1.2.3 From 44900962268c50aa1f9823e71d5b75cfa9e7ea4f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 29 Mar 2017 10:27:15 +0200 Subject: Restrict automated tests on Boot2Qt to non-graphical tests This allows us to enable running of some of the tests in the CI and gives us test coverage for some important architecture specific aspects of the engine. Graphical tests are omitted at the moment as well as a few other tests (such as ES6 suite), that will be added incrementally. This change is just an enabler. Once in place tests can be enabled in qt5.git's platform_configs. Change-Id: I9179aaf1fe12f4423833379b97d16b711c57f39b Reviewed-by: Sami Nurmenniemi Reviewed-by: Lars Knoll --- tests/auto/auto.pro | 3 +++ tests/auto/qml/qml.pro | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 1e80f1bf65..f9c1fcce91 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -18,4 +18,7 @@ qtHaveModule(gui):qtConfig(opengl(es1|es2)?) { # console applications not supported uikit: SUBDIRS -= qmltest +# Restricted sub-set for now +boot2qt: SUBDIRS = qml + installed_cmake.depends = cmake diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index a9b18e9f32..007eb0dc83 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -7,6 +7,9 @@ PUBLICTESTS += \ parserstress \ qjsvalueiterator \ qjsonbinding \ + +!boot2qt { +PUBLICTESTS += \ qmlmin \ qqmlcomponent \ qqmlconsole \ @@ -25,15 +28,21 @@ PUBLICTESTS += \ qquickfolderlistmodel \ qqmlapplicationengine \ qqmlsettings \ - qqmlstatemachine + qqmlstatemachine \ + qmldiskcache +} PRIVATETESTS += \ - animation \ qqmlcpputils \ + qqmldirparser \ + v4misc \ + +!boot2qt { +PRIVATETESTS += \ + animation \ qqmlecmascript \ qqmlcontext \ qqmlexpression \ - qqmldirparser \ qqmlglobal \ qqmllanguage \ qqmlopenmetaobject \ @@ -57,13 +66,12 @@ PRIVATETESTS += \ qqmltimer \ qqmlinstantiator \ qqmlenginecleanup \ - v4misc \ qqmltranslation \ qqmlimport \ qqmlobjectmodel \ - qmldiskcache \ qv4mm \ ecmascripttests +} qtHaveModule(widgets) { PUBLICTESTS += \ @@ -73,7 +81,7 @@ qtHaveModule(widgets) { SUBDIRS += $$PUBLICTESTS SUBDIRS += $$METATYPETESTS -qtConfig(process) { +qtConfig(process):!boot2qt { !contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger SUBDIRS += qmllint qmlplugindump } -- cgit v1.2.3 From 05fc81f720144225a8449b25dc65f8d21a69bbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Wed, 29 Mar 2017 22:31:31 +0300 Subject: Blacklist TextEdit autotests on macOS 10.12 TextEdit::test_textentry and TextEdit::test_textentry_char fail on macOS 10.12. Task-number: QTBUG-58972 Change-Id: I3d9e4db3a3243ab9a5e373c9cdb23200d80232bd Reviewed-by: Liang Qi --- tests/auto/qmltest/BLACKLIST | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests') diff --git a/tests/auto/qmltest/BLACKLIST b/tests/auto/qmltest/BLACKLIST index d324e9da5d..e0a4ce1743 100644 --- a/tests/auto/qmltest/BLACKLIST +++ b/tests/auto/qmltest/BLACKLIST @@ -10,3 +10,7 @@ linux [ListView::test_listInteractiveCurrentIndexEnforce] linux macos-10.12 +[TextEdit::test_textentry] +macos-10.12 +[TextEdit::test_textentry_char] +macos-10.12 -- cgit v1.2.3 From ae0d74fca32aabdd4c268a77654c552baacced69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Thu, 30 Mar 2017 12:08:30 +0300 Subject: Blacklist tst_qquickapplication::active on OS X 10.11 Task-number: QTBUG-58785 Change-Id: I860e99b32275ff618b96fb18e3b76d6bb15d18d4 Reviewed-by: Liang Qi --- tests/auto/quick/qquickapplication/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/quick/qquickapplication/BLACKLIST (limited to 'tests') diff --git a/tests/auto/quick/qquickapplication/BLACKLIST b/tests/auto/quick/qquickapplication/BLACKLIST new file mode 100644 index 0000000000..81592db56f --- /dev/null +++ b/tests/auto/quick/qquickapplication/BLACKLIST @@ -0,0 +1,2 @@ +[active] +osx-10.11 -- cgit v1.2.3 From 9b4d31825e5f76e91af555549223ea6b33dd37e6 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 15 Mar 2017 12:12:22 +0100 Subject: Qml Debugger: Make sure all objects have a type QQmlMetaType::prettyTypeName() does a better job in finding a valid type name for our objects than we can do ourselves. Task-number: QTCREATORBUG-17741 Change-Id: Ie8a192aceb230e73b5295b745987692548aff641 Reviewed-by: Simon Hausmann --- .../tst_qqmlenginedebugservice.cpp | 71 +++++++++++++++++----- .../qml/debugger/shared/qqmlenginedebugclient.cpp | 1 + 2 files changed, 57 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp index 8c30a82317..d9a4777115 100644 --- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp +++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp @@ -180,14 +180,9 @@ void tst_QQmlEngineDebugService::recursiveObjectTest( { const QMetaObject *meta = o->metaObject(); - QQmlType *type = QQmlMetaType::qmlType(meta); - QString className = type ? QString(type->qmlTypeName()) - : QString(meta->className()); - className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1); - QCOMPARE(oref.debugId, QQmlDebugService::idForObject(o)); QCOMPARE(oref.name, o->objectName()); - QCOMPARE(oref.className, className); + QCOMPARE(oref.className, QQmlMetaType::prettyTypeName(o)); QCOMPARE(oref.contextDebugId, QQmlDebugService::idForObject( qmlContext(o))); @@ -201,6 +196,7 @@ void tst_QQmlEngineDebugService::recursiveObjectTest( QmlDebugObjectReference cref; foreach (const QmlDebugObjectReference &ref, oref.children) { + QVERIFY(!ref.className.isEmpty()); if (ref.debugId == debugId) { cref = ref; break; @@ -369,6 +365,7 @@ void tst_QQmlEngineDebugService::setMethodBody() { bool success; QmlDebugObjectReference obj = findRootObject(2); + QVERIFY(!obj.className.isEmpty()); QObject *root = m_components.at(2); // Without args @@ -410,6 +407,7 @@ void tst_QQmlEngineDebugService::setMethodBody() void tst_QQmlEngineDebugService::watch_property() { QmlDebugObjectReference obj = findRootObject(); + QVERIFY(!obj.className.isEmpty()); QmlDebugPropertyReference prop = findProperty(obj.properties, "width"); bool success; @@ -454,6 +452,7 @@ void tst_QQmlEngineDebugService::watch_property() void tst_QQmlEngineDebugService::watch_object() { QmlDebugObjectReference obj = findRootObject(); + QVERIFY(!obj.className.isEmpty()); bool success; @@ -519,6 +518,7 @@ void tst_QQmlEngineDebugService::watch_expression() int origWidth = m_rootItem->property("width").toInt(); QmlDebugObjectReference obj = findRootObject(); + QVERIFY(!obj.className.isEmpty()); bool success; @@ -654,6 +654,7 @@ void tst_QQmlEngineDebugService::queryObject() bool success; QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success); @@ -665,6 +666,7 @@ void tst_QQmlEngineDebugService::queryObject() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); QmlDebugObjectReference obj = m_dbg->object(); + QVERIFY(!obj.className.isEmpty()); // check source as defined in main() QmlDebugFileReference source = obj.source; @@ -676,12 +678,15 @@ void tst_QQmlEngineDebugService::queryObject() recursiveObjectTest(m_rootItem, obj, recursive); if (recursive) { - foreach (const QmlDebugObjectReference &child, obj.children) + foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); QVERIFY(child.properties.count() > 0); + } QmlDebugObjectReference rect; QmlDebugObjectReference text; foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); if (child.className == "Rectangle") rect = child; else if (child.className == "Text") @@ -695,8 +700,10 @@ void tst_QQmlEngineDebugService::queryObject() QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue"))); } else { - foreach (const QmlDebugObjectReference &child, obj.children) + foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); QCOMPARE(child.properties.count(), 0); + } } } @@ -715,6 +722,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation() bool success; QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName(); int lineNumber = rootObject.source.lineNumber; @@ -737,6 +745,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation() QCOMPARE(m_dbg->objects().count(), 1); QmlDebugObjectReference obj = m_dbg->objects().first(); + QVERIFY(!obj.className.isEmpty()); // check source as defined in main() QmlDebugFileReference source = obj.source; @@ -748,12 +757,15 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation() recursiveObjectTest(m_rootItem, obj, recursive); if (recursive) { - foreach (const QmlDebugObjectReference &child, obj.children) + foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); QVERIFY(child.properties.count() > 0); + } QmlDebugObjectReference rect; QmlDebugObjectReference text; foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); if (child.className == "Rectangle") rect = child; else if (child.className == "Text") @@ -767,8 +779,10 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation() QCOMPARE(findProperty(text.properties, "color").value, qVariantFromValue(QColor("blue"))); } else { - foreach (const QmlDebugObjectReference &child, obj.children) + foreach (const QmlDebugObjectReference &child, obj.children) { + QVERIFY(!child.className.isEmpty()); QCOMPARE(child.properties.count(), 0); + } } } @@ -783,6 +797,7 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation_data() void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451() { QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); int contextId = rootObject.contextDebugId; QQmlContext *context = qobject_cast(QQmlDebugService::objectForId(contextId)); QQmlComponent component(context->engine()); @@ -809,6 +824,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); foreach (QmlDebugObjectReference child, rootObject.children) { + QVERIFY(!child.className.isEmpty()); success = false; lineNumber = child.source.lineNumber; columnNumber = child.source.columnNumber; @@ -831,6 +847,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); foreach (QmlDebugObjectReference child, rootObject.children) { + QVERIFY(!child.className.isEmpty()); success = false; lineNumber = child.source.lineNumber; columnNumber = child.source.columnNumber; @@ -846,6 +863,7 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes() bool success; QmlDebugObjectReference rootObject = findRootObject(4, true); + QVERIFY(!rootObject.className.isEmpty()); QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(0); unconnected->queryObject(rootObject, &success); @@ -857,6 +875,7 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); QmlDebugObjectReference obj = m_dbg->object(); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties, "modelIndex").value, QVariant()); } @@ -950,6 +969,7 @@ void tst_QQmlEngineDebugService::queryExpressionResultBC_data() void tst_QQmlEngineDebugService::setBindingForObject() { QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); QVERIFY(rootObject.debugId != -1); QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width"); @@ -967,6 +987,7 @@ void tst_QQmlEngineDebugService::setBindingForObject() QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); widthPropertyRef = findProperty(rootObject.properties, "width"); QCOMPARE(widthPropertyRef.value, QVariant(15)); @@ -982,6 +1003,7 @@ void tst_QQmlEngineDebugService::setBindingForObject() QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); widthPropertyRef = findProperty(rootObject.properties, "width"); QCOMPARE(widthPropertyRef.value, QVariant(20)); @@ -992,13 +1014,14 @@ void tst_QQmlEngineDebugService::setBindingForObject() // set handler // rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); QCOMPARE(rootObject.children.size(), 5); // Rectangle, Text, MouseArea, Component.onCompleted, NonScriptPropertyElement QmlDebugObjectReference mouseAreaObject = rootObject.children.at(2); + QVERIFY(!mouseAreaObject.className.isEmpty()); m_dbg->queryObjectRecursive(mouseAreaObject, &success); QVERIFY(success); QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); mouseAreaObject = m_dbg->object(); - QCOMPARE(mouseAreaObject.className, QString("MouseArea")); QmlDebugPropertyReference onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); @@ -1015,11 +1038,14 @@ void tst_QQmlEngineDebugService::setBindingForObject() QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); mouseAreaObject = rootObject.children.at(2); + QVERIFY(!mouseAreaObject.className.isEmpty()); m_dbg->queryObjectRecursive(mouseAreaObject, &success); QVERIFY(success); QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); mouseAreaObject = m_dbg->object(); + QVERIFY(!mouseAreaObject.className.isEmpty()); onEnteredRef = findProperty(mouseAreaObject.properties, "onEntered"); QCOMPARE(onEnteredRef.name, QString("onEntered")); QCOMPARE(onEnteredRef.value, QVariant("function() { [code] }")); @@ -1028,6 +1054,7 @@ void tst_QQmlEngineDebugService::setBindingForObject() void tst_QQmlEngineDebugService::resetBindingForObject() { QmlDebugObjectReference rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); QVERIFY(rootObject.debugId != -1); QmlDebugPropertyReference widthPropertyRef = findProperty(rootObject.properties, "width"); @@ -1048,6 +1075,7 @@ void tst_QQmlEngineDebugService::resetBindingForObject() QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); widthPropertyRef = findProperty(rootObject.properties, "width"); QCOMPARE(widthPropertyRef.value, QVariant(0)); @@ -1063,6 +1091,7 @@ void tst_QQmlEngineDebugService::resetBindingForObject() QCOMPARE(m_dbg->valid(), true); rootObject = findRootObject(); + QVERIFY(!rootObject.className.isEmpty()); QmlDebugPropertyReference boldPropertyRef = findProperty(rootObject.properties, "font.bold"); QCOMPARE(boldPropertyRef.value.toBool(), false); @@ -1076,7 +1105,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() const int sourceIndex = 3; QmlDebugObjectReference obj = findRootObject(sourceIndex); - + QVERIFY(!obj.className.isEmpty()); QVERIFY(obj.debugId != -1); QVERIFY(obj.children.count() >= 2); bool success; @@ -1092,6 +1121,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(),200); @@ -1102,6 +1132,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() obj = findRootObject(sourceIndex, true); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100); @@ -1111,6 +1142,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(state.children.count() > 0); QmlDebugObjectReference propertyChange = state.children[0]; + QVERIFY(!propertyChange.className.isEmpty()); QVERIFY(propertyChange.debugId != -1); m_dbg->setBindingForObject(propertyChange.debugId, "width",QVariant(300),true, @@ -1120,6 +1152,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() // check properties changed in state obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(),100); @@ -1128,6 +1161,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300); // check changing properties of base state from within a state @@ -1141,6 +1175,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(),300); m_dbg->queryExpressionResult(obj.debugId,QString("state=\"\""), &success); @@ -1148,6 +1183,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400); // reset binding while in a state @@ -1156,6 +1192,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result()))); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300); m_dbg->resetBindingForObject(propertyChange.debugId, "width", &success); @@ -1164,6 +1201,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QCOMPARE(m_dbg->valid(), true); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 400); // re-add binding @@ -1174,6 +1212,7 @@ void tst_QQmlEngineDebugService::setBindingInStates() QCOMPARE(m_dbg->valid(), true); obj = findRootObject(sourceIndex); + QVERIFY(!obj.className.isEmpty()); QCOMPARE(findProperty(obj.properties,"width").value.toInt(), 300); } @@ -1182,7 +1221,7 @@ void tst_QQmlEngineDebugService::queryObjectTree() const int sourceIndex = 3; QmlDebugObjectReference obj = findRootObject(sourceIndex, true); - + QVERIFY(!obj.className.isEmpty()); QVERIFY(obj.debugId != -1); QVERIFY(obj.children.count() >= 2); @@ -1192,16 +1231,16 @@ void tst_QQmlEngineDebugService::queryObjectTree() QVERIFY(state.children.count() > 0); QmlDebugObjectReference propertyChange = state.children[0]; + QVERIFY(!propertyChange.className.isEmpty()); QVERIFY(propertyChange.debugId != -1); QmlDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties,"target"); QCOMPARE(propertyChangeTarget.objectDebugId, propertyChange.debugId); QmlDebugObjectReference targetReference = qvariant_cast(propertyChangeTarget.value); + QVERIFY(!targetReference.className.isEmpty()); QVERIFY(targetReference.debugId != -1); - - // check transition QmlDebugObjectReference transition = obj.children[0]; QCOMPARE(transition.className, QString("Transition")); @@ -1210,12 +1249,14 @@ void tst_QQmlEngineDebugService::queryObjectTree() QVERIFY(transition.children.count() > 0); QmlDebugObjectReference animation = transition.children[0]; + QVERIFY(!animation.className.isEmpty()); QVERIFY(animation.debugId != -1); QmlDebugPropertyReference animationTarget = findProperty(animation.properties,"target"); QCOMPARE(animationTarget.objectDebugId, animation.debugId); targetReference = qvariant_cast(animationTarget.value); + QVERIFY(!targetReference.className.isEmpty()); QVERIFY(targetReference.debugId != -1); QCOMPARE(findProperty(animation.properties,"property").value.toString(), QString("width")); diff --git a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp index 3e27951d78..c0252a0290 100644 --- a/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp +++ b/tests/auto/qml/debugger/shared/qqmlenginedebugclient.cpp @@ -386,6 +386,7 @@ void QQmlEngineDebugClient::decode(QPacket &ds, { QmlDebugObjectReference obj; obj.debugId = prop.value.toInt(); + obj.className = prop.valueTypeName; prop.value = qVariantFromValue(obj); break; } -- cgit v1.2.3 From f261a534cc96d41cee15462795844116887bd99a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 31 Mar 2017 15:52:47 +0200 Subject: V4: Set correct source locations for jumps out of conditionals We always want to place the jump on the last line of the conditionally executed statement, unless we might never execute the last line. In the latter case, that is if the inner statement is again a conditional, we use some token of the outer condition. This works fine with loops, as the loop condition is actually checked after each iteration, and it's plausible to the user that we jump there. With "if" statements, it's not so great. We cannot really explain why we jump back to the "if" token after executing the conditional statement. However, we have to add some source location to the jump instruction as otherwise it uses the source location of the last statement that had one, which is rather random. Task-number: QTBUG-59204 Task-number: QTBUG-59774 Change-Id: I48e331ce1c1830f236e16b75c9201a2f490d2092 Reviewed-by: Simon Hausmann --- .../qml/debugger/qv4debugger/tst_qv4debugger.cpp | 68 +++++++++++++++------- 1 file changed, 48 insertions(+), 20 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index 6d0d884ed7..584bd10151 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -315,8 +315,8 @@ private slots: void stepToEndOfScript_data() { redundancy_data(); } void stepToEndOfScript(); - void lastLineOfLoop_data(); - void lastLineOfLoop(); + void lastLineOfConditional_data(); + void lastLineOfConditional(); private: QV4Debugger *debugger() const { @@ -801,32 +801,60 @@ void tst_qv4debugger::stepToEndOfScript() QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number. } -void tst_qv4debugger::lastLineOfLoop_data() +void tst_qv4debugger::lastLineOfConditional_data() { - QTest::addColumn("loopHead"); - QTest::addColumn("loopTail"); - - QTest::newRow("for") << "for (var i = 0; i < 10; ++i) {\n" << "}\n"; - QTest::newRow("for..in") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}\n"; - QTest::newRow("while") << "while (ret < 10) {\n" << "}\n"; - QTest::newRow("do..while") << "do {\n" << "} while (ret < 10);\n"; + QTest::addColumn("head"); + QTest::addColumn("tail"); + QTest::addColumn("breakPoint"); + QTest::addColumn("lastLine"); + + QTest::newRow("for {block}") << "for (var i = 0; i < 10; ++i) {\n" << "}" << 4 << 7; + QTest::newRow("for..in {block}") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}" << 4 << 7; + QTest::newRow("while {block}") << "while (ret < 10) {\n" << "}" << 4 << 7; + QTest::newRow("do..while {block}") << "do {\n" << "} while (ret < 10);" << 4 << 7; + + QTest::newRow("if true {block}") << "if (true) {\n" << "}" + << 4 << 7; + QTest::newRow("if false {block}") << "if (false) {\n" << "}" + << 2 << 8; + QTest::newRow("if true else {block}") << "if (true) {\n" << "} else {\n ret += 8;\n}" + << 4 << 7; + QTest::newRow("if false else {block}") << "if (false) {\n" << "} else {\n ret += 8;\n}" + << 8 << 9; + + QTest::newRow("for statement") << "for (var i = 0; i < 10; ++i)\n" << "" << 4 << 2; + QTest::newRow("for..in statement") << "for (var i in [0, 1, 2, 3, 4])\n" << "" << 4 << 2; + QTest::newRow("while statement") << "while (ret < 10)\n" << "" << 4 << 2; + QTest::newRow("do..while statement") << "do\n" << "while (ret < 10);" << 4 << 7; + + // For two nested if statements without blocks, we need to map the jump from the inner to the + // outer one on the outer "if". There is just no better place. + QTest::newRow("if true statement") << "if (true)\n" << "" << 4 << 2; + QTest::newRow("if false statement") << "if (false)\n" << "" << 2 << 8; + + // Also two nested ifs without blocks. + QTest::newRow("if true else statement") << "if (true)\n" << "else\n ret += 8;" << 4 << 2; + QTest::newRow("if false else statement") << "if (false)\n" << "else\n ret += 8;" << 8 << 9; } -void tst_qv4debugger::lastLineOfLoop() +void tst_qv4debugger::lastLineOfConditional() { - QFETCH(QString, loopHead); - QFETCH(QString, loopTail); + QFETCH(QString, head); + QFETCH(QString, tail); + QFETCH(int, breakPoint); + QFETCH(int, lastLine); QString script = - "var ret = 0;\n" - + loopHead + + "var ret = 2;\n" + + head + " if (ret == 2)\n" " ret += 4;\n" // breakpoint, then step over - " else \n" + " else\n" " ret += 1;\n" - + loopTail; + + tail + "\n" + + "ret -= 5;"; - debugger()->addBreakPoint("trueBranch", 4); + debugger()->addBreakPoint("trueBranch", breakPoint); m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver; evaluateJavaScript(script, "trueBranch"); QVERIFY(m_debuggerAgent->m_wasPaused); @@ -834,10 +862,10 @@ void tst_qv4debugger::lastLineOfLoop() QVERIFY(m_debuggerAgent->m_statesWhenPaused.count() > 1); QV4Debugger::ExecutionState firstState = m_debuggerAgent->m_statesWhenPaused.first(); QCOMPARE(firstState.fileName, QString("trueBranch")); - QCOMPARE(firstState.lineNumber, 4); + QCOMPARE(firstState.lineNumber, breakPoint); QV4Debugger::ExecutionState secondState = m_debuggerAgent->m_statesWhenPaused.at(1); QCOMPARE(secondState.fileName, QString("trueBranch")); - QCOMPARE(secondState.lineNumber, 7); + QCOMPARE(secondState.lineNumber, lastLine); } void tst_qv4debugger::redundancy_data() -- cgit v1.2.3 From 3063599da646f00fc80e42933358935e6565d7b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Tue, 4 Apr 2017 09:19:27 +0300 Subject: Blacklist tst_qquickwindows::requestActivate in macOS 10.11 Task-number: QTBUG-59857 Change-Id: I0d17caceaed0a59ec9abc7f9e8d5fbcc5b504287 Reviewed-by: Liang Qi --- tests/auto/quick/qquickwindow/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/quick/qquickwindow/BLACKLIST (limited to 'tests') diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST new file mode 100644 index 0000000000..b2720c2642 --- /dev/null +++ b/tests/auto/quick/qquickwindow/BLACKLIST @@ -0,0 +1,2 @@ +[requestActivate] +osx-10.11 -- cgit v1.2.3 From 4427be1a9dfd889fc1a65654f0aa61cb253b5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Tue, 4 Apr 2017 12:06:28 +0300 Subject: Blacklist nestedSliderUsingTouch in Ubuntu 16.04 Task-number: QTBUG-59840 Change-Id: I147eb4aa0f0c61f9c017ce1614ea3b2b2d2386c9 Reviewed-by: Liang Qi --- tests/auto/quick/qquickflickable/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/BLACKLIST b/tests/auto/quick/qquickflickable/BLACKLIST index 647bf819a5..f35397f119 100644 --- a/tests/auto/quick/qquickflickable/BLACKLIST +++ b/tests/auto/quick/qquickflickable/BLACKLIST @@ -17,3 +17,5 @@ osx osx-10.10 [flickVelocity] osx-10.10 +[nestedSliderUsingTouch:keepNeither] +ubuntu-16.04 -- cgit v1.2.3 From b4f36c22f4b883679c0dcd8a98a221cbdc987d08 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 4 Apr 2017 12:41:22 +0200 Subject: Adapt tst_qquickflickable::nestedSliderUsingTouch for slow CI QQuickTouchUtils::flush() doesn't actually cause all events to be fully delivered. Task-number: QTBUG-59840 Change-Id: Id5bcd97fa06c0d183e633494eca6aa61908348ae Reviewed-by: J-P Nurmi --- tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 3ecebfb48f..988582f96b 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -2044,10 +2044,10 @@ void tst_qquickflickable::nestedSliderUsingTouch() QCOMPARE(tda->active(), !ungrabs); QTest::touchEvent(window, touchDevice).release(0, p0, window); QQuickTouchUtils::flush(window); - QCOMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed); - QCOMPARE(tda->touchUpdates, updates); - QCOMPARE(tda->touchReleases, releases); - QCOMPARE(tda->ungrabs, ungrabs); + QTRY_COMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed); + QTRY_COMPARE(tda->touchUpdates, updates); + QTRY_COMPARE(tda->touchReleases, releases); + QTRY_COMPARE(tda->ungrabs, ungrabs); } // QTBUG-31328 -- cgit v1.2.3 From af72231fe4a91226d945db9a526fb755332548eb Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 4 Apr 2017 16:26:20 +0200 Subject: Error out if TestCase.verify receives more than 2 parameters Change-Id: I3299f602970067aaef290d4f1c7449d3ab03fb3c Reviewed-by: Simon Hausmann Reviewed-by: Mitch Curtis --- tests/auto/qmltest/selftests/tst_selftests.qml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tests') diff --git a/tests/auto/qmltest/selftests/tst_selftests.qml b/tests/auto/qmltest/selftests/tst_selftests.qml index 439ea7a70d..5555876014 100644 --- a/tests/auto/qmltest/selftests/tst_selftests.qml +++ b/tests/auto/qmltest/selftests/tst_selftests.qml @@ -167,6 +167,16 @@ TestCase { caught = true } verify(caught) + + caught = false; + try { + testCase.verify(true, "foo", "bar") + } catch (e) { + compare(e.message, "QtQuickTest::fail") + compare(functions.failmsg, "More than two arguments given to verify(). Did you mean tryVerify() or tryCompare()?") + caught = true + } + verify(caught) } function test_compare() { -- cgit v1.2.3 From b8eeb7109ca4ed913225868edf8035848ea70ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Wed, 5 Apr 2017 11:43:42 +0300 Subject: Blacklist tst_QQuickMultiPointTouchArea::nonOverlapping in Ubuntu 16.04 Task-number: QTBUG-59829 Change-Id: Ib0b416200922f1e03188960db3735e45012d2797 Reviewed-by: Liang Qi --- tests/auto/quick/qquickmultipointtoucharea/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/auto/quick/qquickmultipointtoucharea/BLACKLIST (limited to 'tests') diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST new file mode 100644 index 0000000000..86200a327e --- /dev/null +++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST @@ -0,0 +1,2 @@ +[nonOverlapping] +ubuntu-16.04 -- cgit v1.2.3 From 315f3689866adea143b064ade6a77d6e21bcc2e3 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 29 Mar 2017 13:11:08 +0200 Subject: Revert "Positioners: allow distinguishing between implicit/explicit child size" This reverts commit 2556bfdab42dc0aefb34bb7cf304063c7db0ff00. This is no longer necessary, as there are now no users of this functionality in other modules. Change-Id: If92bbdb3e5e95b4103610d68d22e929cf30c4e5e Reviewed-by: J-P Nurmi Reviewed-by: Robin Burchell --- .../qquickpositioners/data/implicitGridOneItem.qml | 12 ------ .../qquickpositioners/data/implicitRowOneItem.qml | 9 ----- .../qquickpositioners/tst_qquickpositioners.cpp | 44 ---------------------- 3 files changed, 65 deletions(-) delete mode 100644 tests/auto/quick/qquickpositioners/data/implicitGridOneItem.qml delete mode 100644 tests/auto/quick/qquickpositioners/data/implicitRowOneItem.qml (limited to 'tests') diff --git a/tests/auto/quick/qquickpositioners/data/implicitGridOneItem.qml b/tests/auto/quick/qquickpositioners/data/implicitGridOneItem.qml deleted file mode 100644 index 8da9fc270d..0000000000 --- a/tests/auto/quick/qquickpositioners/data/implicitGridOneItem.qml +++ /dev/null @@ -1,12 +0,0 @@ -import QtQuick 2.9 -import PositionerTest 1.0 - -ImplicitGrid { - columns: 2 - rows: 1 - - Text { - text: "Text" - width: parent.width - } -} diff --git a/tests/auto/quick/qquickpositioners/data/implicitRowOneItem.qml b/tests/auto/quick/qquickpositioners/data/implicitRowOneItem.qml deleted file mode 100644 index 25a287cf31..0000000000 --- a/tests/auto/quick/qquickpositioners/data/implicitRowOneItem.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.9 -import PositionerTest 1.0 - -ImplicitRow { - Text { - text: "Text" - width: parent.width - } -} diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp index 4c4afb7a7b..1b3939401a 100644 --- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp +++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp @@ -98,8 +98,6 @@ private slots: void test_attachedproperties(); void test_attachedproperties_data(); void test_attachedproperties_dynamic(); - void test_useImplicitSize_oneItem_data(); - void test_useImplicitSize_oneItem(); void populateTransitions_row(); void populateTransitions_row_data(); @@ -306,8 +304,6 @@ void tst_qquickpositioners::moveTransitions_flow_data() tst_qquickpositioners::tst_qquickpositioners() { - qmlRegisterType("PositionerTest", 1, 0, "ImplicitRow"); - qmlRegisterType("PositionerTest", 1, 0, "ImplicitGrid"); } void tst_qquickpositioners::test_horizontal() @@ -4008,46 +4004,6 @@ void tst_qquickpositioners::test_attachedproperties_dynamic() } -void tst_qquickpositioners::test_useImplicitSize_oneItem_data() -{ - QTest::addColumn("positionerType"); - - QTest::newRow("Grid") << "Grid"; - QTest::newRow("Row") << "Row"; -} - -void tst_qquickpositioners::test_useImplicitSize_oneItem() -{ - QFETCH(QString, positionerType); - - QQuickView view; - view.setSource(testFileUrl(QString::fromLatin1("implicit%1OneItem.qml").arg(positionerType))); - QCOMPARE(view.status(), QQuickView::Ready); - view.show(); - QVERIFY(QTest::qWaitForWindowExposed(&view)); - - QQuickItem *positioner = view.rootObject(); - QVERIFY(positioner); - const qreal oldPositionerImplicitWidth = positioner->implicitWidth(); - - QQuickText *text = qobject_cast(positioner->childItems().first()); - QVERIFY(text); - const qreal oldTextImplicitWidth = text->implicitWidth(); - QCOMPARE(positioner->implicitWidth(), text->implicitWidth()); - - // Ensure that the implicit size of the positioner changes when the implicit size - // of one of its children changes. - text->setText(QLatin1String("Even More Text")); - const qreal textImplicitWidthIncrease = text->implicitWidth() - oldTextImplicitWidth; - QVERIFY(textImplicitWidthIncrease > 0); - QTRY_COMPARE(positioner->implicitWidth(), oldPositionerImplicitWidth + textImplicitWidthIncrease); - - // Ensure that the implicit size of the positioner does not change when the - // explicit size of one of its children changes. - text->setWidth(10); - QTRY_COMPARE(positioner->implicitWidth(), oldPositionerImplicitWidth + textImplicitWidthIncrease); -} - QQuickView *tst_qquickpositioners::createView(const QString &filename, bool wait) { QQuickView *window = new QQuickView(0); -- cgit v1.2.3 From 79e44016d535a559971339bf215851ccca77494a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 5 Apr 2017 10:06:07 +0200 Subject: tst_qquickflickable: remove bogus ItemAcceptsDrops flag TouchDragArea (only for the nestedSliderUsingTouch test so far) doesn't need this flag. It was a copy-and-paste mistake. Change-Id: I4aba79f940e89c9b5f91f2a347c1b7f458284e24 Reviewed-by: J-P Nurmi --- tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 988582f96b..f8277c6895 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -63,9 +63,7 @@ public: , touchReleases(0) , ungrabs(0) , m_active(false) - { - setFlags(ItemAcceptsDrops); - } + { } QPointF pos() const { return m_pos; } -- cgit v1.2.3 From 8b255c67b965cda334425d64a0f1fd13ace93584 Mon Sep 17 00:00:00 2001 From: "Martin T. H. Sandsmark" Date: Sun, 12 Mar 2017 15:03:56 +0100 Subject: QQuickParticleSystem: Fix crash when an Affector dies A guarded pointer wasn't checked before being de-referenced, that lead to a crash if an emitter was modified after an affector was deleted, but before updateCurrentTime() was called. Change-Id: I6cb605a711319fb77c1e2e87fa9f35427cd7797b Reviewed-by: Robin Burchell --- .../qquickparticlesystem/data/crashaffectors.qml | 43 ++++++++++++++++++++++ .../tst_qquickparticlesystem.cpp | 7 ++++ 2 files changed, 50 insertions(+) create mode 100644 tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml (limited to 'tests') diff --git a/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml b/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml new file mode 100644 index 0000000000..de105916a7 --- /dev/null +++ b/tests/auto/particles/qquickparticlesystem/data/crashaffectors.qml @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2017 reMarkable A/S +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Particles 2.0 + +ParticleSystem { + running: false + Affector { Component.onCompleted: destroy() } + Emitter { + Timer { interval: 1; running: true; onTriggered: parent.lifeSpan = 1 } + } +} diff --git a/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp b/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp index 5c82b946e5..5f9db12144 100644 --- a/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp +++ b/tests/auto/particles/qquickparticlesystem/tst_qquickparticlesystem.cpp @@ -42,6 +42,7 @@ public: private slots: void initTestCase(); void test_basic(); + void test_affectorscrash(); }; void tst_qquickparticlesystem::initTestCase() @@ -78,6 +79,12 @@ void tst_qquickparticlesystem::test_basic() delete view; QVERIFY(extremelyFuzzyCompare(stillAlive, 500, 5));//Small simulation variance is permissible. } +void tst_qquickparticlesystem::test_affectorscrash() +{ + QScopedPointer view (createView(testFileUrl("crashaffectors.qml"), 600)); + + // This should have crashed by now +} QTEST_MAIN(tst_qquickparticlesystem); -- cgit v1.2.3 From 80060b7beca8e4d29683298fe77a5d770c606c06 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 5 Apr 2017 11:41:30 +0200 Subject: Add auto-test for qmlcachegen This test writes a simple QML file with embedded JS code into a temporary directory, calls qmlcachegen to generate the cache file, removes the original source code and tries to load the component. Change-Id: I63e1b0c76a987f4a21b3dc6cb7c4dc828dd5d11f Reviewed-by: Lars Knoll --- tests/auto/qml/qml.pro | 1 + tests/auto/qml/qmlcachegen/qmlcachegen.pro | 7 ++ tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 121 +++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 tests/auto/qml/qmlcachegen/qmlcachegen.pro create mode 100644 tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp (limited to 'tests') diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index 007eb0dc83..ac288674c7 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -39,6 +39,7 @@ PRIVATETESTS += \ !boot2qt { PRIVATETESTS += \ + qmlcachegen \ animation \ qqmlecmascript \ qqmlcontext \ diff --git a/tests/auto/qml/qmlcachegen/qmlcachegen.pro b/tests/auto/qml/qmlcachegen/qmlcachegen.pro new file mode 100644 index 0000000000..8d8b37be15 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/qmlcachegen.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qmlcachegen +macos:CONFIG -= app_bundle + +SOURCES += tst_qmlcachegen.cpp + +QT += core-private qml-private testlib diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp new file mode 100644 index 0000000000..466d63bf80 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +class tst_qmlcachegen: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + + void loadGeneratedFile(); +}; + +// A wrapper around QQmlComponent to ensure the temporary reference counts +// on the type data as a result of the main thread <> loader thread communication +// are dropped. Regular Synchronous loading will leave us with an event posted +// to the gui thread and an extra refcount that will only be dropped after the +// event delivery. A plain sendPostedEvents() however is insufficient because +// we can't be sure that the event is posted after the constructor finished. +class CleanlyLoadingComponent : public QQmlComponent +{ +public: + CleanlyLoadingComponent(QQmlEngine *engine, const QUrl &url) + : QQmlComponent(engine, url, QQmlComponent::Asynchronous) + { waitForLoad(); } + CleanlyLoadingComponent(QQmlEngine *engine, const QString &fileName) + : QQmlComponent(engine, fileName, QQmlComponent::Asynchronous) + { waitForLoad(); } + + void waitForLoad() + { + QTRY_VERIFY(status() == QQmlComponent::Ready || status() == QQmlComponent::Error); + } +}; + +static bool generateCache(const QString &qmlFileName) +{ + QProcess proc; + proc.setProcessChannelMode(QProcess::ForwardedChannels); + proc.setProgram(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator() + QLatin1String("qmlcachegen")); + proc.setArguments(QStringList() << (QLatin1String("--target-architecture=") + QSysInfo::buildCpuArchitecture()) << qmlFileName); + proc.start(); + if (!proc.waitForFinished()) + return false; + if (proc.exitStatus() != QProcess::NormalExit) + return false; + return proc.exitCode() == 0; +} + +void tst_qmlcachegen::initTestCase() +{ + qputenv("QML_FORCE_DISK_CACHE", "1"); +} + +void tst_qmlcachegen::loadGeneratedFile() +{ + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + const QString testFilePath = writeTempFile("test.qml", "import QtQml 2.0\n" + "QtObject {\n" + " property int value: Math.min(100, 42);\n" + "}"); + + QVERIFY(generateCache(testFilePath)); + + const QString cacheFilePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(cacheFilePath)); + QVERIFY(QFile::remove(testFilePath)); + + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); + QScopedPointer obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("value").toInt(), 42); +} + +QTEST_GUILESS_MAIN(tst_qmlcachegen) + +#include "tst_qmlcachegen.moc" -- cgit v1.2.3 From 79544c715412a945359d3fe3ebc3dfc11c58f983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Thu, 6 Apr 2017 09:22:26 +0300 Subject: Blacklist tst_QQuickMultiPointTouchArea::nested on Ubuntu 16.04 Task-number: QTBUG-59960 Change-Id: Ibbcde3aa64e517a7bc0c0073efc84ff66a3fae4c Reviewed-by: Liang Qi --- tests/auto/quick/qquickmultipointtoucharea/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST index 86200a327e..cab6e2f7bf 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST +++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST @@ -1,2 +1,4 @@ [nonOverlapping] ubuntu-16.04 +[nested] +ubuntu-16.04 -- cgit v1.2.3 From fcb9a740787084f1549df6d4d93d2c3886d39acd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 5 Apr 2017 14:47:34 +0200 Subject: Fix loading of ahead-of-time generated cache files when cross-compiling The target ABI is something that we must include correctly at cache generation time. The corresponding qmake variable is available in qtbase now, so we can use that and embed it in the generated data. Change-Id: Icd6e44824f5151535ce9ddac27687b7877288725 Reviewed-by: Lars Knoll --- tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 466d63bf80..27bb2348b8 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -71,7 +71,7 @@ static bool generateCache(const QString &qmlFileName) QProcess proc; proc.setProcessChannelMode(QProcess::ForwardedChannels); proc.setProgram(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator() + QLatin1String("qmlcachegen")); - proc.setArguments(QStringList() << (QLatin1String("--target-architecture=") + QSysInfo::buildCpuArchitecture()) << qmlFileName); + proc.setArguments(QStringList() << (QLatin1String("--target-architecture=") + QSysInfo::buildCpuArchitecture()) << (QLatin1String("--target-abi=") + QSysInfo::buildAbi()) << qmlFileName); proc.start(); if (!proc.waitForFinished()) return false; -- cgit v1.2.3 From 9b961334cfd81ec5fcc4dc7d2c50154cddd5f230 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 5 Apr 2017 12:11:25 +0200 Subject: Fix support for jsTr() and QT_TR_NOOP in list elements when caching Similar to the Qt Quick Compiler we need to do the expression simplification pass at cache generation time to extract translation calls in list elements. Change-Id: I267fc9647ab82bc83d6b087c06c0036df38238ff Reviewed-by: Lars Knoll --- tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 27bb2348b8..b7e616a050 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -42,6 +42,7 @@ private slots: void initTestCase(); void loadGeneratedFile(); + void translationExpressionSupport(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -116,6 +117,47 @@ void tst_qmlcachegen::loadGeneratedFile() QCOMPARE(obj->property("value").toInt(), 42); } +void tst_qmlcachegen::translationExpressionSupport() +{ + QTemporaryDir tempDir; + QVERIFY(tempDir.isValid()); + + const auto writeTempFile = [&tempDir](const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); + }; + + const QString testFilePath = writeTempFile("test.qml", "import QtQml.Models 2.2\n" + "import QtQml 2.2\n" + "QtObject {\n" + " property ListModel model: ListModel {\n" + " ListElement {\n" + " text: qsTr(\"All\")\n" + " }\n" + " ListElement {\n" + " text: QT_TR_NOOP(\"Ok\")\n" + " }\n" + " }\n" + " property string text: model.get(0).text + \" \" + model.get(1).text\n" + "}"); + + + QVERIFY(generateCache(testFilePath)); + + const QString cacheFilePath = testFilePath + QLatin1Char('c'); + QVERIFY(QFile::exists(cacheFilePath)); + QVERIFY(QFile::remove(testFilePath)); + + QQmlEngine engine; + CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); + QScopedPointer obj(component.create()); + QVERIFY(!obj.isNull()); + QCOMPARE(obj->property("text").toString(), QString("All Ok")); +} + QTEST_GUILESS_MAIN(tst_qmlcachegen) #include "tst_qmlcachegen.moc" -- cgit v1.2.3 From 67d1d7843ab5e1c904c8f0f76eadb9fc3f1bbb17 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 5 Apr 2017 12:58:01 +0200 Subject: Enable running of qmlcachegen tests on ARM/qemu This gives us test coverage for the most important cross-compiling scenario of x86-64 host to armv7 target. Change-Id: I31abd3802681b14561e1ee4c60f6cc9cc2049bf2 Reviewed-by: Lars Knoll --- tests/auto/qml/qml.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro index ac288674c7..59566ad927 100644 --- a/tests/auto/qml/qml.pro +++ b/tests/auto/qml/qml.pro @@ -36,10 +36,10 @@ PRIVATETESTS += \ qqmlcpputils \ qqmldirparser \ v4misc \ + qmlcachegen !boot2qt { PRIVATETESTS += \ - qmlcachegen \ animation \ qqmlecmascript \ qqmlcontext \ -- cgit v1.2.3 From 37da30b83021869b2fd069ea49d72d89b16c2046 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sun, 20 Nov 2016 22:23:14 +0100 Subject: Allow custom bounds behaviors for Flickable [ChangeLog][QtQuick][Flickable] Added a boundsMovement property that allows disabling the default bounce effect and implementing custom edge effects. Task-number: QTBUG-38515 Change-Id: Id00d30a863e264cdbac00fbad8189406f29484c4 Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- .../quick/qquickflickable/tst_qquickflickable.cpp | 143 ++++++++++++++------- 1 file changed, 94 insertions(+), 49 deletions(-) (limited to 'tests') diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index f8277c6895..ef6e444580 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -2216,6 +2216,7 @@ Q_DECLARE_METATYPE(QQuickFlickable::BoundsBehavior) void tst_qquickflickable::overshoot() { QFETCH(QQuickFlickable::BoundsBehavior, boundsBehavior); + QFETCH(int, boundsMovement); QScopedPointer window(new QQuickView); window->setSource(testFileUrl("overshoot.qml")); @@ -2232,6 +2233,7 @@ void tst_qquickflickable::overshoot() QCOMPARE(flickable->contentHeight(), 400.0); flickable->setBoundsBehavior(boundsBehavior); + flickable->setBoundsMovement(QQuickFlickable::BoundsMovement(boundsMovement)); // drag past the beginning QTest::mousePress(window.data(), Qt::LeftButton, 0, QPoint(10, 10)); @@ -2240,23 +2242,30 @@ void tst_qquickflickable::overshoot() QTest::mouseMove(window.data(), QPoint(40, 40)); QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(50, 50)); + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) { + QVERIFY(flickable->property("minContentX").toReal() < 0.0); + QVERIFY(flickable->property("minContentY").toReal() < 0.0); + } else { + QCOMPARE(flickable->property("minContentX").toReal(), 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), 0.0); + } if (boundsBehavior & QQuickFlickable::DragOverBounds) { - QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0); - QCOMPARE(flickable->property("minContentY").toReal(), - flickable->property("minVerticalOvershoot").toReal()); - QCOMPARE(flickable->property("minContentX").toReal(), - flickable->property("minHorizontalOvershoot").toReal()); + QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); } else { - QCOMPARE(flickable->property("minContentY").toReal(), 0.0); - QCOMPARE(flickable->property("minContentX").toReal(), 0.0); - QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + } + if (bool(boundsMovement == QQuickFlickable::FollowBoundsBehavior) == bool(boundsBehavior & QQuickFlickable::DragOverBounds)) { + QCOMPARE(flickable->property("minContentX").toReal(), + flickable->property("minHorizontalOvershoot").toReal()); + QCOMPARE(flickable->property("minContentY").toReal(), + flickable->property("minVerticalOvershoot").toReal()); } - QCOMPARE(flickable->property("maxContentY").toReal(), 0.0); QCOMPARE(flickable->property("maxContentX").toReal(), 0.0); - QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxContentY").toReal(), 0.0); QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); flickable->setContentX(20.0); flickable->setContentY(20.0); @@ -2266,23 +2275,30 @@ void tst_qquickflickable::overshoot() flick(window.data(), QPoint(10, 10), QPoint(50, 50), 100); QTRY_VERIFY(!flickable->property("flicking").toBool()); + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::OvershootBounds)) { + QVERIFY(flickable->property("minContentX").toReal() < 0.0); + QVERIFY(flickable->property("minContentY").toReal() < 0.0); + } else { + QCOMPARE(flickable->property("minContentX").toReal(), 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), 0.0); + } if (boundsBehavior & QQuickFlickable::OvershootBounds) { - QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); QVERIFY(flickable->property("minHorizontalOvershoot").toReal() < 0.0); - QCOMPARE(flickable->property("minContentY").toReal(), - flickable->property("minVerticalOvershoot").toReal()); - QCOMPARE(flickable->property("minContentX").toReal(), - flickable->property("minHorizontalOvershoot").toReal()); + QVERIFY(flickable->property("minVerticalOvershoot").toReal() < 0.0); } else { - QCOMPARE(flickable->property("minContentY").toReal(), 0.0); - QCOMPARE(flickable->property("minContentX").toReal(), 0.0); - QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + } + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::OvershootBounds)) { + QCOMPARE(flickable->property("minContentX").toReal(), + flickable->property("minHorizontalOvershoot").toReal()); + QCOMPARE(flickable->property("minContentY").toReal(), + flickable->property("minVerticalOvershoot").toReal()); } - QCOMPARE(flickable->property("maxContentY").toReal(), 20.0); QCOMPARE(flickable->property("maxContentX").toReal(), 20.0); - QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxContentY").toReal(), 20.0); QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); flickable->setContentX(200.0); flickable->setContentY(200.0); @@ -2295,23 +2311,30 @@ void tst_qquickflickable::overshoot() QTest::mouseMove(window.data(), QPoint(20, 20)); QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(10, 10)); + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::DragOverBounds)) { + QVERIFY(flickable->property("maxContentX").toReal() > 200.0); + QVERIFY(flickable->property("maxContentX").toReal() > 200.0); + } else { + QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); + QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); + } if (boundsBehavior & QQuickFlickable::DragOverBounds) { - QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0); - QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, - flickable->property("maxVerticalOvershoot").toReal()); - QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, - flickable->property("maxHorizontalOvershoot").toReal()); + QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); } else { - QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); - QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); - QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + } + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::DragOverBounds)) { + QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, + flickable->property("maxHorizontalOvershoot").toReal()); + QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, + flickable->property("maxVerticalOvershoot").toReal()); } - QCOMPARE(flickable->property("minContentY").toReal(), 200.0); QCOMPARE(flickable->property("minContentX").toReal(), 200.0); - QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), 200.0); QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); flickable->setContentX(180.0); flickable->setContentY(180.0); @@ -2321,37 +2344,59 @@ void tst_qquickflickable::overshoot() flick(window.data(), QPoint(50, 50), QPoint(10, 10), 100); QTRY_VERIFY(!flickable->property("flicking").toBool()); + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) && (boundsBehavior & QQuickFlickable::OvershootBounds)) { + QVERIFY(flickable->property("maxContentX").toReal() > 200.0); + QVERIFY(flickable->property("maxContentY").toReal() > 200.0); + } else { + QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); + QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); + } if (boundsBehavior & QQuickFlickable::OvershootBounds) { - QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); QVERIFY(flickable->property("maxHorizontalOvershoot").toReal() > 0.0); - QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, - flickable->property("maxVerticalOvershoot").toReal()); - QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, - flickable->property("maxHorizontalOvershoot").toReal()); + QVERIFY(flickable->property("maxVerticalOvershoot").toReal() > 0.0); } else { - QCOMPARE(flickable->property("maxContentY").toReal(), 200.0); - QCOMPARE(flickable->property("maxContentX").toReal(), 200.0); - QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); QCOMPARE(flickable->property("maxHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("maxVerticalOvershoot").toReal(), 0.0); + } + if ((boundsMovement == QQuickFlickable::FollowBoundsBehavior) == (boundsBehavior & QQuickFlickable::OvershootBounds)) { + QCOMPARE(flickable->property("maxContentX").toReal() - 200.0, + flickable->property("maxHorizontalOvershoot").toReal()); + QCOMPARE(flickable->property("maxContentY").toReal() - 200.0, + flickable->property("maxVerticalOvershoot").toReal()); } - QCOMPARE(flickable->property("minContentY").toReal(), 180.0); QCOMPARE(flickable->property("minContentX").toReal(), 180.0); - QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minContentY").toReal(), 180.0); QCOMPARE(flickable->property("minHorizontalOvershoot").toReal(), 0.0); + QCOMPARE(flickable->property("minVerticalOvershoot").toReal(), 0.0); } void tst_qquickflickable::overshoot_data() { QTest::addColumn("boundsBehavior"); - - QTest::newRow("StopAtBounds") - << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds); - QTest::newRow("DragOverBounds") - << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds); - QTest::newRow("OvershootBounds") - << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds); - QTest::newRow("DragAndOvershootBounds") - << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds); + QTest::addColumn("boundsMovement"); + + QTest::newRow("StopAtBounds,FollowBoundsBehavior") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds) + << int(QQuickFlickable::FollowBoundsBehavior); + QTest::newRow("DragOverBounds,FollowBoundsBehavior") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds) + << int(QQuickFlickable::FollowBoundsBehavior); + QTest::newRow("OvershootBounds,FollowBoundsBehavior") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds) + << int(QQuickFlickable::FollowBoundsBehavior); + QTest::newRow("DragAndOvershootBounds,FollowBoundsBehavior") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds) + << int(QQuickFlickable::FollowBoundsBehavior); + + QTest::newRow("DragOverBounds,StopAtBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds) + << int(QQuickFlickable::StopAtBounds); + QTest::newRow("OvershootBounds,StopAtBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds) + << int(QQuickFlickable::StopAtBounds); + QTest::newRow("DragAndOvershootBounds,StopAtBounds") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds) + << int(QQuickFlickable::StopAtBounds); } void tst_qquickflickable::overshoot_reentrant() -- cgit v1.2.3 From 90e7521313fc9e89d492d65f9ad0dca3c38e7225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tony=20Saraj=C3=A4rvi?= Date: Mon, 10 Apr 2017 21:54:58 +0300 Subject: Blacklist tst_qquickwindow::attachedProperty on macOS 10.11 Task-number: QTBUG-60052 Change-Id: I9f415fa2c2a984dd347983c67d1255efb858cb0d Reviewed-by: Liang Qi --- tests/auto/quick/qquickwindow/BLACKLIST | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tests') diff --git a/tests/auto/quick/qquickwindow/BLACKLIST b/tests/auto/quick/qquickwindow/BLACKLIST index b2720c2642..157808fdbf 100644 --- a/tests/auto/quick/qquickwindow/BLACKLIST +++ b/tests/auto/quick/qquickwindow/BLACKLIST @@ -1,2 +1,4 @@ [requestActivate] osx-10.11 +[attachedProperty] +osx-10.11 -- cgit v1.2.3 From a8570c79780fe3351ede0265eb97672bd349de99 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 7 Apr 2017 14:16:14 +0200 Subject: tst_qmlplugindump: Ensure process starts properly While we're here, clean up the output too. Only print it if the test fails. Change-Id: I69973e1e6b5125378649081f7ab361e6d31005b4 Reviewed-by: Simon Hausmann --- tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp index 838966e2a0..68e11e3551 100644 --- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp +++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp @@ -105,12 +105,12 @@ void tst_qmlplugindump::singleton() args << QLatin1String("tests.dumper.CompositeSingleton") << QLatin1String("1.0") << QLatin1String("."); dumper.start(qmlplugindumpPath, args); - dumper.waitForFinished(); + QVERIFY2(dumper.waitForStarted(), qPrintable(dumper.errorString())); + QVERIFY2(dumper.waitForFinished(), qPrintable(dumper.errorString())); const QString &result = dumper.readAllStandardOutput(); - qDebug() << "result: " << result; - QVERIFY(result.contains(QLatin1String("exports: [\"Singleton 1.0\"]"))); - QVERIFY(result.contains(QLatin1String("exportMetaObjectRevisions: [0]"))); + QVERIFY2(result.contains(QLatin1String("exports: [\"Singleton 1.0\"]")), qPrintable(result)); + QVERIFY2(result.contains(QLatin1String("exportMetaObjectRevisions: [0]")), qPrintable(result)); } QTEST_MAIN(tst_qmlplugindump) -- cgit v1.2.3