aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp')
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp111
1 files changed, 110 insertions, 1 deletions
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index 8ccf4714ba..e2c0055ea1 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -56,6 +56,7 @@ private slots:
void fileSelectors();
void localAliases();
void cacheResources();
+ void stableOrderOfDependentCompositeTypes();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -554,7 +555,115 @@ void tst_qmldiskcache::cacheResources()
QCOMPARE(obj->property("value").toInt(), 20);
}
- QCOMPARE(QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot | QDir::Files).count(), 1);
+ const QStringList entries = QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot | QDir::Files);
+ QCOMPARE(entries.count(), 1);
+
+ {
+ QFile cacheFile(qmlCacheDirectory + QLatin1Char('/') + entries.constFirst());
+ QVERIFY2(cacheFile.open(QIODevice::ReadOnly), qPrintable(cacheFile.errorString()));
+ QV4::CompiledData::Unit unit;
+ QVERIFY(cacheFile.read(reinterpret_cast<char *>(&unit), sizeof(unit)) == sizeof(unit));
+ QCOMPARE(qint64(unit.sourceTimeStamp), QFileInfo(QCoreApplication::applicationFilePath()).lastModified().toMSecsSinceEpoch());
+ }
+}
+
+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()));
+ }
}
QTEST_MAIN(tst_qmldiskcache)