diff options
Diffstat (limited to 'tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp')
-rw-r--r-- | tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 68b450ab26..12aeff7591 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -28,6 +28,7 @@ #include <QtTest/QtTest> #include <QtQml/qqmlengine.h> +#include <QtQml/qqmlnetworkaccessmanagerfactory.h> #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> #include <QtQml/private/qqmlengine_p.h> @@ -45,6 +46,7 @@ private slots: void trimCache2(); void keepSingleton(); void keepRegistrations(); + void intercept(); }; void tst_QQMLTypeLoader::testLoadComplete() @@ -192,6 +194,172 @@ void tst_QQMLTypeLoader::keepRegistrations() verifyTypes(true, false); // qmlRegisterType creates an undeletable type. } +class NetworkReply : public QNetworkReply +{ +public: + NetworkReply() + { + open(QIODevice::ReadOnly); + } + + void setData(const QByteArray &data) + { + if (isFinished()) + return; + m_buffer = data; + emit readyRead(); + setFinished(true); + emit finished(); + } + + void fail() + { + if (isFinished()) + return; + m_buffer.clear(); + setError(ContentNotFoundError, "content not found"); + emit error(ContentNotFoundError); + setFinished(true); + emit finished(); + } + + qint64 bytesAvailable() const override + { + return m_buffer.size(); + } + + qint64 readData(char *data, qint64 maxlen) override + { + if (m_buffer.length() < maxlen) + maxlen = m_buffer.length(); + std::memcpy(data, m_buffer.data(), maxlen); + m_buffer.remove(0, maxlen); + return maxlen; + } + + void abort() override + { + if (isFinished()) + return; + m_buffer.clear(); + setFinished(true); + emit finished(); + } + +private: + QByteArray m_buffer; +}; + +class NetworkAccessManager : public QNetworkAccessManager +{ + Q_OBJECT +public: + + NetworkAccessManager(QObject *parent) : QNetworkAccessManager(parent) + { + } + + QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, + QIODevice *outgoingData) override + { + QUrl url = request.url(); + QString scheme = url.scheme(); + if (op != GetOperation || !scheme.endsWith("+debug")) + return QNetworkAccessManager::createRequest(op, request, outgoingData); + + scheme.chop(sizeof("+debug") - 1); + url.setScheme(scheme); + + NetworkReply *reply = new NetworkReply; + QString filename = QQmlFile::urlToLocalFileOrQrc(url); + QTimer::singleShot(10, reply, [this, reply, filename]() { + if (filename.isEmpty()) { + reply->fail(); + } else { + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + emit loaded(filename); + reply->setData(file.readAll()); + } else + reply->fail(); + } + }); + return reply; + } + +signals: + void loaded(const QString &filename); +}; + +class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory +{ +public: + QStringList loadedFiles; + + QNetworkAccessManager *create(QObject *parent) override + { + NetworkAccessManager *manager = new NetworkAccessManager(parent); + QObject::connect(manager, &NetworkAccessManager::loaded, [this](const QString &filename) { + loadedFiles.append(filename); + }); + return manager; + } +}; + +class UrlInterceptor : public QQmlAbstractUrlInterceptor +{ +public: + QUrl intercept(const QUrl &path, DataType type) override + { + Q_UNUSED(type); + if (!QQmlFile::isLocalFile(path)) + return path; + + // Don't rewrite internal Qt paths. We'd hit C++ plugins there. + QString filename = QQmlFile::urlToLocalFileOrQrc(path); + if (filename.startsWith(":/qt-project.org/") + || filename.startsWith(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath))) { + return path; + } + + QUrl result = path; + QString scheme = result.scheme(); + if (!scheme.endsWith("+debug")) + result.setScheme(scheme + "+debug"); + return result; + } +}; + +void tst_QQMLTypeLoader::intercept() +{ + QQmlEngine engine; + engine.addImportPath(dataDirectory()); + + UrlInterceptor interceptor; + NetworkAccessManagerFactory factory; + + engine.setUrlInterceptor(&interceptor); + engine.setNetworkAccessManagerFactory(&factory); + + QQmlComponent component(&engine, testFileUrl("test_intercept.qml")); + + QVERIFY(component.status() != QQmlComponent::Ready); + QTRY_VERIFY2(component.status() == QQmlComponent::Ready, + component.errorString().toUtf8().constData()); + + QScopedPointer<QObject> o(component.create()); + QVERIFY(o.data()); + + QTRY_COMPARE(o->property("created").toInt(), 2); + QTRY_COMPARE(o->property("loaded").toInt(), 2); + + QCOMPARE(factory.loadedFiles.length(), 4); + QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/test_intercept.qml")); + QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Intercept.qml")); + QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Fast/qmldir")); + QVERIFY(factory.loadedFiles.contains(dataDirectory() + "/Fast/Fast.qml")); +} + QTEST_MAIN(tst_QQMLTypeLoader) #include "tst_qqmltypeloader.moc" |