void tst_qmldiskcache::recompileAfterChange() { QQmlEngine engine; TestCompiler testCompiler(&engine); QVERIFY(testCompiler.tempDir.isValid()); const QByteArray contents = QByteArrayLiteral("import TypeTest 1.0\n" "TypeThatWillChange {\n" "}"); qmlRegisterType<TypeVersion1>("TypeTest", 1, 0, "TypeThatWillChange"); { testCompiler.clearCache(); QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString)); QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString)); } QDateTime initialCacheTimeStamp = QFileInfo(testCompiler.cacheFilePath).lastModified(); { CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<TypeVersion1> obj(qobject_cast<TypeVersion1*>(component.create())); QVERIFY(!obj.isNull()); QCOMPARE(QFileInfo(testCompiler.cacheFilePath).lastModified(), initialCacheTimeStamp); } engine.clearComponentCache(); { CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<TypeVersion1> obj(qobject_cast<TypeVersion1*>(component.create())); QVERIFY(!obj.isNull()); QCOMPARE(QFileInfo(testCompiler.cacheFilePath).lastModified(), initialCacheTimeStamp); } engine.clearComponentCache(); qmlClearTypeRegistrations(); qmlRegisterType<TypeVersion2>("TypeTest", 1, 0, "TypeThatWillChange"); waitForFileSystem(); { CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<TypeVersion2> obj(qobject_cast<TypeVersion2*>(component.create())); QVERIFY(!obj.isNull()); QVERIFY(QFileInfo(testCompiler.cacheFilePath).lastModified() > initialCacheTimeStamp); } }
void Reloader::reload() { qDebug() << "reloading"; //The engines has a internal cache that prevents reloading. QQmlEngine *engine = m_viewer->engine(); engine->trimComponentCache(); engine->clearComponentCache(); m_viewer->setSource(m_mainFile); }
void tst_qqmlengine::clearComponentCache() { QQmlEngine engine; // Create original qml file { QFile file("temp.qml"); QVERIFY(file.open(QIODevice::WriteOnly)); file.write("import QtQuick 2.0\nQtObject {\nproperty int test: 10\n}\n"); file.close(); } // Test "test" property { QQmlComponent component(&engine, "temp.qml"); QObject *obj = component.create(); QVERIFY(obj != 0); QCOMPARE(obj->property("test").toInt(), 10); delete obj; } // Modify qml file { QFile file("temp.qml"); QVERIFY(file.open(QIODevice::WriteOnly)); file.write("import QtQuick 2.0\nQtObject {\nproperty int test: 11\n}\n"); file.close(); } // Test cache hit { QQmlComponent component(&engine, "temp.qml"); QObject *obj = component.create(); QVERIFY(obj != 0); QCOMPARE(obj->property("test").toInt(), 10); delete obj; } // Clear cache engine.clearComponentCache(); // Test cache refresh { QQmlComponent component(&engine, "temp.qml"); QObject *obj = component.create(); QVERIFY(obj != 0); QCOMPARE(obj->property("test").toInt(), 11); delete obj; } }
void tst_qmldiskcache::fileSelectors() { QQmlEngine engine; QTemporaryDir tempDir; QVERIFY(tempDir.isValid()); const QString testFilePath = tempDir.path() + "/test.qml"; { QFile f(testFilePath); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject { property int value: 42 }")); } const QString selector = QStringLiteral("testSelector"); const QString selectorPath = tempDir.path() + "/+" + selector; const QString selectedTestFilePath = selectorPath + "/test.qml"; { QVERIFY(QDir::root().mkpath(selectorPath)); QFile f(selectorPath + "/test.qml"); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject { property int value: 100 }")); } { QQmlComponent component(&engine, testFilePath); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 42); QFile cacheFile(testFilePath + "c"); QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName())); } QQmlFileSelector qmlSelector(&engine); qmlSelector.setExtraSelectors(QStringList() << selector); engine.clearComponentCache(); { QQmlComponent component(&engine, testFilePath); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 100); QFile cacheFile(selectedTestFilePath + "c"); QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName())); } }
void tst_qmldiskcache::localAliases() { QQmlEngine engine; TestCompiler testCompiler(&engine); QVERIFY(testCompiler.tempDir.isValid()); const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n" "QtObject {\n" " id: root\n" " property int prop: 100\n" " property alias dummy1: root.prop\n" " property alias dummy2: root.prop\n" " property alias dummy3: root.prop\n" " property alias dummy4: root.prop\n" " property alias dummy5: root.prop\n" " property alias foo: root.prop\n" " property alias bar: root.foo\n" "}"); { testCompiler.clearCache(); QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString)); QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString)); } { CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("bar").toInt(), 100); } engine.clearComponentCache(); { CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("bar").toInt(), 100); } }
void tst_qmldiskcache::stableOrderOfDependentCompositeTypes() { QQmlEngine engine; QTemporaryDir tempDir; QVERIFY(tempDir.isValid()); { const QString depFilePath = tempDir.path() + "/FirstDependentType.qml"; QFile f(depFilePath); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject { property int value: 42 }")); } { const QString depFilePath = tempDir.path() + "/SecondDependentType.qml"; QFile f(depFilePath); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject { property int value: 100 }")); } const QString testFilePath = tempDir.path() + "/main.qml"; { QFile f(testFilePath); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject {\n" " property QtObject dep1: FirstDependentType{}\n" " property QtObject dep2: SecondDependentType{}\n" " property int value: dep1.value + dep2.value\n" "}")); } QByteArray firstDependentTypeClassName; QByteArray secondDependentTypeClassName; { CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 142); firstDependentTypeClassName = qvariant_cast<QObject *>(obj->property("dep1"))->metaObject()->className(); secondDependentTypeClassName = qvariant_cast<QObject *>(obj->property("dep2"))->metaObject()->className(); } QVERIFY(firstDependentTypeClassName != secondDependentTypeClassName); QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData()); QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData()); const QString testFileCachePath = testFilePath + QLatin1Char('c'); QVERIFY(QFile::exists(testFileCachePath)); QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); engine.clearComponentCache(); waitForFileSystem(); // Creating the test component a second time should load it from the cache (same time stamp), // despite the class names of the dependent composite types differing. { CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 142); QVERIFY(qvariant_cast<QObject *>(obj->property("dep1"))->metaObject()->className() != firstDependentTypeClassName); QVERIFY(qvariant_cast<QObject *>(obj->property("dep2"))->metaObject()->className() != secondDependentTypeClassName); } { QVERIFY(QFile::exists(testFileCachePath)); QDateTime newCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); QCOMPARE(newCacheTimeStamp, initialCacheTimeStamp); } // Now change the first dependent QML type and see if we correctly re-generate the // caches. engine.clearComponentCache(); waitForFileSystem(); { const QString depFilePath = tempDir.path() + "/FirstDependentType.qml"; QFile f(depFilePath); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.write(QByteArrayLiteral("import QtQml 2.0\nQtObject { property int value: 40 }")); } { CleanlyLoadingComponent component(&engine, QUrl::fromLocalFile(testFilePath)); QScopedPointer<QObject> obj(component.create()); QVERIFY(!obj.isNull()); QCOMPARE(obj->property("value").toInt(), 140); } { QVERIFY(QFile::exists(testFileCachePath)); QDateTime newCacheTimeStamp = QFileInfo(testFileCachePath).lastModified(); QVERIFY2(newCacheTimeStamp > initialCacheTimeStamp, qPrintable(newCacheTimeStamp.toString())); } }