mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-29 05:44:14 +02:00
Test the second save on every example, a single-space value and accents
Review of #1109 (scorpio810): - tst_resaveunchanged now resaves every .qet in examples/ twice instead of two of them (24 rows, ~40 s). Dropping the load-time trim now also fails affuteuse_250h.qet, which the two-file version missed. - New case singleSpaceValueKept: a title-block property set to one space survives two saves (#973), and an accented property comes back unchanged. Fails if qetproject.cpp stops parsing with PreserveSpacingOnlyNodes. - New tst_diagramcontext: the QDom reader (projects) and the pugixml reader (element definitions in the collection) return the same value for plain, stray-spaced, accented and non-Latin text. Fails if the pugixml path decodes as Latin-1 or either reader stops trimming. The pugixml reader still reads a single-space value as "": pugixml drops whitespace-only text unless parse_ws_pcdata is set, as it did before this PR. That reader only sees element definitions, never a project, so #973's title-block values do not go through it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -330,8 +330,8 @@ target_compile_definitions(tst_conductorselfretrace PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
|
||||
|
||||
# Saving a project that was just saved changes nothing: runs the real
|
||||
# binary's --resave twice on examples/Projet_vierge.qet (empty information
|
||||
# values) and examples/m_000.qet (information values with stray spaces).
|
||||
# binary's --resave twice on every project in examples/, and on one whose
|
||||
# title block holds a single-space value (#973).
|
||||
add_executable(
|
||||
tst_resaveunchanged
|
||||
tst_resaveunchanged.cpp)
|
||||
@@ -341,3 +341,17 @@ target_link_libraries(tst_resaveunchanged PRIVATE Qt::Test)
|
||||
target_compile_definitions(tst_resaveunchanged PRIVATE
|
||||
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\""
|
||||
"QET_EXAMPLES_DIR=\"${QET_DIR}/examples\"")
|
||||
|
||||
# DiagramContext::fromXml() -- the two readers (QDom for projects, pugixml
|
||||
# for element definitions in the collection) give the same values: stray
|
||||
# spaces trimmed, accents kept.
|
||||
add_executable(
|
||||
tst_diagramcontext
|
||||
tst_diagramcontext.cpp
|
||||
${QET_DIR}/sources/diagramcontext.cpp
|
||||
${QET_DIR}/sources/qet.cpp
|
||||
${QET_DIR}/sources/qeticons.cpp
|
||||
${QET_DIR}/sources/shortcutmanager.cpp)
|
||||
add_test(NAME tst_diagramcontext COMMAND tst_diagramcontext)
|
||||
target_include_directories(tst_diagramcontext PRIVATE ${QET_DIR}/sources)
|
||||
target_link_libraries(tst_diagramcontext PRIVATE Qt::Test Qt::Widgets Qt::Xml pugixml::pugixml)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <QtTest>
|
||||
|
||||
#include "diagramcontext.h"
|
||||
#include "qetapp.h"
|
||||
|
||||
QString QETApp::m_interface_language;
|
||||
|
||||
/**
|
||||
DiagramContext::fromXml() has two readers: QDom, for projects, and
|
||||
pugixml, for element definitions in the collection. Both must give the
|
||||
values the next save writes -- stray spaces around real content trimmed,
|
||||
accented characters kept.
|
||||
*/
|
||||
class tst_diagramcontext : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
static QByteArray xml(const QString &value)
|
||||
{
|
||||
return QStringLiteral(
|
||||
"<elementInformations>"
|
||||
"<elementInformation name=\"v\" show=\"1\">%1</elementInformation>"
|
||||
"</elementInformations>")
|
||||
.arg(value)
|
||||
.toUtf8();
|
||||
}
|
||||
|
||||
static QString fromDom(const QByteArray &data)
|
||||
{
|
||||
QDomDocument doc;
|
||||
if (!doc.setContent(data)) return QStringLiteral("<parse error>");
|
||||
DiagramContext dc;
|
||||
dc.fromXml(doc.documentElement(), QStringLiteral("elementInformation"));
|
||||
return dc.value(QStringLiteral("v")).toString();
|
||||
}
|
||||
|
||||
static QString fromPugi(const QByteArray &data)
|
||||
{
|
||||
pugi::xml_document doc;
|
||||
if (!doc.load_buffer(data.constData(), size_t(data.size())))
|
||||
return QStringLiteral("<parse error>");
|
||||
DiagramContext dc;
|
||||
dc.fromXml(doc.document_element(), QStringLiteral("elementInformation"));
|
||||
return dc.value(QStringLiteral("v")).toString();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void bothReadersAgree_data()
|
||||
{
|
||||
QTest::addColumn<QString>("value");
|
||||
QTest::addColumn<QString>("expected");
|
||||
|
||||
QTest::newRow("plain") << "PRISE" << "PRISE";
|
||||
QTest::newRow("stray spaces") << " PRISE " << "PRISE";
|
||||
QTest::newRow("accents") << "Armoire façade été" << "Armoire façade été";
|
||||
QTest::newRow("accents and stray spaces") << " Moteur à cage " << "Moteur à cage";
|
||||
QTest::newRow("non-Latin") << "Двигатель 電機" << "Двигатель 電機";
|
||||
}
|
||||
|
||||
void bothReadersAgree()
|
||||
{
|
||||
QFETCH(QString, value);
|
||||
QFETCH(QString, expected);
|
||||
QCOMPARE(fromDom(xml(value)), expected);
|
||||
QCOMPARE(fromPugi(xml(value)), expected);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_diagramcontext)
|
||||
|
||||
#include "tst_diagramcontext.moc"
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QRegularExpression>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
// Saving a project that was just saved must change nothing. Two things
|
||||
@@ -16,7 +17,8 @@
|
||||
// - information values were trimmed on save but not on load, so a label
|
||||
// with stray spaces kept them in its displayed copy until the project
|
||||
// was opened again (m_000.qet).
|
||||
// Runs the real binary's --resave twice on each example.
|
||||
// Runs the real binary's --resave twice on every example, and on a
|
||||
// project whose title block holds a value that is a single space (#973).
|
||||
class tst_resaveunchanged : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -56,17 +58,23 @@ private slots:
|
||||
QVERIFY(QFile::exists(QStringLiteral(QET_TEST_BINARY_PATH)));
|
||||
}
|
||||
|
||||
// Projet_vierge.qet has empty information values, m_000.qet values
|
||||
// with stray spaces; every other example is here so a new cause shows.
|
||||
void secondSaveChangesNothing_data()
|
||||
{
|
||||
QTest::addColumn<QString>("project");
|
||||
QTest::newRow("empty information values") << QStringLiteral("Projet_vierge.qet");
|
||||
QTest::newRow("information values with stray spaces") << QStringLiteral("m_000.qet");
|
||||
const QDir examples(QStringLiteral(QET_EXAMPLES_DIR));
|
||||
const QStringList projects =
|
||||
examples.entryList({QStringLiteral("*.qet")}, QDir::Files, QDir::Name);
|
||||
QVERIFY(!projects.isEmpty());
|
||||
for (const QString &project : projects)
|
||||
QTest::newRow(project.toUtf8().constData()) << examples.filePath(project);
|
||||
}
|
||||
|
||||
void secondSaveChangesNothing()
|
||||
{
|
||||
QFETCH(QString, project);
|
||||
const QString first = resave(QStringLiteral(QET_EXAMPLES_DIR "/") + project);
|
||||
const QString first = resave(project);
|
||||
QVERIFY2(!first.isEmpty(), "first --resave failed");
|
||||
const QString second = resave(first);
|
||||
QVERIFY2(!second.isEmpty(), "second --resave failed");
|
||||
@@ -74,6 +82,38 @@ private slots:
|
||||
QVERIFY(!a.isEmpty());
|
||||
QVERIFY2(a == b, "the second save changed the file");
|
||||
}
|
||||
|
||||
// A title-block value that is a single space is kept through two saves
|
||||
// (#973), and a value with accents comes back as it went in.
|
||||
void singleSpaceValueKept()
|
||||
{
|
||||
QByteArray xml = read(QStringLiteral(QET_EXAMPLES_DIR "/Projet_vierge.qet"));
|
||||
QVERIFY(xml.contains("<properties>"));
|
||||
xml.replace("<properties>",
|
||||
"<properties>"
|
||||
"<property show=\"1\" name=\"space\"> </property>"
|
||||
"<property show=\"1\" name=\"accents\">Armoire façade été</property>");
|
||||
const QString in = m_dir.filePath(QStringLiteral("space.qet"));
|
||||
QFile f(in);
|
||||
QVERIFY(f.open(QIODevice::WriteOnly));
|
||||
f.write(xml);
|
||||
f.close();
|
||||
|
||||
const QString first = resave(in);
|
||||
QVERIFY2(!first.isEmpty(), "first --resave failed");
|
||||
const QString second = resave(first);
|
||||
QVERIFY2(!second.isEmpty(), "second --resave failed");
|
||||
const QByteArray a = read(first), b = read(second);
|
||||
QVERIFY2(a == b, "the second save changed the file");
|
||||
|
||||
const QString saved = QString::fromUtf8(b);
|
||||
QVERIFY2(saved.contains(QRegularExpression(
|
||||
QStringLiteral("<property [^>]*name=\"space\"[^>]*> </property>"))),
|
||||
"the single-space value was lost");
|
||||
QVERIFY2(saved.contains(QRegularExpression(
|
||||
QStringLiteral("<property [^>]*name=\"accents\"[^>]*>Armoire façade été</property>"))),
|
||||
"the accented value changed");
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_resaveunchanged)
|
||||
|
||||
Reference in New Issue
Block a user