From c08428d381b2db644a48094e105c2289ba090fb9 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 14 Jun 2026 22:03:04 +0300 Subject: om0 fix camera slug collisions and align ISO fallback order Review follow-up on the stats aggregation module: - Distinct camera labels that sanitized to the same slug (e.g. two models differing only in punctuation) shared one STATS_CAMERA_PHOTOS list and one camera-.html link, so um0 would render a merged/ambiguous per-camera page. Add _stats_resolve_camera_slug, which uniquifies colliding slugs with a numeric suffix and tracks ownership in a new STATS_SLUG_OWNERS reverse map. It returns via a nameref (not command substitution) so the global mutation persists in the caller's shell. - Align the stats ISO fallback order with album.source.sh's tooltip builder (ISOSpeedRatings -> PhotographicSensitivity -> ISO) so a photo with multiple ISO tags buckets the same value it displays. - Document that the format breakdown trusts the file extension. - Add test_stats_distinct_cameras_get_unique_slugs covering the collision fix and slug reuse on re-encounter. Co-Authored-By: Claude Opus 4.8 --- tests/cli.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'tests/cli.sh') diff --git a/tests/cli.sh b/tests/cli.sh index 6ae69cc..423bc49 100755 --- a/tests/cli.sh +++ b/tests/cli.sh @@ -4982,6 +4982,32 @@ test_stats_tolerates_missing_and_edge_case_fields() { test::teardown } +test_stats_distinct_cameras_get_unique_slugs() { + test::setup + test::source_shuriken_lib + reset_photo_exif_stats + + # Two distinct camera labels that sanitize to the same base slug must keep + # separate leaderboard entries, separate camera-.html slugs, and + # separate per-camera photo lists (regression: slug collision merged them). + accumulate_photo_stats 'a.jpg' <<< $' exif:Model: Canon EOS 1D' + accumulate_photo_stats 'b.jpg' <<< $' exif:Model: Canon EOS-1D!!' + + test "${STATS_CAMERAS[Canon EOS 1D]}" -eq 1 + test "${STATS_CAMERAS[Canon EOS-1D!!]}" -eq 1 + test "${STATS_CAMERA_SLUGS[Canon EOS 1D]}" = 'canon-eos-1d' + test "${STATS_CAMERA_SLUGS[Canon EOS-1D!!]}" = 'canon-eos-1d-2' + test "${STATS_CAMERA_PHOTOS[canon-eos-1d]}" = 'a.jpg' + test "${STATS_CAMERA_PHOTOS[canon-eos-1d-2]}" = 'b.jpg' + + # Re-encountering the first camera reuses its slug and appends, not a new one. + accumulate_photo_stats 'c.jpg' <<< $' exif:Model: Canon EOS 1D' + test "${STATS_CAMERAS[Canon EOS 1D]}" -eq 2 + test "${STATS_CAMERA_PHOTOS[canon-eos-1d]}" = $'a.jpg\nc.jpg' + + test::teardown +} + test_stats_bucket_boundaries_and_datetime_parsing() { test::setup test::source_shuriken_lib @@ -5347,6 +5373,9 @@ main() { test::run_case \ 'stats tolerate missing and edge-case fields' \ test_stats_tolerates_missing_and_edge_case_fields + test::run_case \ + 'stats give distinct cameras unique slugs' \ + test_stats_distinct_cameras_get_unique_slugs test::run_case \ 'stats bucket boundaries and datetime parsing' \ test_stats_bucket_boundaries_and_datetime_parsing -- cgit v1.2.3