Skip to content

Commit a18a6ff

Browse files
authored
Merge pull request #483 from carlfriedrich/fix/always-correctly-clean-up-temp-contents
Always correctly clean up temp contents
2 parents d0bfd31 + f51c51c commit a18a6ff

File tree

9 files changed

+122
-20
lines changed

9 files changed

+122
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- Make Windows install clearer in the docs by adding an option for Linux/Mac and another one for Windows.
77
- Add support for empty values and values containing spaces in data providers via new `data_set` function
88
- Document workaround for global function name collisions when sourcing scripts in tests by copying the original function
9+
- Fix `temp_dir` and `temp_file` data not being cleaned up when created in `set_up_before_script`
910

1011
## [0.23.0](https://github.com/TypedDevs/bashunit/compare/0.22.3...0.23.0) - 2025-08-03
1112

docs/globals.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ Internal messages from bashunit include the `[INTERNAL]` prefix so you can easil
5858

5959
> `temp_file <?prefix>`: creates a temporal file
6060
61+
The file is automatically deleted when bashunit completes.
62+
6163
## temp_dir
6264

6365
> `temp_dir <?prefix>`: creates a temporal directory
6466
67+
The directory is automatically deleted when bashunit completes.
68+
6569
## is_command_available
6670

6771
> `is_command_available`: Checks if command is available

src/globals.sh

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ function temp_file() {
4343
mkdir -p "$base_dir" && chmod -R 777 "$base_dir"
4444
local test_prefix=""
4545
if [[ -n "${BASHUNIT_CURRENT_TEST_ID:-}" ]]; then
46+
# We're inside a test function - use test ID
4647
test_prefix="${BASHUNIT_CURRENT_TEST_ID}_"
48+
elif [[ -n "${BASHUNIT_CURRENT_SCRIPT_ID:-}" ]]; then
49+
# We're at script level (e.g., in set_up_before_script) - use script ID
50+
test_prefix="${BASHUNIT_CURRENT_SCRIPT_ID}_"
4751
fi
4852
mktemp "$base_dir/${test_prefix}${prefix}.XXXXXXX"
4953
}
@@ -54,17 +58,26 @@ function temp_dir() {
5458
mkdir -p "$base_dir" && chmod -R 777 "$base_dir"
5559
local test_prefix=""
5660
if [[ -n "${BASHUNIT_CURRENT_TEST_ID:-}" ]]; then
61+
# We're inside a test function - use test ID
5762
test_prefix="${BASHUNIT_CURRENT_TEST_ID}_"
63+
elif [[ -n "${BASHUNIT_CURRENT_SCRIPT_ID:-}" ]]; then
64+
# We're at script level (e.g., in set_up_before_script) - use script ID
65+
test_prefix="${BASHUNIT_CURRENT_SCRIPT_ID}_"
5866
fi
5967
mktemp -d "$base_dir/${test_prefix}${prefix}.XXXXXXX"
6068
}
6169

62-
function cleanup_temp_files() {
63-
internal_log "cleanup_temp_files"
70+
function cleanup_testcase_temp_files() {
71+
internal_log "cleanup_testcase_temp_files"
6472
if [[ -n "${BASHUNIT_CURRENT_TEST_ID:-}" ]]; then
6573
rm -rf "${TMPDIR:-/tmp}/bashunit/tmp/${BASHUNIT_CURRENT_TEST_ID}"_*
66-
else
67-
rm -rf "${TMPDIR:-/tmp}/bashunit/tmp"/*
74+
fi
75+
}
76+
77+
function cleanup_script_temp_files() {
78+
internal_log "cleanup_script_temp_files"
79+
if [[ -n "${BASHUNIT_CURRENT_SCRIPT_ID:-}" ]]; then
80+
rm -rf "${TMPDIR:-/tmp}/bashunit/tmp/${BASHUNIT_CURRENT_SCRIPT_ID}"_*
6881
fi
6982
}
7083

src/helpers.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,14 @@ function helper::get_function_line_number() {
328328

329329
echo "$line_number"
330330
}
331+
332+
function helper::generate_id() {
333+
local basename="$1"
334+
local sanitized_basename
335+
sanitized_basename="$(helper::normalize_variable_name "$basename")"
336+
if env::is_parallel_run_enabled; then
337+
echo "${sanitized_basename}_$$_$(random_str 6)"
338+
else
339+
echo "${sanitized_basename}_$$"
340+
fi
341+
}

src/main.sh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ function main::exec_tests() {
7070
reports::generate_report_html "$BASHUNIT_REPORT_HTML"
7171
fi
7272

73-
cleanup_temp_files
7473
internal_log "Finished tests" "exit_code:$exit_code"
7574
exit $exit_code
7675
}
@@ -98,23 +97,22 @@ function main::exec_benchmarks() {
9897

9998
benchmark::print_results
10099

101-
cleanup_temp_files
102100
internal_log "Finished benchmarks"
103101
}
104102

105103
function main::cleanup() {
106104
printf "%sCaught Ctrl-C, killing all child processes...%s\n" "${_COLOR_SKIPPED}" "${_COLOR_DEFAULT}"
107105
# Kill all child processes of this script
108106
pkill -P $$
109-
cleanup_temp_files
107+
cleanup_script_temp_files
110108
exit 1
111109
}
112110

113111
function main::handle_stop_on_failure_sync() {
114112
printf "\n%sStop on failure enabled...%s\n" "${_COLOR_SKIPPED}" "${_COLOR_DEFAULT}"
115113
console_results::print_failing_tests_and_reset
116114
console_results::render_result
117-
cleanup_temp_files
115+
cleanup_script_temp_files
118116
exit 1
119117
}
120118

src/runner.sh

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ function runner::load_test_files() {
55
local filter=$1
66
shift
77
local files=("${@}")
8+
local scripts_ids=()
89

910
for test_file in "${files[@]}"; do
1011
if [[ ! -f $test_file ]]; then
1112
continue
1213
fi
14+
unset BASHUNIT_CURRENT_TEST_ID
15+
export BASHUNIT_CURRENT_SCRIPT_ID="$(helper::generate_id "${test_file}")"
16+
scripts_ids+=("${BASHUNIT_CURRENT_SCRIPT_ID}")
1317
internal_log "Loading file" "$test_file"
1418
# shellcheck source=/dev/null
1519
source "$test_file"
@@ -21,6 +25,9 @@ function runner::load_test_files() {
2125
fi
2226
runner::run_tear_down_after_script
2327
runner::clean_set_up_and_tear_down_after_script
28+
if ! parallel::is_enabled; then
29+
cleanup_script_temp_files
30+
fi
2431
internal_log "Finished file" "$test_file"
2532
done
2633

@@ -32,6 +39,10 @@ function runner::load_test_files() {
3239
# Kill the spinner once the aggregation finishes
3340
disown "$spinner_pid" && kill "$spinner_pid" &>/dev/null
3441
printf "\r " # Clear the spinner output
42+
for script_id in "${scripts_ids[@]}"; do
43+
export BASHUNIT_CURRENT_SCRIPT_ID="${script_id}"
44+
cleanup_script_temp_files
45+
done
3546
fi
3647
}
3748

@@ -42,12 +53,15 @@ function runner::load_bench_files() {
4253

4354
for bench_file in "${files[@]}"; do
4455
[[ -f $bench_file ]] || continue
56+
unset BASHUNIT_CURRENT_TEST_ID
57+
export BASHUNIT_CURRENT_SCRIPT_ID="$(helper::generate_id "${test_file}")"
4558
# shellcheck source=/dev/null
4659
source "$bench_file"
4760
runner::run_set_up_before_script
4861
runner::call_bench_functions "$bench_file" "$filter"
4962
runner::run_tear_down_after_script
5063
runner::clean_set_up_and_tear_down_after_script
64+
cleanup_script_temp_files
5165
done
5266
}
5367

@@ -232,17 +246,11 @@ function runner::run_test() {
232246
local fn_name="$1"
233247
shift
234248

249+
internal_log "Running test" "$fn_name" "$*"
235250
# Export a unique test identifier so that test doubles can
236251
# create temporary files scoped per test run. This prevents
237252
# race conditions when running tests in parallel.
238-
local sanitized_fn_name
239-
sanitized_fn_name="$(helper::normalize_variable_name "$fn_name")"
240-
internal_log "Running test" "$fn_name" "$*"
241-
if env::is_parallel_run_enabled; then
242-
export BASHUNIT_CURRENT_TEST_ID="${sanitized_fn_name}_$$_$(random_str 6)"
243-
else
244-
export BASHUNIT_CURRENT_TEST_ID="${sanitized_fn_name}_$$"
245-
fi
253+
export BASHUNIT_CURRENT_TEST_ID="$(helper::generate_id "$fn_name")"
246254

247255
state::reset_test_title
248256

@@ -265,6 +273,7 @@ function runner::run_test() {
265273
state::set_test_exit_code "$exit_code"
266274
runner::run_tear_down
267275
runner::clear_mocks
276+
cleanup_testcase_temp_files
268277
state::export_subshell_context
269278
' EXIT
270279
state::initialize_assertions_count
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bash
2+
3+
# @data_provider execution_modes
4+
function test_script_temp_files_are_cleaned_up_after_test_run() {
5+
local mode="$1"
6+
local fixture_file="tests/acceptance/fixtures/script_with_setup_temp_file.sh"
7+
local temp_base_dir="${TMPDIR:-/tmp}/bashunit/tmp"
8+
local output
9+
10+
if [[ "$mode" == "parallel" ]]; then
11+
output=$(./bashunit --parallel "$fixture_file" 2>&1)
12+
else
13+
output=$(./bashunit "$fixture_file" 2>&1)
14+
fi
15+
16+
# Check that the test run was successful
17+
assert_contains "All tests passed" "$output"
18+
19+
# Check that no script-setup temp files remain in the temp directory
20+
local remaining_files
21+
if [[ -d "$temp_base_dir" ]]; then
22+
remaining_files=$(find "$temp_base_dir" -name "*script-setup*" 2>/dev/null || true)
23+
24+
assert_empty "$remaining_files"
25+
26+
# Manually clean up remaining files
27+
if [[ -n "$remaining_files" ]]; then
28+
echo "$remaining_files" | xargs rm -rf 2>/dev/null || true
29+
fi
30+
fi
31+
}
32+
33+
function execution_modes() {
34+
echo "sequential"
35+
echo "parallel"
36+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
3+
function set_up_before_script() {
4+
SCRIPT_TEMP_FILE=$(temp_file "script-setup")
5+
SCRIPT_TEMP_DIR=$(temp_dir "script-setup")
6+
echo "Script temp file created: $SCRIPT_TEMP_FILE" > "$SCRIPT_TEMP_FILE"
7+
echo "Script temp dir created: $SCRIPT_TEMP_DIR" > "$SCRIPT_TEMP_DIR/marker.txt"
8+
}
9+
10+
function test_simple_passing_test() {
11+
assert_equals "1" "1"
12+
}
13+
14+
function test_another_simple_test() {
15+
assert_file_exists "$SCRIPT_TEMP_FILE"
16+
assert_directory_exists "$SCRIPT_TEMP_DIR"
17+
}

tests/unit/globals_test.sh

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
set -euo pipefail
66

7+
function set_up_before_script() {
8+
SCRIPT_TEMP_FILE=$(temp_file "custom-prefix")
9+
SCRIPT_TEMP_DIR=$(temp_dir "custom-prefix")
10+
}
11+
712
function tear_down_after_script() {
813
export BASHUNIT_DEV_LOG=""
914
}
@@ -58,22 +63,30 @@ function test_globals_random_str_custom_len() {
5863
assert_matches "^[A-Za-z0-9]{3}$" "$(random_str 3)"
5964
}
6065

61-
function test_globals_temp_file() {
66+
function test_globals_temp_file_in_test_function() {
6267
# shellcheck disable=SC2155
6368
local temp_file=$(temp_file "custom-prefix")
6469
assert_file_exists "$temp_file"
65-
cleanup_temp_files
70+
cleanup_testcase_temp_files
6671
assert_file_not_exists "$temp_file"
6772
}
6873

69-
function test_globals_temp_dir() {
74+
function test_globals_temp_dir_in_test_function() {
7075
# shellcheck disable=SC2155
7176
local temp_dir=$(temp_dir "custom-prefix")
7277
assert_directory_exists "$temp_dir"
73-
cleanup_temp_files
78+
cleanup_testcase_temp_files
7479
assert_directory_not_exists "$temp_dir"
7580
}
7681

82+
function test_globals_temp_dir_and_file_in_script() {
83+
assert_directory_exists "$SCRIPT_TEMP_DIR"
84+
assert_file_exists "$SCRIPT_TEMP_FILE"
85+
cleanup_script_temp_files
86+
assert_directory_not_exists "$SCRIPT_TEMP_DIR"
87+
assert_file_not_exists "$SCRIPT_TEMP_FILE"
88+
}
89+
7790
function test_globals_log_level_error() {
7891
log "error" "hello," "error"
7992

0 commit comments

Comments
 (0)