Initialize TranslationData padding before writing cache files

Otherwise the resulting files differ subtly.

Fixes: QTBUG-74532
Change-Id: I12b4f1ba6dda781d63ad50cce87861ba24582bf7
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Ulf Hermann 2019-03-21 16:25:55 +01:00
parent 9ce826901b
commit 497a795081
19 changed files with 105 additions and 36 deletions

View File

@ -1108,6 +1108,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
translationData.commentIndex = 0; // empty string
translationData.padding = 0;
if (!args || !args->expression)
return; // no arguments, stop
@ -1148,6 +1149,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg
QV4::CompiledData::TranslationData translationData;
translationData.number = -1;
translationData.commentIndex = 0; // empty string, but unused
translationData.padding = 0;
if (!args || !args->expression)
return; // no arguments, stop

View File

@ -0,0 +1,15 @@
import QtQuick 2.12
Item {
Component {
Rectangle {
id: xxx
Text {
text: qsTr("&Undo")
}
Text {
text: qsTr("&Redo")
}
}
}
}

View File

@ -2,23 +2,31 @@ CONFIG += testcase qtquickcompiler
TARGET = tst_qmlcachegen
macos:CONFIG -= app_bundle
include (../../shared/util.pri)
TESTDATA = data/*
SOURCES += tst_qmlcachegen.cpp
workerscripts_test.files = worker.js worker.qml
RESOURCES += \
data/versionchecks.qml \
data/jsimport.qml \
data/script.js \
data/library.js \
data/Enums.qml \
data/componentInItem.qml \
data/jsmoduleimport.qml \
data/script.mjs
workerscripts_test.files = \
data/worker.js \
data/worker.qml
workerscripts_test.prefix = /workerscripts
RESOURCES += workerscripts_test
RESOURCES += versionchecks.qml
RESOURCES += trickypaths.qrc
RESOURCES += jsimport.qml script.js library.js
RESOURCES += Enums.qml
RESOURCES += \
workerscripts_test \
trickypaths.qrc
# QTBUG-46375
!win32: RESOURCES += trickypaths_umlaut.qrc
RESOURCES += jsmoduleimport.qml script.mjs
QT += core-private qml-private testlib

View File

@ -1,7 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/directory with spaces">
<file alias="file name with spaces.qml">trickypaths.qml</file>
<file>versionStyleSuffix-1.2-core-yc.qml</file>
<file>versionStyleSuffix-1.2-more.qml</file>
<file alias="file name with spaces.qml">data/trickypaths.qml</file>
<file alias="versionStyleSuffix-1.2-core-yc.qml">data/versionStyleSuffix-1.2-core-yc.qml</file>
<file alias="versionStyleSuffix-1.2-more.qml">data/versionStyleSuffix-1.2-more.qml</file>
</qresource>
</RCC>

View File

@ -1,5 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file alias="Bäh.qml">umlaut.qml</file>
<file alias="Bäh.qml">data/umlaut.qml</file>
</qresource>
</RCC>

View File

@ -38,7 +38,9 @@
#include <private/qqmlcomponent_p.h>
#include <qtranslator.h>
class tst_qmlcachegen: public QObject
#include "../../shared/util.h"
class tst_qmlcachegen: public QQmlDataTest
{
Q_OBJECT
@ -65,6 +67,9 @@ private slots:
void enums();
void sourceFileIndices();
void reproducibleCache_data();
void reproducibleCache();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@ -352,12 +357,13 @@ static QQmlPrivate::CachedQmlUnit *temporaryModifiedCachedUnit = nullptr;
void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
QVERIFY(QFile::exists(":/versionchecks.qml"));
QCOMPARE(QFileInfo(":/versionchecks.qml").size(), 0);
QVERIFY(QFile::exists(":/data/versionchecks.qml"));
QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
Q_ASSERT(!temporaryModifiedCachedUnit);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
const QV4::CompiledData::Unit *originalUnit = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error);
const QV4::CompiledData::Unit *originalUnit = QQmlMetaType::findCachedCompilationUnit(
QUrl("qrc:/data/versionchecks.qml"), &error);
QVERIFY(originalUnit);
QV4::CompiledData::Unit *tweakedUnit = (QV4::CompiledData::Unit *)malloc(originalUnit->unitSize);
memcpy(reinterpret_cast<void *>(tweakedUnit), reinterpret_cast<const void *>(originalUnit), originalUnit->unitSize);
@ -365,7 +371,7 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
temporaryModifiedCachedUnit = new QQmlPrivate::CachedQmlUnit{tweakedUnit, nullptr, nullptr};
auto testHandler = [](const QUrl &url) -> const QQmlPrivate::CachedQmlUnit * {
if (url == QUrl("qrc:/versionchecks.qml"))
if (url == QUrl("qrc:/data/versionchecks.qml"))
return temporaryModifiedCachedUnit;
return nullptr;
};
@ -373,15 +379,18 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
{
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
QVERIFY(!QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error));
QVERIFY(!QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/data/versionchecks.qml"), &error));
QCOMPARE(error, QQmlMetaType::CachedUnitLookupError::VersionMismatch);
}
{
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:/versionchecks.qml"));
QQmlComponent component(&engine, QUrl("qrc:/data/versionchecks.qml"));
QCOMPARE(component.status(), QQmlComponent::Error);
QCOMPARE(component.errorString(), QString("qrc:/versionchecks.qml:-1 File was compiled ahead of time with an incompatible version of Qt and the original file cannot be found. Please recompile\n"));
QCOMPARE(component.errorString(),
QString("qrc:/data/versionchecks.qml:-1 File was compiled ahead of time with an "
"incompatible version of Qt and the original file cannot be found. Please "
"recompile\n"));
}
Q_ASSERT(temporaryModifiedCachedUnit);
@ -394,12 +403,12 @@ void tst_qmlcachegen::versionChecksForAheadOfTimeUnits()
void tst_qmlcachegen::workerScripts()
{
QVERIFY(QFile::exists(":/workerscripts/worker.js"));
QVERIFY(QFile::exists(":/workerscripts/worker.qml"));
QCOMPARE(QFileInfo(":/workerscripts/worker.js").size(), 0);
QVERIFY(QFile::exists(":/workerscripts/data/worker.js"));
QVERIFY(QFile::exists(":/workerscripts/data/worker.qml"));
QCOMPARE(QFileInfo(":/workerscripts/data/worker.js").size(), 0);
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/worker.qml"));
CleanlyLoadingComponent component(&engine, QUrl("qrc:///workerscripts/data/worker.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_VERIFY(obj->property("success").toBool());
@ -496,7 +505,7 @@ void tst_qmlcachegen::trickyPaths()
void tst_qmlcachegen::qrcScriptImport()
{
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsimport.qml"));
CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/jsimport.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_COMPARE(obj->property("value").toInt(), 42);
@ -559,14 +568,14 @@ void tst_qmlcachegen::fsScriptImport()
void tst_qmlcachegen::moduleScriptImport()
{
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///jsmoduleimport.qml"));
CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/jsmoduleimport.qml"));
QVERIFY2(!component.isError(), qPrintable(component.errorString()));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_VERIFY(obj->property("ok").toBool());
QVERIFY(QFile::exists(":/script.mjs"));
QCOMPARE(QFileInfo(":/script.mjs").size(), 0);
QVERIFY(QFile::exists(":/data/script.mjs"));
QCOMPARE(QFileInfo(":/data/script.mjs").size(), 0);
{
auto componentPrivate = QQmlComponentPrivate::get(&component);
@ -579,7 +588,8 @@ void tst_qmlcachegen::moduleScriptImport()
QVERIFY(unitData->flags & QV4::CompiledData::Unit::IsESModule);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/script.mjs"), &error);
const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(
QUrl("qrc:/data/script.mjs"), &error);
QVERIFY(unitFromResources);
QCOMPARE(unitFromResources, compilationUnit->unitData());
@ -589,7 +599,7 @@ void tst_qmlcachegen::moduleScriptImport()
void tst_qmlcachegen::enums()
{
QQmlEngine engine;
CleanlyLoadingComponent component(&engine, QUrl("qrc:///Enums.qml"));
CleanlyLoadingComponent component(&engine, QUrl("qrc:///data/Enums.qml"));
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QTRY_COMPARE(obj->property("value").toInt(), 200);
@ -597,16 +607,50 @@ void tst_qmlcachegen::enums()
void tst_qmlcachegen::sourceFileIndices()
{
QVERIFY(QFile::exists(":/versionchecks.qml"));
QCOMPARE(QFileInfo(":/versionchecks.qml").size(), 0);
QVERIFY(QFile::exists(":/data/versionchecks.qml"));
QCOMPARE(QFileInfo(":/data/versionchecks.qml").size(), 0);
QQmlMetaType::CachedUnitLookupError error = QQmlMetaType::CachedUnitLookupError::NoError;
const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(QUrl("qrc:/versionchecks.qml"), &error);
const QV4::CompiledData::Unit *unitFromResources = QQmlMetaType::findCachedCompilationUnit(
QUrl("qrc:/data/versionchecks.qml"), &error);
QVERIFY(unitFromResources);
QVERIFY(unitFromResources->flags & QV4::CompiledData::Unit::PendingTypeCompilation);
QCOMPARE(uint(unitFromResources->sourceFileIndex), uint(0));
}
void tst_qmlcachegen::reproducibleCache_data()
{
QTest::addColumn<QString>("filePath");
QDir dir(dataDirectory());
for (const QString &entry : dir.entryList(QDir::Files)) {
QVERIFY(entry.endsWith(".qml") || entry.endsWith(".js") || entry.endsWith(".mjs"));
QTest::newRow(entry.toUtf8().constData()) << dir.filePath(entry);
}
}
void tst_qmlcachegen::reproducibleCache()
{
QFETCH(QString, filePath);
QFile file(filePath);
QVERIFY(file.exists());
auto generate = [](const QString &path) {
if (!generateCache(path))
return QByteArray();
QFile generated(path + 'c');
[&](){ QVERIFY(generated.open(QIODevice::ReadOnly)); }();
const QByteArray result = generated.readAll();
generated.remove();
return result;
};
const QByteArray contents1 = generate(file.fileName());
const QByteArray contents2 = generate(file.fileName());
QCOMPARE(contents1, contents2);
}
QTEST_GUILESS_MAIN(tst_qmlcachegen)
#include "tst_qmlcachegen.moc"