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 @@ -14,6 +14,7 @@
- The `--parallel` unsupported-OS warning no longer claims Alpine is excluded: Alpine has been a supported parallel platform since the race conditions were fixed, the message was simply never updated

### Fixed
- `bashunit assert <name>` with no arguments now reports a clear error and exits non-zero. It used to compute a `-1` array index, which Bash 3.x rejects, so it leaked a raw `bad array subscript` and still exited `0` — a malformed standalone assertion in a deploy script reported success (#877)
- A missing `--env`/`--boot` bootstrap file is now an error instead of a green run that tested nothing: the file used to be sourced unchecked, so a typo'd path leaked a raw `No such file or directory`, skipped the entire suite and still exited `0`. The report options (`--report-json`, `--log-junit`, `--report-tap`, `--report-html`, `--log-gha`) are likewise checked before the run instead of failing silently after it — an unwritable destination produced a passing run, no report on disk, and exit `0`. `--seed` now validates as a non-negative integer like the other numeric options (#875)
- The numeric options (`--jobs`, `--retry`, `--test-timeout`, `--coverage-min`) and `--output` now reject an invalid value with a clear error and a non-zero exit, instead of dropping the setting. `--jobs abc` was the worst case: `[ n -lt abc ]` errors rather than returning false, so the Bash 3.x job-slot poll never reached its `break` and the run **hung**, while Bash 4.3+ silently ignored the concurrency limit. `--coverage-min abc` leaked a raw `[: abc: integer expression expected` and still exited `0`, so a CI job never enforced its threshold. Validation runs on the resolved configuration, so it covers the `BASHUNIT_*` environment variables too (#873)
- An unknown option is now rejected with a clear error and a non-zero exit instead of being silently filed under test paths. A mistyped flag used to degrade the run while still reporting success: `bashunit --parralel tests/` ran sequentially and exited `0`, and `bashunit --filterr foo tests/` swallowed both the flag and its value and ran the whole suite. Applies to `test` and `bench`; the `assert` subcommand parses its own arguments and is unchanged (#871)
Expand Down
10 changes: 10 additions & 0 deletions src/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,16 @@ function bashunit::main::exec_assert() {
fi
fi

# Every assertion needs at least one argument. Without this guard args_count is
# 0, so the last_index below is -1: Bash 3.x has no negative subscripts, so the
# expansion failed with a raw `bad array subscript` and the run still exited 0
# (#877).
if [ "$args_count" -lt 1 ]; then
printf "%sError: assert %s requires at least one argument.%s\n" \
"${_BASHUNIT_COLOR_FAILED}" "$original_assert_fn" "${_BASHUNIT_COLOR_DEFAULT}" >&2
exit 1
fi

# Get the last argument safely by calculating the array length
local last_index=$((args_count - 1))
local last_arg="${args[$last_index]}"
Expand Down
29 changes: 29 additions & 0 deletions tests/acceptance/bashunit_assert_errors_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,35 @@ function test_bashunit_assert_subcommand_non_existing_function() {
assert_command_not_found "" "" "$exit_code"
}

# args_count was 0, so `${args[-1]}` expanded to a negative subscript: a raw
# `bad array subscript` on Bash 3.x, and the run still exited 0 (#877).
function test_bashunit_assert_subcommand_without_arguments() {
local output
local exit_code
output=$(./bashunit assert equals 2>&1) && exit_code=$? || exit_code=$?

assert_general_error "" "" "$exit_code"
assert_not_contains "bad array subscript" "$output"
assert_contains "equals" "$output"
}

function test_bashunit_assert_subcommand_without_arguments_for_a_code_assertion() {
local output
local exit_code
output=$(./bashunit assert successful_code 2>&1) && exit_code=$? || exit_code=$?

assert_general_error "" "" "$exit_code"
assert_not_contains "bad array subscript" "$output"
}

function test_bashunit_assert_subcommand_still_accepts_a_single_argument() {
local output
local exit_code
output=$(./bashunit assert empty "" 2>&1) && exit_code=$? || exit_code=$?

assert_successful_code "" "" "$exit_code"
}

function test_bashunit_assert_subcommand_failure() {
local exit_code
./bashunit --no-parallel assert equals "foo" "bar" 2>&1 && exit_code=$? || exit_code=$?
Expand Down
Loading