diff options
Diffstat (limited to 'tests')
38 files changed, 1535 insertions, 101 deletions
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml index a36d0cae91..0fa9f1ffd8 100644 --- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml +++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml @@ -36,6 +36,7 @@ Item { var b = {a: "hello", d: 1 } var c var d = 12 + console.log("Component.onCompleted"); } function foo() { var a = [1, 2] diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp index 8d1a165243..3aa3a5c87e 100644 --- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp +++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp @@ -142,24 +142,36 @@ void tst_QQmlDebuggingEnabler::cleanup() void tst_QQmlDebuggingEnabler::data() { + QTest::addColumn<QString>("connector"); QTest::addColumn<bool>("blockMode"); QTest::addColumn<QStringList>("services"); - QTest::newRow("noblock,all") << false << QStringList(); - QTest::newRow("block,all") << true << QStringList(); - QTest::newRow("noblock,debugger") << false << QQmlDebuggingEnabler::debuggerServices(); - QTest::newRow("block,debugger") << true << QQmlDebuggingEnabler::debuggerServices(); - QTest::newRow("noblock,inspector") << false << QQmlDebuggingEnabler::inspectorServices(); - QTest::newRow("block,inspector") << true << QQmlDebuggingEnabler::inspectorServices(); - QTest::newRow("noblock,profiler") << false << QQmlDebuggingEnabler::profilerServices(); - QTest::newRow("block,profiler") << true << QQmlDebuggingEnabler::profilerServices(); - QTest::newRow("noblock,debugger+inspector") - << false << QQmlDebuggingEnabler::debuggerServices() + - QQmlDebuggingEnabler::inspectorServices(); - QTest::newRow("block,debugger+inspector") - << true << QQmlDebuggingEnabler::debuggerServices() + - QQmlDebuggingEnabler::inspectorServices(); - + QStringList connectors({ + QLatin1String("QQmlDebugServer"), + QLatin1String("QQmlNativeDebugConnector") + }); + + QList<bool> blockModes({ true, false }); + + QList<QStringList> serviceLists({ + QStringList(), + QQmlDebuggingEnabler::nativeDebuggerServices(), + QQmlDebuggingEnabler::debuggerServices(), + QQmlDebuggingEnabler::inspectorServices(), + QQmlDebuggingEnabler::profilerServices(), + QQmlDebuggingEnabler::debuggerServices() + QQmlDebuggingEnabler::inspectorServices() + }); + + foreach (const QString &connector, connectors) { + foreach (bool blockMode, blockModes) { + foreach (const QStringList &serviceList, serviceLists) { + QString name = connector + QLatin1Char(',') + + QLatin1String(blockMode ? "block" : "noblock") + QLatin1Char(',') + + serviceList.join(QLatin1Char('-')); + QTest::newRow(name.toUtf8().constData()) << connector << blockMode << serviceList; + } + } + } } void tst_QQmlDebuggingEnabler::qmlscene_data() @@ -169,27 +181,36 @@ void tst_QQmlDebuggingEnabler::qmlscene_data() void tst_QQmlDebuggingEnabler::qmlscene() { + QFETCH(QString, connector); QFETCH(bool, blockMode); QFETCH(QStringList, services); - connection = new QQmlDebugConnection(); - QList<QQmlDebugClient *> clients = QQmlDebugTest::createOtherClients(connection); process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this); process->setMaximumBindErrors(1); process->start(QStringList() - << QString::fromLatin1("-qmljsdebugger=port:5555,5565%1%2%3") + << QString::fromLatin1("-qmljsdebugger=connector:%1%2%3%4") + .arg(connector + (connector == QLatin1String("QQmlDebugServer") ? + QLatin1String(",port:5555,5565") : QString())) .arg(blockMode ? QLatin1String(",block") : QString()) .arg(services.isEmpty() ? QString() : QString::fromLatin1(",services:")) .arg(services.isEmpty() ? QString() : services.join(",")) << testFile(QLatin1String("test.qml"))); - QVERIFY(process->waitForSessionStart()); - connection->connectToHost("127.0.0.1", process->debugPort()); - QVERIFY(connection->waitForConnected()); - foreach (QQmlDebugClient *client, clients) - QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ? - QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable); + if (connector == QLatin1String("QQmlDebugServer")) { + QVERIFY(process->waitForSessionStart()); + connection = new QQmlDebugConnection(); + QList<QQmlDebugClient *> clients = QQmlDebugTest::createOtherClients(connection); + connection->connectToHost("127.0.0.1", process->debugPort()); + QVERIFY(connection->waitForConnected()); + foreach (QQmlDebugClient *client, clients) + QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ? + QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable); + } + + QCOMPARE(process->state(), QLatin1String("running")); + if (!blockMode) + QTRY_VERIFY(process->output().contains(QLatin1String("qml: Component.onCompleted"))); } void tst_QQmlDebuggingEnabler::custom_data() @@ -199,13 +220,12 @@ void tst_QQmlDebuggingEnabler::custom_data() void tst_QQmlDebuggingEnabler::custom() { + QFETCH(QString, connector); QFETCH(bool, blockMode); QFETCH(QStringList, services); const int portFrom = 5555; const int portTo = 5565; - connection = new QQmlDebugConnection(); - QList<QQmlDebugClient *> clients = QQmlDebugTest::createOtherClients(connection); process = new QQmlDebugProcess(QCoreApplication::applicationDirPath() + QLatin1String("/qqmldebuggingenablerserver"), this); process->setMaximumBindErrors(portTo - portFrom); @@ -214,18 +234,28 @@ void tst_QQmlDebuggingEnabler::custom() if (blockMode) args << QLatin1String("-block"); - args << QString::number(portFrom) << QString::number(portTo); + args << QLatin1String("-connector") << connector + << QString::number(portFrom) << QString::number(portTo); + if (!services.isEmpty()) args << QLatin1String("-services") << services; process->start(args); - QVERIFY(process->waitForSessionStart()); - connection->connectToHost("127.0.0.1", process->debugPort()); - QVERIFY(connection->waitForConnected()); - foreach (QQmlDebugClient *client, clients) - QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ? - QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable); + if (connector == QLatin1String("QQmlDebugServer")) { + QVERIFY(process->waitForSessionStart()); + connection = new QQmlDebugConnection(); + QList<QQmlDebugClient *> clients = QQmlDebugTest::createOtherClients(connection); + connection->connectToHost("127.0.0.1", process->debugPort()); + QVERIFY(connection->waitForConnected()); + foreach (QQmlDebugClient *client, clients) + QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ? + QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable); + } + + QCOMPARE(process->state(), QLatin1String("running")); + if (!blockMode) + QTRY_VERIFY(process->output().contains(QLatin1String("QQmlEngine created"))); } QTEST_MAIN(tst_QQmlDebuggingEnabler) diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp index cfbb31f9e1..a064bbbacc 100644 --- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp +++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp @@ -28,6 +28,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qlibraryinfo.h> +#include <QtCore/qdebug.h> #include <QtQml/qqmldebug.h> #include <QtQml/qqmlengine.h> @@ -40,12 +41,18 @@ int main(int argc, char *argv[]) QCoreApplication app(argc, argv); QStringList arguments = app.arguments(); arguments.removeFirst(); + QString connector = QLatin1String("QQmlDebugServer"); if (arguments.size() && arguments.first() == QLatin1String("-block")) { block = QQmlDebuggingEnabler::WaitForClient; arguments.removeFirst(); } + if (arguments.size() >= 2 && arguments.first() == QLatin1String("-connector")) { + arguments.removeFirst(); + connector = arguments.takeFirst(); + } + if (arguments.size() >= 2) { portFrom = arguments.takeFirst().toInt(); portTo = arguments.takeFirst().toInt(); @@ -54,12 +61,20 @@ int main(int argc, char *argv[]) if (arguments.size() && arguments.takeFirst() == QLatin1String("-services")) QQmlDebuggingEnabler::setServices(arguments); - if (!portFrom || !portTo) - qFatal("Port range has to be specified."); + if (connector == QLatin1String("QQmlDebugServer")) { + if (!portFrom || !portTo) + qFatal("Port range has to be specified."); + + while (portFrom <= portTo) + QQmlDebuggingEnabler::startTcpDebugServer(portFrom++, block); + } else if (connector == QLatin1String("QQmlNativeDebugConnector")) { + QVariantHash configuration; + configuration[QLatin1String("block")] = (block == QQmlDebuggingEnabler::WaitForClient); + QQmlDebuggingEnabler::startDebugConnector(connector, configuration); + } - while (portFrom <= portTo) - QQmlDebuggingEnabler::startTcpDebugServer(portFrom++, block); QQmlEngine engine; + qDebug() << "QQmlEngine created\n"; Q_UNUSED(engine); return app.exec(); } diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro index 79e772c1ee..cbaf3b5309 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/qqmldebugjs.pro @@ -9,6 +9,7 @@ SOURCES += tst_qqmldebugjs.cpp INCLUDEPATH += ../../shared include(../../../../shared/util.pri) include(../../shared/debugutil.pri) +include(../../shared/qqmlenginedebugclient.pri) TESTDATA = data/* diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp index d1150be831..31b8d63ec2 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include "debugutil_p.h" +#include "../../shared/qqmlenginedebugclient.h" #include "../../../../shared/util.h" #include <private/qqmldebugclient_p.h> @@ -52,6 +53,7 @@ const char *STEPACTION = "stepaction"; const char *STEPCOUNT = "stepcount"; const char *EXPRESSION = "expression"; const char *FRAME = "frame"; +const char *CONTEXT = "context"; const char *GLOBAL = "global"; const char *DISABLEBREAK = "disable_break"; const char *HANDLES = "handles"; @@ -215,6 +217,8 @@ private slots: void evaluateInLocalScope_data() { targetData(); } void evaluateInLocalScope(); + void evaluateInContext(); + void getScripts_data() { targetData(); } void getScripts(); @@ -257,7 +261,7 @@ public: void interrupt(); void continueDebugging(StepAction stepAction); - void evaluate(QString expr, int frame = -1); + void evaluate(QString expr, int frame = -1, int context = -1); void lookup(QList<int> handles, bool includeSource = false); void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); void frame(int number = -1); @@ -280,6 +284,7 @@ signals: void connected(); void interruptRequested(); void result(); + void failure(); void stopped(); private: @@ -340,13 +345,14 @@ void QJSDebugClient::continueDebugging(StepAction action) sendMessage(packMessage(V8REQUEST, json.toString().toUtf8())); } -void QJSDebugClient::evaluate(QString expr, int frame) +void QJSDebugClient::evaluate(QString expr, int frame, int context) { // { "seq" : <number>, // "type" : "request", // "command" : "evaluate", // "arguments" : { "expression" : <expression to evaluate>, - // "frame" : <number> + // "frame" : <number>, + // "context" : <object ID> // } // } VARIANTMAPINIT; @@ -358,6 +364,9 @@ void QJSDebugClient::evaluate(QString expr, int frame) if (frame != -1) args.setProperty(QLatin1String(FRAME),QJSValue(frame)); + if (context != -1) + args.setProperty(QLatin1String(CONTEXT), QJSValue(context)); + if (!args.isUndefined()) { jsonVal.setProperty(QLatin1String(ARGUMENTS),args); } @@ -684,6 +693,7 @@ void QJSDebugClient::messageReceived(const QByteArray &data) if (type == "response") { if (!value.value("success").toBool()) { + emit failure(); qDebug() << "Received success == false response from application"; return; } @@ -1394,6 +1404,58 @@ void tst_QQmlDebugJS::evaluateInLocalScope() QCOMPARE(body.value("value").toInt(),10); } +void tst_QQmlDebugJS::evaluateInContext() +{ + connection = new QQmlDebugConnection(); + process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + + "/qmlscene", this); + client = new QJSDebugClient(connection); + QScopedPointer<QQmlEngineDebugClient> engineClient(new QQmlEngineDebugClient(connection)); + process->start(QStringList() << QLatin1String(BLOCKMODE) << testFile(ONCOMPLETED_QMLFILE)); + + QVERIFY(process->waitForSessionStart()); + + connection->connectToHost("127.0.0.1", process->debugPort()); + QVERIFY(connection->waitForConnected()); + + QTRY_COMPARE(client->state(), QQmlEngineDebugClient::Enabled); + QTRY_COMPARE(engineClient->state(), QQmlEngineDebugClient::Enabled); + client->connect(); + + // "a" not accessible without extra context + client->evaluate(QLatin1String("a + 10"), -1, -1); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(failure()))); + + bool success = false; + engineClient->queryAvailableEngines(&success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(engineClient.data(), SIGNAL(result()))); + + QVERIFY(engineClient->engines().count()); + engineClient->queryRootContexts(engineClient->engines()[0].debugId, &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(engineClient.data(), SIGNAL(result()))); + + auto contexts = engineClient->rootContext().contexts; + QCOMPARE(contexts.count(), 1); + auto objects = contexts[0].objects; + QCOMPARE(objects.count(), 1); + engineClient->queryObjectRecursive(objects[0], &success); + QVERIFY(success); + QVERIFY(QQmlDebugTest::waitForSignal(engineClient.data(), SIGNAL(result()))); + auto object = engineClient->object(); + + // "a" accessible in context of surrounding object + client->evaluate(QLatin1String("a + 10"), -1, object.debugId); + QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(result()))); + + QString jsonString = client->response; + QVariantMap value = client->parser.call(QJSValueList() << QJSValue(jsonString)).toVariant().toMap(); + + QVariantMap body = value.value("body").toMap(); + QTRY_COMPARE(body.value("value").toInt(), 20); +} + void tst_QQmlDebugJS::getScripts() { //void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant()); diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp index a503da4e4b..8d21a8a45a 100644 --- a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp +++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp @@ -51,12 +51,6 @@ private: QQmlDebugConnection *m_conn; QQmlDebugTestService *m_service; - bool connect(); - -signals: - void waiting(); - void parallel(); - private slots: void initTestCase(); @@ -75,12 +69,13 @@ void tst_QQmlDebugLocal::initTestCase() const QString waitingMsg = QString("QML Debugger: Connecting to socket %1...").arg(fileName); QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData()); + QQmlDebuggingEnabler::connectToLocalDebugger(fileName); + + QTest::qWait(1000); m_conn = new QQmlDebugConnection(this); m_conn->startLocalServer(fileName); - QQmlDebuggingEnabler::connectToLocalDebugger(fileName); - new QQmlEngine(this); QQmlDebugTestClient client("tst_QQmlDebugLocal::handshake()", m_conn); diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp index a23b7e37eb..6793596174 100644 --- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp +++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp @@ -41,6 +41,7 @@ #include <private/qv4isel_moth_p.h> #include <private/qv4string_p.h> #include <private/qqmlbuiltinfunctions_p.h> +#include <private/qqmldebugservice_p.h> using namespace QV4; using namespace QV4::Debugging; @@ -203,8 +204,8 @@ public slots: while (!m_expressionRequests.isEmpty()) { Q_ASSERT(debugger->state() == QV4Debugger::Paused); ExpressionRequest request = m_expressionRequests.takeFirst(); - ExpressionEvalJob job(debugger->engine(), request.frameNr, request.expression, - &collector); + ExpressionEvalJob job(debugger->engine(), request.frameNr, request.context, + request.expression, &collector); debugger->runInEngine(&job); m_expressionResults << job.returnValue(); m_expressionRefs << job.refs(); @@ -276,6 +277,7 @@ public: struct ExpressionRequest { QString expression; int frameNr; + int context; }; QVector<ExpressionRequest> m_expressionRequests; QList<QJsonObject> m_expressionResults; @@ -726,24 +728,34 @@ void tst_qv4debugger::evaluateExpression() TestAgent::ExpressionRequest request; request.expression = "x"; request.frameNr = 0; + request.context = -1; // no extra context m_debuggerAgent->m_expressionRequests << request; request.expression = "x"; request.frameNr = 1; m_debuggerAgent->m_expressionRequests << request; + request.context = 5355; // invalid context object + m_debuggerAgent->m_expressionRequests << request; + + QObject object; // some object without QML context + request.context = QQmlDebugService::idForObject(&object); + m_debuggerAgent->m_expressionRequests << request; + debugger()->addBreakPoint("evaluateExpression", 3); evaluateJavaScript(script, "evaluateExpression"); - QCOMPARE(m_debuggerAgent->m_expressionRefs.count(), 2); + 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(result0.value("type").toString(), QStringLiteral("number")); QCOMPARE(result0.value("value").toInt(), 10); - QCOMPARE(m_debuggerAgent->m_expressionRefs[1].size(), 1); - QJsonObject result1 = m_debuggerAgent->m_expressionRefs[1].first().toObject(); - QCOMPARE(result1.value("type").toString(), QStringLiteral("number")); - QCOMPARE(result1.value("value").toInt(), 20); + for (int i = 1; i < 4; ++i) { + QCOMPARE(m_debuggerAgent->m_expressionRefs[i].size(), 1); + QJsonObject result1 = m_debuggerAgent->m_expressionRefs[1].first().toObject(); + QCOMPARE(result1.value("type").toString(), QStringLiteral("number")); + QCOMPARE(result1.value("value").toInt(), 20); + } } QTEST_MAIN(tst_qv4debugger) diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 52df4c0642..82bc3d0c59 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -1040,6 +1040,8 @@ void tst_QJSEngine::builtinFunctionNames_data() QTest::newRow("Array.prototype.toString") << QString("Array.prototype.toString") << QString("toString"); QTest::newRow("Array.prototype.toLocaleString") << QString("Array.prototype.toLocaleString") << QString("toLocaleString"); QTest::newRow("Array.prototype.concat") << QString("Array.prototype.concat") << QString("concat"); + QTest::newRow("Array.prototype.find") << QString("Array.prototype.find") << QString("find"); + QTest::newRow("Array.prototype.findIndex") << QString("Array.prototype.findIndex") << QString("findIndex"); QTest::newRow("Array.prototype.join") << QString("Array.prototype.join") << QString("join"); QTest::newRow("Array.prototype.pop") << QString("Array.prototype.pop") << QString("pop"); QTest::newRow("Array.prototype.push") << QString("Array.prototype.push") << QString("push"); @@ -2149,12 +2151,27 @@ void tst_QJSEngine::jsNumberClass() QJSValue ret = eng.evaluate("new Number(123).toExponential()"); QVERIFY(ret.isString()); QCOMPARE(ret.toString(), QString::fromLatin1("1.23e+2")); + ret = eng.evaluate("new Number(123).toExponential(1)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("1.2e+2")); + ret = eng.evaluate("new Number(123).toExponential(2)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("1.23e+2")); + ret = eng.evaluate("new Number(123).toExponential(3)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("1.230e+2")); } QVERIFY(proto.property("toFixed").isCallable()); { QJSValue ret = eng.evaluate("new Number(123).toFixed()"); QVERIFY(ret.isString()); QCOMPARE(ret.toString(), QString::fromLatin1("123")); + ret = eng.evaluate("new Number(123).toFixed(1)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("123.0")); + ret = eng.evaluate("new Number(123).toFixed(2)"); + QVERIFY(ret.isString()); + QCOMPARE(ret.toString(), QString::fromLatin1("123.00")); } QVERIFY(proto.property("toPrecision").isCallable()); { diff --git a/tests/auto/qml/qqmlmoduleplugin/data/works22.qml b/tests/auto/qml/qqmlmoduleplugin/data/works22.qml new file mode 100644 index 0000000000..571a7e754d --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/data/works22.qml @@ -0,0 +1,3 @@ +import org.qtproject.AutoTestQmlPluginType 2.2 + +MyPluginType { valueOnlyIn2: 123 } diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.2.2.pro b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.2.2.pro new file mode 100644 index 0000000000..eec5f23a7b --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.2.2.pro @@ -0,0 +1,12 @@ +TEMPLATE = lib +CONFIG += plugin +SOURCES = plugin.cpp +QT = core qml +DESTDIR = ../imports/org/qtproject/AutoTestQmlPluginType.2.2 + +QT += core-private gui-private qml-private + +IMPORT_FILES = \ + qmldir + +include (../../../shared/imports.pri) diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp new file mode 100644 index 0000000000..ecec870374 --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 <QStringList> +#include <QtQml/qqmlextensionplugin.h> +#include <QtQml/qqml.h> +#include <QDebug> + +class MyPluginType : public QObject +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue) + Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue) + +public: + MyPluginType(QObject *parent=0) : QObject(parent) + { + qWarning("import2.2 worked"); + } + + int value() const { return v; } + void setValue(int i) { v = i; } + +private: + int v; +}; + + +class MyPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + MyPlugin() + { + qWarning("plugin2.2 created"); + } + + void registerTypes(const char *uri) + { + Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType"); + qmlRegisterType<MyPluginType>(uri, 2, 0, "MyPluginType"); + qmlRegisterModule(uri, 2, 2); + } +}; + +#include "plugin.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/qmldir new file mode 100644 index 0000000000..0a8b5d46eb --- /dev/null +++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/qmldir @@ -0,0 +1 @@ +plugin plugin diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro index 889968f6cc..0f548aa6f8 100644 --- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro +++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro @@ -20,7 +20,8 @@ SUBDIRS =\ protectedModule\ plugin/childplugin\ plugin.2/childplugin\ - plugin.2.1/childplugin + plugin.2.1/childplugin\ + plugin.2.2 tst_qqmlmoduleplugin_pro.depends += plugin SUBDIRS += tst_qqmlmoduleplugin.pro diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index 265492b435..8600e1e8ab 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -52,8 +52,7 @@ public: private slots: virtual void initTestCase(); void importsPlugin(); - void importsPlugin2(); - void importsPlugin21(); + void importsPlugin_data(); void importsMixedQmlCppPlugin(); void incorrectPluginCase(); void importPluginWithQmlFile(); @@ -70,6 +69,7 @@ private slots: void importStrictModule(); void importStrictModule_data(); void importProtectedModule(); + void importVersionedModule(); void importsChildPlugin(); void importsChildPlugin2(); void importsChildPlugin21(); @@ -130,29 +130,15 @@ void tst_qqmlmoduleplugin::initTestCase() void tst_qqmlmoduleplugin::importsPlugin() { - QQmlEngine engine; - engine.addImportPath(m_importsDirectory); - QTest::ignoreMessage(QtWarningMsg, "plugin created"); - QTest::ignoreMessage(QtWarningMsg, "import worked"); - QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations."); - QQmlComponent component(&engine, testFileUrl(QStringLiteral("works.qml"))); - foreach (QQmlError err, component.errors()) - qWarning() << err; - VERIFY_ERRORS(0); - QObject *object = component.create(); - QVERIFY(object != 0); - QCOMPARE(object->property("value").toInt(),123); - delete object; -} + QFETCH(QString, suffix); + QFETCH(QString, qmlFile); -void tst_qqmlmoduleplugin::importsPlugin2() -{ QQmlEngine engine; engine.addImportPath(m_importsDirectory); - QTest::ignoreMessage(QtWarningMsg, "plugin2 created"); - QTest::ignoreMessage(QtWarningMsg, "import2 worked"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(QString("plugin%1 created").arg(suffix))); + QTest::ignoreMessage(QtWarningMsg, qPrintable(QString("import%1 worked").arg(suffix))); QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations."); - QQmlComponent component(&engine, testFileUrl(QStringLiteral("works2.qml"))); + QQmlComponent component(&engine, testFileUrl(qmlFile)); foreach (QQmlError err, component.errors()) qWarning() << err; VERIFY_ERRORS(0); @@ -162,21 +148,15 @@ void tst_qqmlmoduleplugin::importsPlugin2() delete object; } -void tst_qqmlmoduleplugin::importsPlugin21() +void tst_qqmlmoduleplugin::importsPlugin_data() { - QQmlEngine engine; - engine.addImportPath(m_importsDirectory); - QTest::ignoreMessage(QtWarningMsg, "plugin2.1 created"); - QTest::ignoreMessage(QtWarningMsg, "import2.1 worked"); - QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations."); - QQmlComponent component(&engine, testFileUrl(QStringLiteral("works21.qml"))); - foreach (QQmlError err, component.errors()) - qWarning() << err; - VERIFY_ERRORS(0); - QObject *object = component.create(); - QVERIFY(object != 0); - QCOMPARE(object->property("value").toInt(),123); - delete object; + QTest::addColumn<QString>("suffix"); + QTest::addColumn<QString>("qmlFile"); + + QTest::newRow("1.0") << "" << "works.qml"; + QTest::newRow("2.0") << "2" << "works2.qml"; + QTest::newRow("2.1") << "2.1" << "works21.qml"; + QTest::newRow("2.2") << "2.2" << "works22.qml"; } void tst_qqmlmoduleplugin::incorrectPluginCase() @@ -578,6 +558,32 @@ void tst_qqmlmoduleplugin::importProtectedModule() QVERIFY(object != 0); } +void tst_qqmlmoduleplugin::importVersionedModule() +{ + qmlRegisterType<QObject>("org.qtproject.VersionedModule", 1, 0, "TestType"); + qmlRegisterModule("org.qtproject.VersionedModule", 1, 1); + + QQmlEngine engine; + engine.addImportPath(m_importsDirectory); + + QUrl url(testFileUrl("empty.qml")); + + QQmlComponent component(&engine); + component.setData("import org.qtproject.VersionedModule 1.0\n TestType {}\n", url); + QScopedPointer<QObject> object10(component.create()); + QVERIFY(!object10.isNull()); + + component.setData("import org.qtproject.VersionedModule 1.1\n TestType {}\n", url); + QScopedPointer<QObject> object11(component.create()); + QVERIFY(!object11.isNull()); + + component.setData("import org.qtproject.VersionedModule 1.2\n TestType {}\n", url); + QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready"); + QScopedPointer<QObject> object12(component.create()); + QVERIFY(object12.isNull()); + QCOMPARE(component.errorString(), QString("%1:1 module \"org.qtproject.VersionedModule\" version 1.2 is not installed\n").arg(url.toString())); +} + void tst_qqmlmoduleplugin::importsChildPlugin() { QQmlEngine engine; diff --git a/tests/auto/qmltest-blacklist/animators/tst_stopped.qml b/tests/auto/qmltest-blacklist/animators/tst_stopped.qml new file mode 100644 index 0000000000..a70da63e13 --- /dev/null +++ b/tests/auto/qmltest-blacklist/animators/tst_stopped.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.1 + +Item { + id: root; + width: 200 + height: 200 + + TestCase { + id: testcase + name: "animators-stopped" + when: false + function test_endresult() { + verify(true); + } + } + + ShaderEffect { + id: shaderEffect + property real t; + width: 10 + height: 10 + + fragmentShader: " + highp uniform float t; + void main() { + gl_FragColor = vec4(t, t, t, 1.0); + } + " + UniformAnimator { id: uniformAnimator; target: shaderEffect; uniform: "t"; loops: Animation.Infinite; running: true; } + } + + Box { + id: box + + ScaleAnimator { id: scaleAnimator; target: box; loops: Animation.Infinite; running: true; } + XAnimator { id: xAnimator; target: box; loops: Animation.Infinite; running: true; } + YAnimator { id: yAnimator; target: box; loops: Animation.Infinite; running: true; } + RotationAnimator { id: rotationAnimator; target: box; loops: Animation.Infinite; running: true; } + OpacityAnimator { id: opacityAnimator; target: box; loops: Animation.Infinite; running: true; } + + Timer { + id: timer; + interval: 500 + running: true + repeat: false + onTriggered: { + xAnimator.stop(); + yAnimator.stop(); + scaleAnimator.stop() + rotationAnimator.stop(); + rotationAnimator.stop(); + uniformAnimator.stop(); + testcase.when = true; + } + } + } +} diff --git a/tests/auto/qmltest/events/tst_events.qml b/tests/auto/qmltest/events/tst_events.qml index e655c26c7d..d9868a316c 100644 --- a/tests/auto/qmltest/events/tst_events.qml +++ b/tests/auto/qmltest/events/tst_events.qml @@ -27,6 +27,7 @@ ****************************************************************************/ import QtQuick 2.0 +import QtQuick.Window 2.0 import QtTest 1.1 Rectangle { @@ -56,6 +57,16 @@ Rectangle { signalName: "doubleClickSignalHelper" } + Window { + id: sub + visible: true + property bool clicked: false + MouseArea { + anchors.fill: parent + onClicked: sub.clicked = true + } + } + MouseArea { anchors.fill: parent onClicked: { @@ -89,6 +100,11 @@ Rectangle { tryCompare(top, "mouseHasBeenClicked", true, 10000) } + function test_mouse_click_subwindow() { + mouseClick(sub) + tryCompare(sub, "clicked", true, 10000) + } + function test_mouse_doubleclick() { doubleClickSpy.clear() mouseDoubleClickSequence(top, 25, 30) diff --git a/tests/auto/qmltest/events/tst_touch.qml b/tests/auto/qmltest/events/tst_touch.qml new file mode 100644 index 0000000000..5b209a6d0b --- /dev/null +++ b/tests/auto/qmltest/events/tst_touch.qml @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Jeremy Katz +** 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$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.0 +import QtTest 1.0 + +MultiPointTouchArea { + id: touchArea + width: 100 + height: 100 + + SignalSpy { + id: touchUpdatedSpy + target: touchArea + signalName: "touchUpdated" + } + + SignalSpy { + id: interiorSpy + target: interior + signalName: "touchUpdated" + } + + MultiPointTouchArea { + id: interior + width: parent.width / 2 + height: parent.height + anchors.right: parent.right + } + + Window { + width: 100; height: 100 + + SignalSpy { + id: subWindowSpy + target: subWindowTouchArea + signalName: "touchUpdated" + } + + MultiPointTouchArea { + id: subWindowTouchArea + anchors.fill: parent + } + } + + TestCase { + when: windowShown + name: "touch" + + function comparePoint(point, id, x, y) { + var retval = true; + var pointId = point.pointId & 0xFFFFFF; //strip device identifier + if (pointId !== id) { + warn("Unexpected pointId: " + pointId + ". Expected " + id); + retval = false; + } + if (point.x !== x) { + warn("Unexpected x: " + point.x + ". Expected " + x); + retval = false; + } + if (point.y !== y) { + warn("Unexpected y: " + point.y + ". Expected " + y); + retval = false; + } + return retval; + } + + function cleanup() { + touchUpdatedSpy.clear(); + interiorSpy.clear(); + subWindowSpy.clear(); + } + + function test_secondWindow() { + var first = 1; + var sequence = touchEvent(subWindowTouchArea); + sequence.press(first, 0, 0, 0); + sequence.commit(); + sequence.release(first, subWindowTouchArea, 0, 0) + sequence.commit(); + compare(subWindowSpy.count, 2); + var touchPoint = subWindowSpy.signalArguments[0][0][0]; + verify(comparePoint(touchPoint, first, 0, 0)); + } + + function initTestCase() { + waitForRendering(touchArea) // when: windowShown may be insufficient + } + + function test_childMapping() { + var sequence = touchEvent(touchArea); + + var first = 1; + // Test mapping touches to a child item + sequence.press(first, interior, 0, 0); + sequence.commit(); + + // Map touches to the parent at the same point + sequence.move(first, touchArea, interior.x, interior.y); + sequence.commit(); + + sequence.release(first, touchArea, interior.x, interior.y); + sequence.commit(); + + compare(interiorSpy.count, 3); + verify(comparePoint(interiorSpy.signalArguments[0][0][0], first, 0, 0)); + verify(comparePoint(interiorSpy.signalArguments[1][0][0], first, 0, 0)); + } + + function test_fullSequence() { + var sequence = touchEvent(touchArea); + verify(sequence); + + var first = 1; + var second = 2; + + sequence.press(first, null, 0, 0); + sequence.commit(); + compare(touchUpdatedSpy.count, 1); + var touchPoints = touchUpdatedSpy.signalArguments[0][0]; + compare(touchPoints.length, 1); + verify(comparePoint(touchPoints[0], first, 0, 0)); + + sequence.stationary(first); + sequence.press(second, null, 1, 0); + sequence.commit(); + compare(touchUpdatedSpy.count, 2); + touchPoints = touchUpdatedSpy.signalArguments[1][0]; + compare(touchPoints.length, 2); + verify(comparePoint(touchPoints[0], first, 0, 0)); + verify(comparePoint(touchPoints[1], second, 1, 0)); + + sequence.release(first); + sequence.move(second, null, 1, 1); + sequence.commit(); + compare(touchUpdatedSpy.count, 3); + touchPoints = touchUpdatedSpy.signalArguments[2][0]; + compare(touchPoints.length, 1); + verify(comparePoint(touchPoints[0], second, 1, 1)); + + sequence.release(second, null, 0, 1); + sequence.commit(); + compare(touchUpdatedSpy.count, 4); + touchPoints = touchUpdatedSpy.signalArguments[3][0]; + compare(touchPoints.length, 0); + } + + function test_simpleChain() { + var first = 1; + touchEvent(touchArea).press(first).commit().release(first).commit(); + compare(touchUpdatedSpy.count, 2); + var touchPoint = touchUpdatedSpy.signalArguments[0][0][0]; + verify(comparePoint(touchPoint, first, touchArea.width / 2, touchArea.height / 2)); + } + } +} diff --git a/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml b/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml new file mode 100644 index 0000000000..5f1e802df2 --- /dev/null +++ b/tests/auto/qmltest/selftests/tst_createTemporaryObject.qml @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQuick.Window 2.2 +import QtTest 1.2 + +TestCase { + id: testCase + name: "tst_createTemporaryObject" + width: 100 + height: 100 + when: windowShown + + property var createdObjectNames: [] + property var createdParentlessObjects: [] + + function verifyNoChildren() { + for (var i = 0; i < createdObjectNames.length; ++i) { + verify(!findChild(testCase, createdObjectNames[i])); + } + + compare(createdParentlessObjects.length, 0, + "The following parentless temporary objects were not destroyed: " + createdParentlessObjects) + } + + function init() { + // The items are destroyed after cleanup(), so we check here after every test, + // and once for the last test in cleanupTestCase(). + verifyNoChildren(); + } + + function cleanupTestCase() { + verifyNoChildren(); + } + + function test_fromQml_data() { + return [ + { tag: "QtObject", qml: "import QtQml 2.0; QtObject {}" }, + { tag: "Item", qml: "import QtQuick 2.0; Item {}" }, + ]; + } + + function test_fromQml(data) { + var object = createTemporaryQmlObject(data.qml, testCase); + verify(object); + + object.objectName = data.tag + "FromQml"; + compare(findChild(testCase, object.objectName), object); + + createdObjectNames.push(object.objectName); + + // Create an object and destroy it early. It should be + // removed from TestCase's list of temporary objects + // as soon as it's destroyed. + var manuallyDestroyedObject = createTemporaryQmlObject(data.qml, testCase); + verify(manuallyDestroyedObject); + + var manuallyDestroyedObjectName = data.tag + "FromQmlShortLived"; + manuallyDestroyedObject.objectName = manuallyDestroyedObjectName; + compare(findChild(testCase, manuallyDestroyedObjectName), manuallyDestroyedObject); + + manuallyDestroyedObject.destroy(); + wait(0); + + verify(!findChild(testCase, manuallyDestroyedObjectName)); + } + + Component { + id: objectComponent + + QtObject {} + } + + Component { + id: itemComponent + + Item {} + } + + Component { + id: windowComponent + + Window {} + } + + function test_fromComponent_data() { + return [ + { tag: "QtObject", component: objectComponent }, + { tag: "Item", component: itemComponent }, + { tag: "Window", component: windowComponent }, + ]; + } + + function test_fromComponent(data) { + var object = createTemporaryObject(data.component, testCase); + verify(object); + + object.objectName = data.tag + "FromComponent"; + compare(findChild(testCase, object.objectName), object); + + if (object.hasOwnProperty("contentItem")) + object.contentItem.objectName = "WindowContentItemFromComponent"; + + createdObjectNames.push(object.objectName); + + // Create an object and destroy it early. It should be + // removed from TestCase's list of temporary objects + // as soon as it's destroyed. + var manuallyDestroyedObject = createTemporaryObject(data.component, testCase); + verify(manuallyDestroyedObject); + + var manuallyDestroyedObjectName = data.tag + "FromComponentShortLived"; + manuallyDestroyedObject.objectName = manuallyDestroyedObjectName; + compare(findChild(testCase, manuallyDestroyedObjectName), manuallyDestroyedObject); + + manuallyDestroyedObject.destroy(); + wait(0); + + verify(!findChild(testCase, manuallyDestroyedObjectName)); + } + + function test_fromComponentParent_data() { + return [ + { tag: "omit", expectedParent: null }, + { tag: "undefined", parent: undefined, expectedParent: null }, + { tag: "null", parent: null, expectedParent: null }, + { tag: "1", parent: 1, expectedParent: null }, + { tag: "testCase", parent: testCase, expectedParent: testCase } + ]; + } + + // Tests that an invalid or missing parent argument results in a parentless object. + // This is the same behavior as displayed by component.createObject(). + function test_fromComponentParent(data) { + var object = data.hasOwnProperty("parent") + ? createTemporaryObject(itemComponent, data.parent) + : createTemporaryObject(itemComponent); + verify(object); + compare(object.parent, data.expectedParent); + + object.objectName = data.tag + "FromComponentOmitParent"; + if (object.parent) { + compare(findChild(testCase, object.objectName), object); + createdObjectNames.push(object.objectName); + } else { + object.Component.destruction.connect(function() { + var indexOfObject = createdParentlessObjects.indexOf(object); + createdParentlessObjects.splice(indexOfObject, 1); + }); + createdParentlessObjects.push(object); + } + } +} diff --git a/tests/auto/quick/drawingmodes/data/DrawingModes.qml b/tests/auto/quick/drawingmodes/data/DrawingModes.qml new file mode 100644 index 0000000000..4211f247f8 --- /dev/null +++ b/tests/auto/quick/drawingmodes/data/DrawingModes.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import Test 1.0 + +Rectangle { + id: root + + width: 200 + height: 200 + color: "black" + + DrawingModeItem { + anchors.fill: parent + } +} diff --git a/tests/auto/quick/drawingmodes/drawingmodes.pro b/tests/auto/quick/drawingmodes/drawingmodes.pro new file mode 100644 index 0000000000..ff5383b501 --- /dev/null +++ b/tests/auto/quick/drawingmodes/drawingmodes.pro @@ -0,0 +1,17 @@ +CONFIG += testcase +TARGET = tst_drawingmodes +SOURCES += tst_drawingmodes.cpp + +macos:CONFIG -= app_bundle + +TESTDATA = data/* + +include(../../shared/util.pri) + +CONFIG += parallel_test +QT += gui qml quick testlib + +OTHER_FILES += \ + data/DrawingModes.qml + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp new file mode 100644 index 0000000000..d4065e3d38 --- /dev/null +++ b/tests/auto/quick/drawingmodes/tst_drawingmodes.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** 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 <qtest.h> + +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qsgnode.h> +#include <QtQuick/qsggeometry.h> +#include <QtQuick/qsgflatcolormaterial.h> +#include <QtGui/qscreen.h> +#include <QtGui/qopenglcontext.h> + +#include "../../shared/util.h" + +class tst_drawingmodes : public QQmlDataTest +{ + Q_OBJECT +public: + tst_drawingmodes(); + + bool hasPixelAround(const QImage &fb, int centerX, int centerY); + QImage runTest(const QString &fileName) + { + QQuickView view(&outerWindow); + view.setResizeMode(QQuickView::SizeViewToRootObject); + view.setSource(testFileUrl(fileName)); + view.setVisible(true); + QTest::qWaitForWindowExposed(&view); + return view.grabWindow(); + } + + //It is important for platforms that only are able to show fullscreen windows + //to have a container for the window that is painted on. + QQuickWindow outerWindow; + const QRgb black; + const QRgb red; + +private slots: + void points(); + void lines(); + void lineStrip(); + void lineLoop(); + void triangles(); + void triangleStrip(); + void triangleFan(); +}; + +class DrawingModeItem : public QQuickItem +{ + Q_OBJECT +public: + static GLenum drawingMode; + + DrawingModeItem() : first(QSGGeometry::defaultAttributes_Point2D(), 5), + second(QSGGeometry::defaultAttributes_Point2D(), 5) + { + setFlag(ItemHasContents, true); + material.setColor(Qt::red); + } + +protected: + QSGGeometry first; + QSGGeometry second; + QSGFlatColorMaterial material; + + virtual QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) + { + if (!node) { + QRect bounds(0, 0, 200, 200); + first.setDrawingMode(drawingMode); + second.setDrawingMode(drawingMode); + + QSGGeometry::Point2D *v = first.vertexDataAsPoint2D(); + v[0].set(bounds.width() * 2 / 8, bounds.height() / 2); + v[1].set(bounds.width() / 8, bounds.height() / 4); + v[2].set(bounds.width() * 3 / 8, bounds.height() / 4); + v[3].set(bounds.width() * 3 / 8, bounds.height() * 3 / 4); + v[4].set(bounds.width() / 8, bounds.height() * 3 / 4); + + v = second.vertexDataAsPoint2D(); + v[0].set(bounds.width() * 6 / 8, bounds.height() / 2); + v[1].set(bounds.width() * 5 / 8, bounds.height() / 4); + v[2].set(bounds.width() * 7 / 8, bounds.height() / 4); + v[3].set(bounds.width() * 7 / 8, bounds.height() * 3 / 4); + v[4].set(bounds.width() * 5 / 8, bounds.height() * 3 / 4); + + node = new QSGNode; + QSGGeometryNode *child = new QSGGeometryNode; + child->setGeometry(&first); + child->setMaterial(&material); + node->appendChildNode(child); + child = new QSGGeometryNode; + child->setGeometry(&second); + child->setMaterial(&material); + node->appendChildNode(child); + } + return node; + } +}; + +GLenum DrawingModeItem::drawingMode; + +bool tst_drawingmodes::hasPixelAround(const QImage &fb, int centerX, int centerY) { + for (int x = centerX - 2; x <= centerX + 2; ++x) { + for (int y = centerY - 2; y <= centerY + 2; ++y) { + if (fb.pixel(x, y) == red) + return true; + } + } + return false; +} + +tst_drawingmodes::tst_drawingmodes() : black(qRgb(0, 0, 0)), red(qRgb(0xff, 0, 0)) +{ + qmlRegisterType<DrawingModeItem>("Test", 1, 0, "DrawingModeItem"); + outerWindow.showNormal(); + outerWindow.setGeometry(0,0,400,400); +} + +void tst_drawingmodes::points() +{ + DrawingModeItem::drawingMode = GL_POINTS; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + +#ifdef Q_OS_WIN + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) + QSKIP("ANGLE cannot draw GL_POINTS."); +#endif + + QImage fb = runTest("DrawingModes.qml"); + + QVERIFY(hasPixelAround(fb, 50, 100)); + QVERIFY(hasPixelAround(fb, 25, 50)); + QVERIFY(hasPixelAround(fb, 75, 50)); + QVERIFY(hasPixelAround(fb, 75, 150)); + QVERIFY(hasPixelAround(fb, 25, 150)); + + QVERIFY(hasPixelAround(fb, 150, 100)); + QVERIFY(hasPixelAround(fb, 125, 50)); + QVERIFY(hasPixelAround(fb, 175, 50)); + QVERIFY(hasPixelAround(fb, 175, 150)); + QVERIFY(hasPixelAround(fb, 125, 150)); + + QVERIFY(!hasPixelAround(fb, 135, 70)); + QVERIFY(!hasPixelAround(fb, 175, 100)); + QVERIFY(!hasPixelAround(fb, 110, 140)); + QVERIFY(!hasPixelAround(fb, 50, 50)); + QVERIFY(!hasPixelAround(fb, 50, 150)); + QVERIFY(!hasPixelAround(fb, 25, 100)); + QVERIFY(!hasPixelAround(fb, 75, 100)); + QVERIFY(!hasPixelAround(fb, 125, 100)); + QVERIFY(!hasPixelAround(fb, 150, 50)); + QVERIFY(!hasPixelAround(fb, 150, 150)); + QVERIFY(!hasPixelAround(fb, 135, 130)); + QVERIFY(!hasPixelAround(fb, 35, 130)); +} + +void tst_drawingmodes::lines() +{ + DrawingModeItem::drawingMode = GL_LINES; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 135, 70)); + QVERIFY(hasPixelAround(fb, 175, 100)); + QVERIFY(!hasPixelAround(fb, 110, 140)); + QVERIFY(!hasPixelAround(fb, 50, 50)); + QVERIFY(!hasPixelAround(fb, 50, 150)); + + QVERIFY(hasPixelAround(fb, 35, 70)); + QVERIFY(hasPixelAround(fb, 75, 100)); + QVERIFY(!hasPixelAround(fb, 25, 100)); + QVERIFY(!hasPixelAround(fb, 125, 100)); + QVERIFY(!hasPixelAround(fb, 150, 50)); + QVERIFY(!hasPixelAround(fb, 150, 150)); + QVERIFY(!hasPixelAround(fb, 135, 130)); + QVERIFY(!hasPixelAround(fb, 35, 130)); +} + +void tst_drawingmodes::lineStrip() +{ + DrawingModeItem::drawingMode = GL_LINE_STRIP; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 135, 70)); + QVERIFY(hasPixelAround(fb, 150, 50)); + QVERIFY(hasPixelAround(fb, 175, 100)); + QVERIFY(hasPixelAround(fb, 150, 150)); + + QVERIFY(hasPixelAround(fb, 35, 70)); + QVERIFY(hasPixelAround(fb, 50, 50)); + QVERIFY(hasPixelAround(fb, 75, 100)); + QVERIFY(hasPixelAround(fb, 50, 150)); + + QVERIFY(!hasPixelAround(fb, 110, 140)); // bad line not there => line strip unbatched + + QVERIFY(!hasPixelAround(fb, 25, 100)); + QVERIFY(!hasPixelAround(fb, 125, 100)); + QVERIFY(!hasPixelAround(fb, 135, 130)); + QVERIFY(!hasPixelAround(fb, 35, 130)); +} + +void tst_drawingmodes::lineLoop() +{ + DrawingModeItem::drawingMode = GL_LINE_LOOP; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 135, 70)); + QVERIFY(hasPixelAround(fb, 135, 130)); + QVERIFY(hasPixelAround(fb, 150, 50)); + QVERIFY(hasPixelAround(fb, 175, 100)); + QVERIFY(hasPixelAround(fb, 150, 150)); + + QVERIFY(hasPixelAround(fb, 35, 70)); + QVERIFY(hasPixelAround(fb, 35, 130)); + QVERIFY(hasPixelAround(fb, 50, 50)); + QVERIFY(hasPixelAround(fb, 75, 100)); + QVERIFY(hasPixelAround(fb, 50, 150)); + + QVERIFY(!hasPixelAround(fb, 110, 140)); // bad line not there => line loop unbatched + + QVERIFY(!hasPixelAround(fb, 25, 100)); + QVERIFY(!hasPixelAround(fb, 125, 100)); +} + +void tst_drawingmodes::triangles() +{ + DrawingModeItem::drawingMode = GL_TRIANGLES; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 150, 75)); + QVERIFY(!hasPixelAround(fb, 162, 100)); + QVERIFY(!hasPixelAround(fb, 150, 125)); + QVERIFY(!hasPixelAround(fb, 137, 100)); + + QVERIFY(!hasPixelAround(fb, 100, 125)); + + QVERIFY(hasPixelAround(fb, 50, 75)); + QVERIFY(!hasPixelAround(fb, 62, 100)); + QVERIFY(!hasPixelAround(fb, 50, 125)); + QVERIFY(!hasPixelAround(fb, 37, 100)); +} + + +void tst_drawingmodes::triangleStrip() +{ + DrawingModeItem::drawingMode = GL_TRIANGLE_STRIP; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 150, 75)); + QVERIFY(hasPixelAround(fb, 162, 100)); + QVERIFY(hasPixelAround(fb, 150, 125)); + QVERIFY(!hasPixelAround(fb, 137, 100)); + + QVERIFY(!hasPixelAround(fb, 100, 125)); // batching avoids extra triangle by duplicating vertices. + + QVERIFY(hasPixelAround(fb, 50, 75)); + QVERIFY(hasPixelAround(fb, 62, 100)); + QVERIFY(hasPixelAround(fb, 50, 125)); + QVERIFY(!hasPixelAround(fb, 37, 100)); +} + +void tst_drawingmodes::triangleFan() +{ + DrawingModeItem::drawingMode = GL_TRIANGLE_FAN; + if (QGuiApplication::primaryScreen()->depth() < 24) + QSKIP("This test does not work at display depths < 24"); + QImage fb = runTest("DrawingModes.qml"); + + QCOMPARE(fb.width(), 200); + QCOMPARE(fb.height(), 200); + + QVERIFY(hasPixelAround(fb, 150, 75)); + QVERIFY(hasPixelAround(fb, 162, 100)); + QVERIFY(hasPixelAround(fb, 150, 125)); + QVERIFY(!hasPixelAround(fb, 137, 100)); + + QVERIFY(!hasPixelAround(fb, 100, 125)); // no extra triangle; triangle fan is not batched + + QVERIFY(hasPixelAround(fb, 50, 75)); + QVERIFY(hasPixelAround(fb, 62, 100)); + QVERIFY(hasPixelAround(fb, 50, 125)); + QVERIFY(!hasPixelAround(fb, 37, 100)); +} + + +QTEST_MAIN(tst_drawingmodes) + +#include "tst_drawingmodes.moc" diff --git a/tests/auto/quick/qquickapplication/data/tst_displayname.qml b/tests/auto/quick/qquickapplication/data/tst_displayname.qml new file mode 100644 index 0000000000..f43beaf6de --- /dev/null +++ b/tests/auto/quick/qquickapplication/data/tst_displayname.qml @@ -0,0 +1,7 @@ +import QtQuick 2.0; + +Item { + id: root; + property string displayName: Qt.application.displayName; + function updateDisplayName(name) { Qt.application.displayName = name; } +} diff --git a/tests/auto/quick/qquickapplication/qquickapplication.pro b/tests/auto/quick/qquickapplication/qquickapplication.pro index 59445a6c16..c47f5472b7 100644 --- a/tests/auto/quick/qquickapplication/qquickapplication.pro +++ b/tests/auto/quick/qquickapplication/qquickapplication.pro @@ -3,5 +3,11 @@ TARGET = tst_qquickapplication macx:CONFIG -= app_bundle SOURCES += tst_qquickapplication.cpp +OTHER_FILES += data/tst_displayname.qml + +include (../../shared/util.pri) + +TESTDATA = data/* + QT += core-private gui-private qml quick qml-private quick-private testlib diff --git a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp index 114f906736..d780b91260 100644 --- a/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp +++ b/tests/auto/quick/qquickapplication/tst_qquickapplication.cpp @@ -36,8 +36,9 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> +#include "../../shared/util.h" -class tst_qquickapplication : public QObject +class tst_qquickapplication : public QQmlDataTest { Q_OBJECT public: @@ -51,6 +52,7 @@ private slots: void inputMethod(); void styleHints(); void cleanup(); + void displayName(); private: QQmlEngine engine; @@ -239,6 +241,29 @@ void tst_qquickapplication::styleHints() QCOMPARE(qvariant_cast<QObject*>(item->property("styleHints")), qApp->styleHints()); } +void tst_qquickapplication::displayName() +{ + QString name[3] = { QStringLiteral("APP NAME 0"), + QStringLiteral("APP NAME 1"), + QStringLiteral("APP NAME 2") + }; + + QQmlComponent component(&engine, testFileUrl("tst_displayname.qml")); + QQuickItem *item = qobject_cast<QQuickItem *>(component.create()); + QVERIFY(item); + QQuickView view; + item->setParentItem(view.rootObject()); + + QCoreApplication::setApplicationName(name[0]); + QCOMPARE(qvariant_cast<QString>(item->property("displayName")), name[0]); + + QGuiApplication::setApplicationName(name[1]); + QCOMPARE(qvariant_cast<QString>(item->property("displayName")), name[1]); + + QMetaObject::invokeMethod(item, "updateDisplayName", Q_ARG(QVariant, QVariant(name[2]))); + QCOMPARE(QGuiApplication::applicationDisplayName(), name[2]); +} + QTEST_MAIN(tst_qquickapplication) #include "tst_qquickapplication.moc" diff --git a/tests/auto/quick/qquickitem/data/shortcutOverride.qml b/tests/auto/quick/qquickitem/data/shortcutOverride.qml new file mode 100644 index 0000000000..fab9175c17 --- /dev/null +++ b/tests/auto/quick/qquickitem/data/shortcutOverride.qml @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** 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.8 +import QtQuick.Window 2.1 + +Item { + property int escapeHandlerActivationCount: 0 + property int shortcutActivationCount: 0 + property alias escapeItem: escapeItem + + Item { + id: escapeItem + objectName: "escapeItem" + focus: true + + // By accepting shortcut override events when the key is Qt.Key_Escape, + // we can ensure that our Keys.onEscapePressed handler (below) will be called. + Keys.onShortcutOverride: event.accepted = (event.key === Qt.Key_Escape) + + Keys.onEscapePressed: { + // Pretend that we just did some really important stuff that was triggered + // by the escape key (like might occur in a popup that has a keyboard shortcut editor, for example). + // Now that we're done, we no longer need focus, so we won't accept future shorcut override events. + focus = false; + event.accepted = true; + ++escapeHandlerActivationCount; + } + } + + Shortcut { + sequence: "Escape" + onActivated: ++shortcutActivationCount + } +} diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index d0139b6cdf..8d974f4d17 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -172,6 +172,8 @@ private slots: void ignoreButtonPressNotInAcceptedMouseButtons(); + void shortcutOverride(); + private: enum PaintOrderOp { @@ -2036,6 +2038,39 @@ void tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() QCOMPARE(item.releaseCount, 1); } +void tst_qquickitem::shortcutOverride() +{ + QQuickView view; + view.setSource(testFileUrl("shortcutOverride.qml")); + ensureFocus(&view); + + QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 0); + QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 0); + + QQuickItem *escapeItem = view.rootObject()->property("escapeItem").value<QQuickItem*>(); + QVERIFY(escapeItem); + QVERIFY(escapeItem->hasActiveFocus()); + + // escapeItem's onEscapePressed handler should accept the first escape press event. + QTest::keyPress(&view, Qt::Key_Escape); + QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 1); + QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 0); + // Now it shouldn't have focus, so it can't handle the next escape press event. + QVERIFY(!escapeItem->hasActiveFocus()); + + QTest::keyRelease(&view, Qt::Key_Escape); + QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 1); + QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 0); + + QTest::keyPress(&view, Qt::Key_Escape); + QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 1); + QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 1); + + QTest::keyRelease(&view, Qt::Key_Escape); + QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount").toInt(), 1); + QCOMPARE(view.rootObject()->property("shortcutActivationCount").toInt(), 1); +} + QTEST_MAIN(tst_qquickitem) #include "tst_qquickitem.moc" diff --git a/tests/auto/quick/qquickmousearea/data/pressAndHold.qml b/tests/auto/quick/qquickmousearea/data/pressAndHold.qml new file mode 100644 index 0000000000..bde195965e --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/pressAndHold.qml @@ -0,0 +1,12 @@ +import QtQuick 2.9 + +Item { + width: 100 + height: 100 + + MouseArea { + id: mouseArea + objectName: "mouseArea" + anchors.fill: parent + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index e1f903123b..c8351b9e18 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -127,6 +127,8 @@ private slots: void containsPress(); void ignoreBySource(); void notPressedAfterStolenGrab(); + void pressAndHold_data(); + void pressAndHold(); private: int startDragDistance() const { @@ -2098,6 +2100,49 @@ void tst_QQuickMouseArea::notPressedAfterStolenGrab() QVERIFY(!ma->pressed()); } +void tst_QQuickMouseArea::pressAndHold_data() +{ + QTest::addColumn<int>("pressAndHoldInterval"); + QTest::addColumn<int>("waitTime"); + + QTest::newRow("default") << -1 << QGuiApplication::styleHints()->mousePressAndHoldInterval(); + QTest::newRow("short") << 500 << 500; + QTest::newRow("long") << 1000 << 1000; +} + +void tst_QQuickMouseArea::pressAndHold() +{ + QFETCH(int, pressAndHoldInterval); + QFETCH(int, waitTime); + + QQuickView window; + QByteArray errorMessage; + QVERIFY2(initView(window, testFileUrl("pressAndHold.qml"), true, &errorMessage), errorMessage.constData()); + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QQuickItem *root = window.rootObject(); + QVERIFY(root != 0); + + QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea"); + QVERIFY(mouseArea != 0); + + QSignalSpy pressAndHoldSpy(mouseArea, &QQuickMouseArea::pressAndHold); + + if (pressAndHoldInterval > -1) + mouseArea->setPressAndHoldInterval(pressAndHoldInterval); + else + mouseArea->resetPressAndHoldInterval(); + + QElapsedTimer t; + t.start(); + QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50)); + QVERIFY(pressAndHoldSpy.wait()); + // should be off by no more than 20% of waitTime + QVERIFY(qAbs(t.elapsed() - waitTime) < (waitTime * 0.2)); + QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(50, 50)); +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" diff --git a/tests/auto/quick/qquickscreen/data/screen.qml b/tests/auto/quick/qquickscreen/data/screen.qml index c246b3cd83..cf60d0ae40 100644 --- a/tests/auto/quick/qquickscreen/data/screen.qml +++ b/tests/auto/quick/qquickscreen/data/screen.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import QtQuick.Window 2.0 as Window +import QtQuick.Window 2.3 as Window Item { width: 100 @@ -10,6 +10,18 @@ Item { property int priOrientation: Window.Screen.primaryOrientation property int updateMask: Window.Screen.orientationUpdateMask property real devicePixelRatio: Window.Screen.devicePixelRatio + property int vx: Window.Screen.virtualX + property int vy: Window.Screen.virtualY Window.Screen.orientationUpdateMask: Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation + + property int screenCount: Qt.application.screens.length + + property variant allScreens + Component.onCompleted: { + allScreens = []; + var s = Qt.application.screens; + for (var i = 0; i < s.length; ++i) + allScreens.push(s[i]); + } } diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp index 92afdf6864..26b687a4a6 100644 --- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp +++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp @@ -33,13 +33,15 @@ #include <QtQuick/QQuickView> #include <QtGui/QScreen> #include "../../shared/util.h" - +#include <QtQuick/private/qquickscreen_p.h> +#include <QDebug> class tst_qquickscreen : public QQmlDataTest { Q_OBJECT private slots: void basicProperties(); void screenOnStartup(); + void fullScreenList(); }; void tst_qquickscreen::basicProperties() @@ -62,6 +64,10 @@ void tst_qquickscreen::basicProperties() QCOMPARE(int(screen->orientationUpdateMask()), root->property("updateMask").toInt()); QCOMPARE(screen->devicePixelRatio(), root->property("devicePixelRatio").toReal()); QVERIFY(screen->devicePixelRatio() >= 1.0); + QCOMPARE(screen->geometry().x(), root->property("vx").toInt()); + QCOMPARE(screen->geometry().y(), root->property("vy").toInt()); + + QVERIFY(root->property("screenCount").toInt() == QGuiApplication::screens().count()); } void tst_qquickscreen::screenOnStartup() @@ -83,6 +89,38 @@ void tst_qquickscreen::screenOnStartup() QCOMPARE(int(screen->orientationUpdateMask()), root->property("updateMask").toInt()); QCOMPARE(screen->devicePixelRatio(), root->property("devicePixelRatio").toReal()); QVERIFY(screen->devicePixelRatio() >= 1.0); + QCOMPARE(screen->geometry().x(), root->property("vx").toInt()); + QCOMPARE(screen->geometry().y(), root->property("vy").toInt()); +} + +void tst_qquickscreen::fullScreenList() +{ + QQuickView view; + view.setSource(testFileUrl("screen.qml")); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QQuickItem* root = view.rootObject(); + QVERIFY(root); + + QJSValue screensArray = root->property("allScreens").value<QJSValue>(); + QVERIFY(screensArray.isArray()); + int length = screensArray.property("length").toInt(); + const QList<QScreen *> screenList = QGuiApplication::screens(); + QVERIFY(length == screenList.count()); + + for (int i = 0; i < length; ++i) { + QQuickScreenInfo *info = qobject_cast<QQuickScreenInfo *>(screensArray.property(i).toQObject()); + QVERIFY(info != nullptr); + QCOMPARE(screenList[i]->name(), info->name()); + QCOMPARE(screenList[i]->size().width(), info->width()); + QCOMPARE(screenList[i]->size().height(), info->height()); + QCOMPARE(screenList[i]->availableVirtualGeometry().width(), info->desktopAvailableWidth()); + QCOMPARE(screenList[i]->availableVirtualGeometry().height(), info->desktopAvailableHeight()); + QCOMPARE(screenList[i]->devicePixelRatio(), info->devicePixelRatio()); + QCOMPARE(screenList[i]->geometry().x(), info->virtualX()); + QCOMPARE(screenList[i]->geometry().y(), info->virtualY()); + } } QTEST_MAIN(tst_qquickscreen) diff --git a/tests/auto/quick/qquickshortcut/data/multiple.qml b/tests/auto/quick/qquickshortcut/data/multiple.qml new file mode 100644 index 0000000000..2b58327cf0 --- /dev/null +++ b/tests/auto/quick/qquickshortcut/data/multiple.qml @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Window 2.2 + +Window { + id: window + + width: 300 + height: 300 + + property bool activated: false + property alias shortcut: shortcut + + Shortcut { + id: shortcut + onActivated: window.activated = true + } +} diff --git a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp index 2df94bb84a..75ccf26af9 100644 --- a/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp +++ b/tests/auto/quick/qquickshortcut/tst_qquickshortcut.cpp @@ -45,6 +45,8 @@ private slots: void context(); void matcher_data(); void matcher(); + void multiple_data(); + void multiple(); }; Q_DECLARE_METATYPE(Qt::Key) @@ -408,6 +410,49 @@ void tst_QQuickShortcut::matcher() qt_quick_set_shortcut_context_matcher(defaultMatcher); } +void tst_QQuickShortcut::multiple_data() +{ + QTest::addColumn<QStringList>("sequences"); + QTest::addColumn<Qt::Key>("key"); + QTest::addColumn<Qt::KeyboardModifiers>("modifiers"); + QTest::addColumn<bool>("enabled"); + QTest::addColumn<bool>("activated"); + + // first + QTest::newRow("Ctrl+X,(Shift+Del)") << (QStringList() << "Ctrl+X" << "Shift+Del") << Qt::Key_X << Qt::KeyboardModifiers(Qt::ControlModifier) << true << true; + // second + QTest::newRow("(Ctrl+X),Shift+Del") << (QStringList() << "Ctrl+X" << "Shift+Del") << Qt::Key_Delete << Qt::KeyboardModifiers(Qt::ShiftModifier) << true << true; + // disabled + QTest::newRow("(Ctrl+X,Shift+Del)") << (QStringList() << "Ctrl+X" << "Shift+Del") << Qt::Key_X << Qt::KeyboardModifiers(Qt::ControlModifier) << false << false; +} + +void tst_QQuickShortcut::multiple() +{ + QFETCH(QStringList, sequences); + QFETCH(Qt::Key, key); + QFETCH(Qt::KeyboardModifiers, modifiers); + QFETCH(bool, enabled); + QFETCH(bool, activated); + + QQmlApplicationEngine engine; + + engine.load(testFileUrl("multiple.qml")); + QQuickWindow *window = qobject_cast<QQuickWindow *>(engine.rootObjects().value(0)); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QObject *shortcut = window->property("shortcut").value<QObject *>(); + QVERIFY(shortcut); + + shortcut->setProperty("enabled", enabled); + shortcut->setProperty("sequences", sequences); + + QTest::keyPress(window, key, modifiers); + + QCOMPARE(window->property("activated").toBool(), activated); +} + QTEST_MAIN(tst_QQuickShortcut) #include "tst_qquickshortcut.moc" diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index 765523316f..ac57a05176 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -929,7 +929,6 @@ void tst_qquicktextedit::hAlignVisual() const int left = numberOfNonWhitePixels(centeredSection1, centeredSection2, image); const int mid = numberOfNonWhitePixels(centeredSection2, centeredSection3, image); const int right = numberOfNonWhitePixels(centeredSection3, centeredSection3End, image); - image.save("test3.png"); QVERIFY2(left < mid, msgNotLessThan(left, mid).constData()); QVERIFY2(mid < right, msgNotLessThan(mid, right).constData()); } diff --git a/tests/auto/quick/qquickwindow/data/windowWithScreen.qml b/tests/auto/quick/qquickwindow/data/windowWithScreen.qml new file mode 100644 index 0000000000..fdc0be3388 --- /dev/null +++ b/tests/auto/quick/qquickwindow/data/windowWithScreen.qml @@ -0,0 +1,10 @@ +import QtQuick 2.0 +import QtQuick.Window 2.3 as Window + +Window.Window { + color: "#00FF00" + targetScreen: Qt.application.screens[0] + Item { + objectName: "item" + } +} diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 8d021d92da..300ca392f9 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -311,6 +311,7 @@ private slots: void clearWindow(); void qmlCreation(); + void qmlCreationWithScreen(); void clearColor(); void defaultState(); @@ -1122,6 +1123,24 @@ void tst_qquickwindow::qmlCreation() QCOMPARE(item->window(), window); } +void tst_qquickwindow::qmlCreationWithScreen() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("windowWithScreen.qml")); + QObject *created = component.create(); + QScopedPointer<QObject> cleanup(created); + QVERIFY(created); + + QQuickWindow *window = qobject_cast<QQuickWindow*>(created); + QVERIFY(window); + QCOMPARE(window->color(), QColor(Qt::green)); + + QQuickItem *item = window->findChild<QQuickItem*>("item"); + QVERIFY(item); + QCOMPARE(item->window(), window); +} + void tst_qquickwindow::clearColor() { //::grab examines rendering to make sure it works visually diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index c7ba4de86c..6e9998c061 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -6,6 +6,7 @@ PUBLICTESTS += \ qtConfig(opengl(es1|es2)?) { PUBLICTESTS += \ + drawingmodes \ rendernode qtHaveModule(widgets): PUBLICTESTS += nodes diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 309c01dcdc..b5af61d723 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) + : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1) { setAcceptedMouseButtons(Qt::LeftButton); } @@ -79,6 +79,9 @@ public: void touchEvent(QTouchEvent *event) { eventList.append(Event(event->type(), event->touchPoints())); + QList<QTouchEvent::TouchPoint> tps = event->touchPoints(); + Q_ASSERT(!tps.isEmpty()); + point0 = tps.first().id(); event->setAccepted(acceptTouch); emit onTouchEvent(this); } @@ -125,12 +128,16 @@ public: event->type() == QEvent::TouchEnd) { QTouchEvent *touch = static_cast<QTouchEvent*>(event); eventList.append(Event(event->type(), touch->touchPoints())); + QList<QTouchEvent::TouchPoint> tps = touch->touchPoints(); + Q_ASSERT(!tps.isEmpty()); + point0 = tps.first().id(); if (filterTouch) event->accept(); return true; } return false; } + int point0; }; class tst_TouchMouse : public QQmlDataTest @@ -581,7 +588,7 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - QCOMPARE(windowPriv->touchMouseId, 0); + QVERIFY(windowPriv->touchMouseId != -1); auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1); QCOMPARE(window->mouseGrabberItem(), eventItem1); @@ -603,7 +610,7 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); QCOMPARE(window->mouseGrabberItem(), flickable); - QCOMPARE(windowPriv->touchMouseId, 0); + QVERIFY(windowPriv->touchMouseId != -1); QCOMPARE(pointerEvent->point(0)->grabber(), flickable); QVERIFY(flickable->isMovingVertically()); @@ -710,7 +717,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() // flickable should have the mouse grab, and have moved the itemForTouchPointId // for the touchMouseId to the new grabber. QCOMPARE(window->mouseGrabberItem(), flickable); - QCOMPARE(windowPriv->touchMouseId, 0); + QVERIFY(windowPriv->touchMouseId != -1); auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); QCOMPARE(pointerEvent->point(0)->grabber(), flickable); @@ -1246,7 +1253,7 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab() rightItem->acceptTouch = true; { QVector<int> ids; - ids.append(0); + ids.append(leftItem->point0); rightItem->grabTouchPoints(ids); } diff --git a/tests/manual/v4/fun.4.js b/tests/manual/v4/fun.4.js index b130acccd3..277761ad09 100644 --- a/tests/manual/v4/fun.4.js +++ b/tests/manual/v4/fun.4.js @@ -15,4 +15,5 @@ print([10, 20, 30].filter(function (v,k,o) { return v >= 20 })); print([10,20,30].reduce(function(a,v,k,o) { return a + v })); print([10,20,30].reduceRight(function(a,v,k,o) { return a + v })); - +print([10, 20, 30].find(function (v,k,o) { return v >= 20 })); +print([10, 20, 30].findIndex(function (v,k,o) { return v >= 20 })); |