aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-11 17:46:00 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-12 11:18:51 +0100
commit7660c30e08975011c7bd47bcb1796139b9d77196 (patch)
tree26e86cbc35560ac5bdf3327ea29f146cc1821787 /tests
parentccc4b52e95ac90c14c59001f675409c1a13c183b (diff)
Cache static compilation units
If we load the same file multiple times, we can re-use the old mapping. In fact we may leak memory if we don't. The fact that we have to use a mutex here is somewhat regrettable, but I haven't found a better way of serializing access. Task-number: QTBUG-89659 Pick-to: 5.15 Change-Id: Iaa44ac80faa5e95f30c05e950ab35083a8b0416b Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp128
1 files changed, 98 insertions, 30 deletions
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index d0c8390a74..d96231e81e 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -64,6 +64,7 @@ private slots:
void singletonDependency();
void cppRegisteredSingletonDependency();
void cacheModuleScripts();
+ void reuseStaticMappings();
private:
QDir m_qmlCacheDirectory;
@@ -127,34 +128,43 @@ struct TestCompiler
mappedFile.setFileName(cacheFilePath);
}
- bool compile(const QByteArray &contents)
+ void reset()
{
closeMapping();
engine->clearComponentCache();
-
waitForFileSystem();
+ }
- {
- QFile f(testFilePath);
- if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- lastErrorString = f.errorString();
- return false;
- }
- if (f.write(contents) != contents.size()) {
- lastErrorString = f.errorString();
- return false;
- }
+ bool writeTestFile(const QByteArray &contents)
+ {
+ QFile f(testFilePath);
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ lastErrorString = f.errorString();
+ return false;
+ }
+ if (f.write(contents) != contents.size()) {
+ lastErrorString = f.errorString();
+ return false;
}
+ return true;
+ }
+ bool loadTestFile()
+ {
CleanlyLoadingComponent component(engine, testFilePath);
if (!component.isReady()) {
lastErrorString = component.errorString();
return false;
}
-
return true;
}
+ bool compile(const QByteArray &contents)
+ {
+ reset();
+ return writeTestFile(contents) && loadTestFile();
+ }
+
const QV4::CompiledData::Unit *mapUnit()
{
if (!mappedFile.open(QIODevice::ReadOnly)) {
@@ -173,29 +183,62 @@ struct TestCompiler
}
typedef void (*HeaderTweakFunction)(QV4::CompiledData::Unit *header);
- bool tweakHeader(HeaderTweakFunction function)
+ bool tweakHeader(HeaderTweakFunction function, const QString &newName)
{
closeMapping();
- QFile f(cacheFilePath);
- if (!f.open(QIODevice::ReadWrite))
+ const QString targetTestFilePath = tempDir.path() + "/" + newName;
+
+ {
+ QFile testFile(testFilePath);
+ if (!testFile.copy(targetTestFilePath))
+ return false;
+ }
+
+ const QString targetCacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QUrl::fromLocalFile(targetTestFilePath));
+
+ QFile source(cacheFilePath);
+ if (!source.copy(targetCacheFilePath))
return false;
+
+ if (!source.open(QIODevice::ReadOnly))
+ return false;
+
+ QFile target(targetCacheFilePath);
+ if (!target.open(QIODevice::WriteOnly))
+ return false;
+
QV4::CompiledData::Unit header;
- if (f.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header))
+ if (source.read(reinterpret_cast<char *>(&header), sizeof(header)) != sizeof(header))
return false;
function(&header);
- f.seek(0);
- return f.write(reinterpret_cast<const char *>(&header), sizeof(header)) == sizeof(header);
+
+ return target.write(reinterpret_cast<const char *>(&header), sizeof(header))
+ == sizeof(header);
}
- bool verify()
+ bool verify(const QString &fileName = QString())
+ {
+ const QString path = fileName.isEmpty() ? testFilePath : tempDir.path() + "/" + fileName;
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
+ = QV4::ExecutableCompilationUnit::create();
+ return unit->loadFromDisk(QUrl::fromLocalFile(path),
+ QFileInfo(path).lastModified(), &lastErrorString);
+ }
+
+ quintptr unitData()
{
QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
= QV4::ExecutableCompilationUnit::create();
return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath),
- QFileInfo(testFilePath).lastModified(), &lastErrorString);
+ QFileInfo(testFilePath).lastModified(), &lastErrorString)
+ ? quintptr(unit->unitData())
+ : 0;
}
+
void closeMapping()
{
if (currentMapping) {
@@ -205,10 +248,11 @@ struct TestCompiler
mappedFile.close();
}
- void clearCache()
+ void clearCache(const QString &fileName = QString())
{
+ const QString path = fileName.isEmpty() ? testFilePath : tempDir.path() + "/" + fileName;
closeMapping();
- QFile::remove(cacheFilePath);
+ QFile::remove(path);
}
QQmlEngine *engine;
@@ -404,25 +448,28 @@ void tst_qmldiskcache::basicVersionChecks()
testCompiler.clearCache();
QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
- testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ const QString qtVersionFile = QStringLiteral("qtversion.qml");
+ QVERIFY(testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
header->qtVersion = 0;
- });
+ }, qtVersionFile));
- QVERIFY(!testCompiler.verify());
+ QVERIFY(!testCompiler.verify(qtVersionFile));
QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("Qt version mismatch. Found 0 expected %1").arg(QT_VERSION, 0, 16));
- testCompiler.clearCache();
+ testCompiler.clearCache(qtVersionFile);
}
{
testCompiler.clearCache();
QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
- testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
+ const QString versionFile = QStringLiteral("version.qml");
+ QVERIFY(testCompiler.tweakHeader([](QV4::CompiledData::Unit *header) {
header->version = 0;
- });
+ }, versionFile));
- QVERIFY(!testCompiler.verify());
+ QVERIFY(!testCompiler.verify(versionFile));
QCOMPARE(testCompiler.lastErrorString, QString::fromUtf8("V4 data structure version mismatch. Found 0 expected %1").arg(QV4_DATA_STRUCTURE_VERSION, 0, 16));
+ testCompiler.clearCache(versionFile);
}
}
@@ -963,6 +1010,27 @@ void tst_qmldiskcache::cacheModuleScripts()
}
}
+void tst_qmldiskcache::reuseStaticMappings()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.writeTestFile("import QtQml\nQtObject { objectName: 'foobar' }\n"));
+ QVERIFY(testCompiler.loadTestFile());
+
+ const quintptr data1 = testCompiler.unitData();
+ QVERIFY(data1 != 0);
+ QCOMPARE(testCompiler.unitData(), data1);
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.loadTestFile());
+
+ QCOMPARE(testCompiler.unitData(), data1);
+}
+
QTEST_MAIN(tst_qmldiskcache)
#include "tst_qmldiskcache.moc"