Skip to content

iccFromXml round-trip sweep silently tests 214 of 215 profiles: basename keying drops the tracked ApplyDataFiles/test-profiles/sRGB_D65_MAT.icc (_build-test-unix.yml:412-413) #2275

Description

@colourbill-ctrl

Describe the Bug

The iccFromXml round-trip stage of the full-test sweep silently covers 214 of the 215
profiles it reports on. Testing/ApplyDataFiles/test-profiles/sRGB_D65_MAT.icc — a tracked
fixture — is never round-tripped, because a different profile that happens to share its
basename overwrites its intermediate XML.

.github/workflows/_build-test-unix.yml:412-413 keys the intermediate on the basename
alone, flattening the whole Testing/ tree into one namespace:

base="$(basename "$icc" .icc)"
xmlout="$XMLDIR/${base}.xml"

Two different profiles collide there:

path bytes provenance
Testing/ApplyDataFiles/test-profiles/sRGB_D65_MAT.icc 24712 tracked (blob ea0af959)
Testing/Display/sRGB_D65_MAT.icc 24708 generated by Testing/CreateAllProfiles.sh from Testing/Display/sRGB_D65_MAT.xml

They are not copies of each other — different sizes, different content. The source list is
find "${WORKSPACE_DIR}/Testing" -name '*.icc' -type f | sort, so ApplyDataFiles/...
is visited first and Display/... second; the second write wins. The next step then
iterates "$XMLDIR"/*.xml, so only the Display/ variant is ever reconstructed and
classified.

The iccToXml step itself is unaffected — it runs on both files and checks each log before
the next iteration overwrites it. The loss is confined to the round-trip stage, and to the
per-file iccToXml log, which is also keyed on the bare basename (:372, :412).

Scope today is exactly one profile, but the flattening is structural: any future fixture
added under a second directory with an existing basename is dropped the same way, silently
and with the totals still looking right.

Build Instructions

cmake -S Build/Cmake -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TOOLS=ON -DENABLE_ICCXML=ON
cmake --build build -j4

Reproduce Bug or Crash

Static check — no build needed. Enumerate tracked .icc plus the names
CreateAllProfiles.sh generates, and look for a duplicate basename:

{ git ls-tree -r --name-only origin/master -- Testing | grep '\.icc$'
  git show origin/master:Testing/CreateAllProfiles.sh \
    | grep -oE 'iccFromXml +[^ ]+ +([^ ]+\.icc)' | awk '{print $3}'
} | xargs -n1 basename | sort | uniq -d
sRGB_D65_MAT.icc

Dynamic — reproduce the sweep's own arithmetic after sh CreateAllProfiles.sh:

cd Testing && sh CreateAllProfiles.sh >/dev/null 2>&1 && cd ..
find Testing -name '*.icc' -type f | wc -l                      # 215
find Testing -name '*.icc' -type f | xargs -n1 basename | sort -u | wc -l   # 214
find Testing -name 'sRGB_D65_MAT.icc' -type f | sort | xargs md5sum
215
214
89a3692c...  Testing/Display/sRGB_D65_MAT.icc                        <- wins
0da9f8d4...  Testing/ApplyDataFiles/test-profiles/sRGB_D65_MAT.icc   <- dropped

(The Display/ md5 varies per run — CreateAllProfiles.sh regenerates it and the header
carries a fresh dateTime/profileID. The size difference, 24708 vs 24712, is stable.)

Measured on 487e1994; f03b1e3e adds no .icc and does not touch profile generation, so
the count is unchanged on current master.

Triage

Coverage loss in CI tooling, not a library defect. No crash, no wrong output — the sweep
reports 214 logs ... 0 unclassified and passes. The failure mode is that it reports on a
corpus one profile smaller than the one it enumerated, without saying so.

Surfaced while measuring the corpus for #2265 (PR #2273).

Expected Behavior

Two defensible fixes; the choice is yours:

(a) Make the intermediate name unique. Derive it from the path relative to Testing/
with separators substituted, e.g. ApplyDataFiles_test-profiles_sRGB_D65_MAT. Restores full
coverage and is collision-proof for future fixtures. It renames every log and intermediate,
so any tooling that greps those names by hand would need a look.

(b) Detect and fail. Keep the flat naming and refuse to overwrite an existing
$xmlout, so a collision is a red lane rather than a silent drop. Smaller and louder, but
it leaves the profile untested until someone renames a fixture.

I'd lean (a), with the totals line reporting enumerated-vs-converted so a future mismatch is
visible either way. Happy to open the PR once you rule.

Environment

  • Affects the ubuntu-latest full-test leg only — _build-matrix.yml:67 gates
    run-full-tests on that OS, and the steps are guarded by if: inputs.run-full-tests.
  • Reproduced locally: Ubuntu (WSL2), clang-18 / GCC 15.2.0, CMAKE_BUILD_TYPE=Debug.

Additional Context

The same basename keying appears in the iccDumpProfile sweep (:372) and the iccToXml
sweep (:412). Those two run the tool once per file, so only their per-file logs collide;
the round-trip stage at :441 is the one that loses a test, because it consumes the
directory the collision wrote into.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BuildBuild system, CMake, compiler, or packagingJSONICC JSON parser, config, or round-trip behaviorTestingCTest, regression, or test coverageciContinuous integration workflow changesneeds-triageMaintainer triage required

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions