Skip to content

--coverage-paths with a space breaks the DEBUG trap and fails the test #1245

Description

@Chemaclass

Problem

A coverage path containing a space produces a DEBUG trap that does not parse:

$ bashunit --coverage --coverage-paths "my src/" "my test.sh"
src/runner/exec.sh: debug trap: line 265: syntax error near unexpected token `src/*'
… 75 more
Tests:      0 passed, 1 failed, 1 total
Assertions: 1 passed, 0 failed, 1 total
my src/math lib.sh                         0/  1 lines (  0%)

Three things go wrong at once, and the last is the worst:

  • 75 syntax errors on stderr for a one-test run
  • coverage reports 0% because record_line never runs
  • the test is reported failed while its own assertion passed — the trap's failures poison the test status, so a green suite turns red for a reason that has nothing to do with the code under test

Cause

bashunit::coverage::build_trap_glob bakes the paths into a case pattern as syntax — deliberately, since | arriving through a variable would not split. But the literal segments are interpolated unquoted:

glob="$glob${resolved}*|${relative}*|./${relative}*|*/${relative}/*|*/${relative}"

so my src reaches the trap as my src/* and the case is a syntax error.

Fix

Single-quote the literal segments, leaving * and | as syntax. That also reads more correctly: a coverage path is a literal, so a [ or ? in a directory name should not act as a pattern.

An embedded apostrophe has to be escaped as '\'', and the literal spelling of that cannot be written inline — the replacement in ${var//pat/repl} processes backslashes and hands it back mangled, which is worth a comment because it looks like it should work.

Note on the existing tests

Three tests in tests/unit/coverage/lookup_test.sh assert the glob's spelling with assert_contains, so they fail on the added quotes although the behaviour they protect is unchanged. The same file already has a glob_matches helper that evals the pattern; switching them to it asserts what the glob admits instead — which is also the only way to tell a pattern that parses from one that parses and matches nothing.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions