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 @@ -4,6 +4,7 @@

### Changed
- Core string assertions (`assert_contains`/`assert_not_contains`, `assert_matches`/`assert_not_matches`, `assert_string_starts_with`/`assert_string_ends_with` and their negations) no longer fork a subshell per call to join their arguments; a fork-free join with identical behaviour replaces it (#844)
- The array, date, duration, json, files and folders assertions now resolve their failure label through the fork-free slot helper instead of a per-call command substitution β€” same labels, fewer forks

## [0.42.0](https://github.com/TypedDevs/bashunit/compare/0.41.0...0.42.0) - 2026-07-20

Expand Down
5 changes: 2 additions & 3 deletions src/assert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ function bashunit::assert::label_to_slot() {
_BASHUNIT_ASSERT_JOINED_OUT=""

# Join positional args into _BASHUNIT_ASSERT_JOINED_OUT with no fork.
# Mirrors $(printf '%s\n' "$@"): joins with newlines and strips trailing
# newlines, so callers that match on the result behave exactly as the previous
# command-substitution did.
# Output matches $(printf '%s\n' "$@") exactly: newline-joined, trailing
# newlines stripped (as command substitution strips them).
function bashunit::assert::join_to_slot() {
local IFS=$'\n'
local joined="$*"
Expand Down
18 changes: 6 additions & 12 deletions src/assert_arrays.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ function assert_array_contains() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
shift

local -a actual
Expand All @@ -82,10 +80,8 @@ function assert_array_length() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
shift

# Use $# / $* rather than building an array: on Bash 3.0 under `set -u`,
Expand All @@ -106,10 +102,8 @@ function assert_array_not_contains() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
shift
local -a actual
actual=("$@")
Expand Down
30 changes: 10 additions & 20 deletions src/assert_dates.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,8 @@ function assert_date_equals() {
actual="$(bashunit::date::to_epoch "$2")"

if [ "$actual" -ne "$expected" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${actual}" "to be equal to" "${expected}"
return
Expand All @@ -126,10 +124,8 @@ function assert_date_before() {
actual="$(bashunit::date::to_epoch "$2")"

if [ "$actual" -ge "$expected" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${actual}" "to be before" "${expected}"
return
Expand All @@ -147,10 +143,8 @@ function assert_date_after() {
actual="$(bashunit::date::to_epoch "$2")"

if [ "$actual" -le "$expected" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${actual}" "to be after" "${expected}"
return
Expand All @@ -170,10 +164,8 @@ function assert_date_within_range() {
actual="$(bashunit::date::to_epoch "$3")"

if [ "$actual" -lt "$from" ] || [ "$actual" -gt "$to" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${actual}" "to be between" "${from} and ${to}"
return
Expand All @@ -197,10 +189,8 @@ function assert_date_within_delta() {
fi

if [ "$diff" -gt "$delta" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${actual}" "to be within" "${delta} seconds of ${expected}"
return
Expand Down
18 changes: 6 additions & 12 deletions src/assert_duration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ function assert_duration() {
elapsed_ms=$(bashunit::duration::measure_ms "$command")

if [ "$elapsed_ms" -gt "$threshold_ms" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${threshold_ms}" "to complete within (ms)" "${command}"
return
Expand All @@ -49,10 +47,8 @@ function assert_duration_less_than() {
elapsed_ms=$(bashunit::duration::measure_ms "$command")

if [ "$elapsed_ms" -ge "$threshold_ms" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${threshold_ms}" "to complete within (ms)" "${command}"
return
Expand All @@ -71,10 +67,8 @@ function assert_duration_greater_than() {
elapsed_ms=$(bashunit::duration::measure_ms "$command")

if [ "$elapsed_ms" -le "$threshold_ms" ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${threshold_ms}" "to take at least (ms)" "${command}"
return
Expand Down
50 changes: 18 additions & 32 deletions src/assert_files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ function assert_file_exists() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label="${3:-$(bashunit::helper::normalize_test_function_name "$test_fn")}"

if [ ! -f "$expected" ]; then
bashunit::assert::label_to_slot "${3:-}"
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${expected}" "to exist but" "do not exist"
return
Expand All @@ -21,11 +20,10 @@ function assert_file_not_exists() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label="${3:-$(bashunit::helper::normalize_test_function_name "$test_fn")}"

if [ -f "$expected" ]; then
bashunit::assert::label_to_slot "${3:-}"
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${expected}" "to not exist but" "the file exists"
return
Expand All @@ -38,11 +36,10 @@ function assert_is_file() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label="${3:-$(bashunit::helper::normalize_test_function_name "$test_fn")}"

if [ ! -f "$expected" ]; then
bashunit::assert::label_to_slot "${3:-}"
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${expected}" "to be a file" "but is not a file"
return
Expand All @@ -55,11 +52,10 @@ function assert_is_file_empty() {
bashunit::assert::should_skip && return 0

local expected="$1"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label="${3:-$(bashunit::helper::normalize_test_function_name "$test_fn")}"

if [ -s "$expected" ]; then
bashunit::assert::label_to_slot "${3:-}"
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed
bashunit::console_results::print_failed_test "${label}" "${expected}" "to be empty" "but is not empty"
return
Expand All @@ -75,10 +71,8 @@ function assert_files_equals() {
local actual="$2"

if [ "$(diff -u "$expected" "$actual")" != '' ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed

bashunit::console_results::print_failed_test "${label}" "${expected}" "Compared" "${actual}" \
Expand All @@ -96,10 +90,8 @@ function assert_files_not_equals() {
local actual="$2"

if [ "$(diff -u "$expected" "$actual")" = '' ]; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed

bashunit::console_results::print_failed_test "${label}" "${expected}" "Compared" "${actual}" \
Expand All @@ -117,10 +109,8 @@ function assert_file_contains() {
local string="$2"

if ! grep -F -q "$string" "$file"; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed

bashunit::console_results::print_failed_test "${label}" "${file}" "to contain" "${string}"
Expand All @@ -137,10 +127,8 @@ function assert_file_not_contains() {
local string="$2"

if grep -q "$string" "$file"; then
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT
bashunit::assert::mark_failed

bashunit::console_results::print_failed_test "${label}" "${file}" "to not contain" "${string}"
Expand Down Expand Up @@ -172,10 +160,8 @@ function assert_file_permissions() {

local expected="$1"
local file="$2"
local test_fn
test_fn="$(bashunit::helper::find_test_function_name)"
local label
label="$(bashunit::helper::normalize_test_function_name "$test_fn")"
bashunit::assert::label_to_slot
local label=$_BASHUNIT_ASSERT_LABEL_OUT

if [ ! -e "$file" ]; then
bashunit::assert::mark_failed
Expand Down
Loading
Loading