[Tests] Drop the empty icon baseline

The legacy icon set is fully paid down, so the ratchet had nothing left to
ratchet: BaselineIsWellFormed required the baseline to be empty, which made
the baseline file, the stale-entry diff and the entry-format regex
unreachable. The rules are enforced directly now.

- AssetsFollowTheRules fails on any violation of collectViolations().
- tests/icon_assets/icon-baseline.txt is gone with its reader.
This commit is contained in:
Lukas Brübach 2026-11-01 18:01:59 +01:00
parent 06ad7a6d92
commit c9685076b9
2 changed files with 8 additions and 69 deletions

View file

@ -1,9 +0,0 @@
# Icon rule baseline (ratchet).
#
# One violation per line: <rule> <path relative to cockatrice/resources/icons>.
# Rules: xml, viewbox, editor-metadata, hardcoded-color, color-filename, no-token, physical-size, raster.
#
# This file may only shrink. When an icon is fixed, delete its line(s) in the
# same change; the test fails while a fixed entry remains. Never add new lines.
#
# The UI glyph set is fully migrated; this list is intentionally empty.

View file

@ -13,18 +13,12 @@
namespace namespace
{ {
const QString ICONS_RELATIVE_PATH = QStringLiteral("cockatrice/resources/icons"); const QString ICONS_RELATIVE_PATH = QStringLiteral("cockatrice/resources/icons");
const QString BASELINE_RELATIVE_PATH = QStringLiteral("tests/icon_assets/icon-baseline.txt");
QString iconsDir() QString iconsDir()
{ {
return QDir(QStringLiteral(COCKATRICE_SOURCE_DIR)).absoluteFilePath(ICONS_RELATIVE_PATH); return QDir(QStringLiteral(COCKATRICE_SOURCE_DIR)).absoluteFilePath(ICONS_RELATIVE_PATH);
} }
QString baselinePath()
{
return QDir(QStringLiteral(COCKATRICE_SOURCE_DIR)).absoluteFilePath(BASELINE_RELATIVE_PATH);
}
/** @brief True for content art that is allowed to carry full color. */ /** @brief True for content art that is allowed to carry full color. */
bool isContentArt(const QString &relativePath) bool isContentArt(const QString &relativePath)
{ {
@ -220,26 +214,6 @@ QSet<QString> collectViolations()
return violations; return violations;
} }
/** @brief Parses the ratchet file; returns false with an error when it cannot be read. */
bool readBaseline(QSet<QString> &entries, QString &error)
{
QFile file(baselinePath());
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
error = QStringLiteral("Cannot read %1").arg(baselinePath());
return false;
}
const QStringList lines = QString::fromUtf8(file.readAll()).split(QLatin1Char('\n'));
for (const QString &line : lines) {
const QString trimmed = line.trimmed();
if (trimmed.isEmpty() || trimmed.startsWith(QLatin1Char('#'))) {
continue;
}
entries.insert(trimmed);
}
return true;
}
QString formatSet(const QSet<QString> &entries) QString formatSet(const QSet<QString> &entries)
{ {
QStringList lines(entries.begin(), entries.end()); QStringList lines(entries.begin(), entries.end());
@ -250,44 +224,18 @@ QString formatSet(const QSet<QString> &entries)
} // namespace } // namespace
/** /**
* @brief The icon ratchet: no new violations, and fixed icons must leave the baseline. * @brief Every UI glyph follows the palette-token rules.
* *
* Existing UI glyphs are grandfathered in tests/icon_assets/icon-baseline.txt. Fixing an icon * The legacy set was paid down icon by icon, so no baseline grandfathers
* without deleting its baseline lines fails on purpose, so the list can only shrink. * violations: a new violation fails right here. Scheme variants
* (`*-dark.svg`/`*-light.svg`) and mana art are exempt inside collectViolations().
*/ */
TEST(IconAssets, BaselineRatchet) TEST(IconAssets, AssetsFollowTheRules)
{ {
ASSERT_TRUE(QDir::isAbsolutePath(iconsDir())); ASSERT_TRUE(QDir::isAbsolutePath(iconsDir()));
ASSERT_TRUE(QDir(iconsDir()).exists()) << "Missing icon directory: " << iconsDir().toStdString(); ASSERT_TRUE(QDir(iconsDir()).exists()) << "Missing icon directory: " << iconsDir().toStdString();
QSet<QString> baseline; const QSet<QString> violations = collectViolations();
QString error; EXPECT_TRUE(violations.isEmpty()) << "Icon rule violations. Fix the icon; do not add exceptions:\n"
ASSERT_TRUE(readBaseline(baseline, error)) << error.toStdString(); << formatSet(violations).toStdString();
const QSet<QString> actual = collectViolations();
const QSet<QString> newViolations = actual - baseline;
const QSet<QString> staleBaseline = baseline - actual;
EXPECT_TRUE(newViolations.isEmpty()) << "New icon rule violations. Fix the icon; do not add exceptions:\n"
<< formatSet(newViolations).toStdString();
EXPECT_TRUE(staleBaseline.isEmpty()) << "These baseline entries are fixed or gone; delete them from "
<< BASELINE_RELATIVE_PATH.toStdString() << ":\n"
<< formatSet(staleBaseline).toStdString();
}
/** @brief Guards against duplicate or malformed baseline entries. */
TEST(IconAssets, BaselineIsWellFormed)
{
QSet<QString> baseline;
QString error;
ASSERT_TRUE(readBaseline(baseline, error)) << error.toStdString();
EXPECT_TRUE(baseline.isEmpty()) << "The legacy baseline is fully paid down; fix new violations instead";
static const QRegularExpression entryPattern(QStringLiteral(
R"(^(xml|viewbox|editor-metadata|hardcoded-color|color-filename|no-token|physical-size|raster) \S+$)"));
for (const QString &entry : baseline) {
EXPECT_TRUE(entryPattern.match(entry).hasMatch()) << "Malformed baseline entry: " << entry.toStdString();
}
} }