Skip to content

test(tests): run the UTF-8 suites on musl by falling back to C.UTF-8 - #175

Open
bfs2021 wants to merge 1 commit into
GingerGraham:mainfrom
bfs2021:musl-c-utf8
Open

bfs2021 wants to merge 1 commit into
GingerGraham:mainfrom
bfs2021:musl-c-utf8

Conversation

@bfs2021

@bfs2021 bfs2021 commented Nov 6, 2026 •

Copy link
Copy Markdown

Problem

In the Alpine (test-alpine) CI job and in the official bash:* images, every UTF-8 test skips: the summary shows 26 locale skips plus check-posix-compat.sh ... skipping because ShellCheck isn't installed, so CI reports 0 failures without having run the coverage that matters most on musl (the 3.0 BusyBox script-name bug appeared exactly there).

Fixes #152 (all four proposed fix steps from the issue are covered here)

Root cause

The test helpers discover a UTF-8 locale with locale -a. musl ships no locale utility, so the lookup returns nothing even though musl supports C.UTF-8 (and accepts every other locale name) without installed locale files — musl's default since 1.1.11 in 2015. The Alpine job also never installs ShellCheck.

Fix

  • Shared helper musl_c_utf8 in tests/test_helpers.sh: returns 0 on any musl system, by matching the ldd --version banner. musl's ldd prints the banner on stderr and exits 1, and run_tests.sh runs with pipefail, so the banner is captured first and the probe's status comes from grep alone (a plain pipeline always returns 1 under pipefail). No version floor: C.UTF-8 has been musl's default since 1.1.11 (2015), and a banner without a Version line can no longer change the result.
  • One shared utf8_locale_name in tests/test_helpers.sh holds the candidate loop plus the musl C.UTF-8 fallback; the copies in test_posix_compat.sh are gone. equivalence_utf8_locale (test_validator_equivalence.sh) keeps only the Linux-only check at the equivalence call site and delegates to the shared helper.
  • compat_locale_available (test_shell_compat.sh) routes its C.UTF-8 case through the shared helper; other names stay unavailable since musl only speaks UTF-8.
  • test_posix_levels_in_turkish_locale stays skipped on musl, with a reason: musl has no locale-specific case mapping, so tr_TR.UTF-8 behaves like C.UTF-8 and the test would pass even with the LC_ALL=C guard around the tr case mapping in logging.sh removed. Other systems keep the locale -a check.
  • New TEST_MAX_SKIPPED guard in run_tests.sh: when set, a run that skips more tests than the threshold fails. The test-alpine job sets TEST_MAX_SKIPPED=10 (the 5 intentional skips plus 5 Turkish-locale skips), so a future change cannot silently skip coverage again.
  • The test-alpine job installs shellcheck so check-posix-compat.sh runs there too.

Testing

In alpine:latest, non-root like CI, with the test-alpine job's command (TEST_SHELLS="bash,bash --posix,zsh,dash,busybox sh" TEST_REQUIRE_SHELLS="zsh dash busybox" plus TEST_MAX_SKIPPED=10):

  • Before: Total Tests: 907, Passed: 875, Failed: 0, Skipped: 32 — 26 locale skips (no UTF-8 locale installed, locale C.UTF-8 is not installed, tr_TR.UTF-8 locale not installed, ...), plus shellcheck not installed.
  • After: Total Tests: 907, Passed: 897, Failed: 0, Skipped: 10 — every UTF-8 test runs and passes on musl, including validators match validators_utf8.tsv and utf8_messages.sh matches bash. The 10 remaining skips are the 5 intentional ones plus the Turkish-locale test, now skipped on musl with its reason; TEST_MAX_SKIPPED=10 passes exactly at the threshold.
  • Guard verified: TEST_MAX_SKIPPED=0 on a suite with skips exits 1 with Error: 2 tests skipped, exceeding TEST_MAX_SKIPPED=0; a non-integer value is rejected the same way.
  • Non-musl systems are unaffected: on glibc locale -a still drives detection and musl_c_utf8 returns 1 (verified on Git Bash/MSYS, where locale -a lists C.utf8).

@bfs2021
bfs2021 requested a review from GingerGraham as a code owner November 6, 2026 20:36
@GingerGraham

Copy link
Copy Markdown
Owner

Thanks for this @bfs2021 . The C.UTF-8 fallback works: the Alpine job goes from 32 skips to 5, and the
bash:* jobs no longer skip the UTF-8 tests. A few changes before merge. Fixes #152 will close
the issue, so anything from it that isn't done here needs to be done or split into a new issue.

1. Keep the Turkish locale test skipped on musl
#152, proposed fix step 3: "Leave the Turkish locale test skipped on musl: musl has no
locale-specific case mapping, so the test would pass without checking anything."

The test checks the LC_ALL=C guard around the tr case mapping in logging.sh. On musl,
tr_TR.UTF-8 behaves like C.UTF-8 (as the PR description says, musl accepts any locale name),
so the test passes even if that guard is removed. Please revert the change to
test_posix_levels_in_turkish_locale. A skip reason that says why would help, e.g.
"musl has no locale-specific case mapping".

2. Add the skip-count guard
#152, last paragraph: "Add a CI check that fails if the Alpine job skips more tests than an
agreed number, so a future change can't silently skip them again."

With item 1 done, the Alpine job should skip 10 tests (the current 5 plus 5 Turkish). A
threshold such as TEST_MAX_SKIPPED=10 in the test-alpine job would do it, checked in
run_tests.sh or a workflow step. Applying the same check to the bash:* jobs is optional.

3. Use one shared locale lookup
#152, proposed fix step 1: "Move the three copies of the locale lookup ... into one
utf8_locale_name helper in tests/test_helpers.sh."

The PR adds the musl fallback to each copy separately. utf8_locale_name and
equivalence_utf8_locale are the same loop, so please merge them into one helper in
tests/test_helpers.sh, with the Linux-only check kept at the equivalence call site.
compat_locale_available checks whichever locale a scenario names, so it can't be replaced.
Its C.UTF-8 case should still go through the shared helper.

4. Drop the musl version floor, or give a source for it
#152, proposed fix step 2: "Detect musl from ldd --version 2>&1, which prints musl." The
issue sets no version floor.

As far as I can tell, C.UTF-8 has been musl's default since 1.1.11 in 2015
(https://openwall.com/lists/musl/2015/08/30/9), so I can't find a reason for 1.2.4. Unless you
have a source for 1.2.4, a plain musl check is simpler. It also fixes an edge case: at the
moment, a banner that contains "musl" but has no Version line returns 0.

5. Commit and PR title
tests is a scope in our Conventional Commits rules, not a type. Please use
test(tests): run the UTF-8 suites on musl by falling back to C.UTF-8.

@bfs2021 bfs2021 changed the title tests: run the UTF-8 suites on musl by falling back to C.UTF-8 test(tests): run the UTF-8 suites on musl by falling back to C.UTF-8 Nov 7, 2026
@bfs2021

bfs2021 commented Nov 7, 2026

Copy link
Copy Markdown
Author

All five points are addressed in 5e23c83:

  1. Turkish-locale test: reverted to skipping on musl, with the reason in the skip message ("musl has no locale-specific case mapping: the LC_ALL=C guard cannot be tested").
  2. Skip-count guard: run_tests.sh now fails when skips exceed TEST_MAX_SKIPPED, and the test-alpine job sets TEST_MAX_SKIPPED=10 (verified: the run passes with exactly 10 skips, and a lower threshold fails with the count in the error).
  3. One shared helper: the candidate loop and the musl fallback now live only in utf8_locale_name in tests/test_helpers.sh; equivalence_utf8_locale keeps the Linux-only check at the equivalence call site and delegates, and compat_locale_available routes its C.UTF-8 case through the shared helper.
  4. Version floor dropped: musl_c_utf8 is now a plain musl check on the ldd --version banner (C.UTF-8 has been musl's default since 1.1.11, 2015), which also removes the dependence on a Version line being present.
  5. Title: commit and PR retitled to test(tests): run the UTF-8 suites on musl by falling back to C.UTF-8.

With these in, all four proposed fix steps from #152 are covered by this PR, so Fixes #152 needs no split-off issue. Full alpine:latest run as non-root with the CI command: 907 tests, 0 failed, 10 skipped.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] UTF-8 tests skip on Alpine and the bash:* CI images

2 participants