Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
### Fixed
- A test that exited non-zero no longer poisons the exit code of subsequent tests in the same file (the per-test exit code was accumulated instead of reset)
- Coverage report now counts backslash line-continuation lines as covered: a multi-line statement's hit is propagated forward across its continuation chain, so the lines after a trailing `\` are no longer reported as uncovered (#722)
- Spying or mocking the `printf` builtin no longer breaks coverage collection: the coverage buffer is now flushed with `builtin printf`, so a test double can no longer shadow the write and silently drop all coverage data for that test (#724)

### Changed
- Documentation and project URLs now point to the new primary domain `bashunit.com` (old `bashunit.typeddevs.com` continues to work as a redirect)
Expand Down
8 changes: 5 additions & 3 deletions src/coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,13 @@ function bashunit::coverage::flush_buffer() {
test_hits_file="${_BASHUNIT_COVERAGE_TEST_HITS_FILE}.$$"
fi

# Write buffered data in a single I/O operation
printf '%s' "$_BASHUNIT_COVERAGE_BUFFER" >>"$data_file"
# Write buffered data in a single I/O operation.
# Use `builtin printf` so a user test spying/mocking the printf builtin
# cannot shadow the coverage write and silently drop data (see issue #724).
builtin printf '%s' "$_BASHUNIT_COVERAGE_BUFFER" >>"$data_file"

if [ -n "$_BASHUNIT_COVERAGE_HITS_BUFFER" ]; then
printf '%s' "$_BASHUNIT_COVERAGE_HITS_BUFFER" >>"$test_hits_file"
builtin printf '%s' "$_BASHUNIT_COVERAGE_HITS_BUFFER" >>"$test_hits_file"
fi

# Reset buffer
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/coverage_core_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,33 @@ function test_coverage_record_line_writes_to_file() {
assert_contains "$test_file:20" "$content"
}

function test_coverage_flush_buffer_writes_even_when_printf_is_spied() {
BASHUNIT_COVERAGE="true"
BASHUNIT_COVERAGE_PATHS="/"
BASHUNIT_COVERAGE_EXCLUDE=""
bashunit::coverage::init

local test_file="/some/path/script.sh"
bashunit::coverage::record_line "$test_file" "10"
bashunit::coverage::record_line "$test_file" "20"

# Spying printf must not shadow the coverage write (issue #724)
bashunit::spy printf
bashunit::coverage::flush_buffer
bashunit::unmock printf

local data_file="$_BASHUNIT_COVERAGE_DATA_FILE"
if bashunit::parallel::is_enabled; then
data_file="${_BASHUNIT_COVERAGE_DATA_FILE}.$$"
fi

local content
content=$(cat "$data_file")

assert_contains "$test_file:10" "$content"
assert_contains "$test_file:20" "$content"
}

function test_coverage_cleanup_removes_temp_files() {
BASHUNIT_COVERAGE="true"
bashunit::coverage::init
Expand Down
Loading