From d0c062a6f6cc4bb523559c6996ab2ace56f42718 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sat, 11 Jul 2026 14:47:57 +0200 Subject: [PATCH] perf(state): skip base64 forks for empty subshell-context fields Extract encode_field, which returns an empty field for empty input without forking base64 (base64 of "" is "" anyway, so the wire format is unchanged). A passing test's title, hook message and output are all empty, so this removes three forks per test. Also short-circuit decode_base64 on empty input. No behaviour change. Closes #762. --- CHANGELOG.md | 1 + src/helpers.sh | 4 ++-- src/state.sh | 37 +++++++++++++++++++++++++------------ tests/unit/state_test.sh | 28 ++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 859ff94e..d3633da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed - Faster test execution: each test file's data-provider annotations are scanned once and cached, replacing a per-test `grep`+`sed` probe with a pure-bash lookup (no behaviour change) (#763) +- Faster test execution: skip the base64 encode fork for a test's empty title, hook message and output (the common case), and short-circuit decoding of empty fields (no behaviour change) (#762) ## [0.41.0](https://github.com/TypedDevs/bashunit/compare/0.40.0...0.41.0) - 2026-07-11 diff --git a/src/helpers.sh b/src/helpers.sh index 4ae08505..9ee3747e 100755 --- a/src/helpers.sh +++ b/src/helpers.sh @@ -149,8 +149,8 @@ function bashunit::helper::encode_base64() { function bashunit::helper::decode_base64() { local value="$1" - # Handle empty string marker - if [ "$value" = "_BASHUNIT_EMPTY_" ]; then + # Empty input decodes to empty; short-circuit to skip the base64 fork (#762). + if [ -z "$value" ] || [ "$value" = "_BASHUNIT_EMPTY_" ]; then printf '' return fi diff --git a/src/state.sh b/src/state.sh index 80c8281c..285778a9 100644 --- a/src/state.sh +++ b/src/state.sh @@ -228,23 +228,36 @@ function bashunit::state::initialize_assertions_count() { _BASHUNIT_ASSERTION_FAILED_IN_TEST=0 } +# base64-encodes a field, writing the result into _BASHUNIT_STATE_ENCODED_OUT. +# Empty values (the common case for title/hook message, and output on a passing +# test) encode to an empty field with no base64 fork (#762). base64 of "" is "" +# anyway, so this stays wire-compatible. +_BASHUNIT_STATE_ENCODED_OUT="" +function bashunit::state::encode_field() { + local value=$1 + if [ -z "$value" ]; then + _BASHUNIT_STATE_ENCODED_OUT="" + return + fi + if [ "$_BASHUNIT_BASE64_WRAP_FLAG" = true ]; then + # Alpine requires the -w 0 option to avoid wrapping + _BASHUNIT_STATE_ENCODED_OUT=$(echo -n "$value" | base64 -w 0) + else + _BASHUNIT_STATE_ENCODED_OUT=$(echo -n "$value" | base64) + fi +} + function bashunit::state::export_subshell_context() { local encoded_test_output local encoded_test_title - local encoded_test_hook_message - if [ "$_BASHUNIT_BASE64_WRAP_FLAG" = true ]; then - # Alpine requires the -w 0 option to avoid wrapping - encoded_test_output=$(echo -n "$_BASHUNIT_TEST_OUTPUT" | base64 -w 0) - encoded_test_title=$(echo -n "$_BASHUNIT_TEST_TITLE" | base64 -w 0) - encoded_test_hook_message=$(echo -n "$_BASHUNIT_TEST_HOOK_MESSAGE" | base64 -w 0) - else - # macOS and others: default base64 without wrapping - encoded_test_output=$(echo -n "$_BASHUNIT_TEST_OUTPUT" | base64) - encoded_test_title=$(echo -n "$_BASHUNIT_TEST_TITLE" | base64) - encoded_test_hook_message=$(echo -n "$_BASHUNIT_TEST_HOOK_MESSAGE" | base64) - fi + bashunit::state::encode_field "$_BASHUNIT_TEST_OUTPUT" + encoded_test_output=$_BASHUNIT_STATE_ENCODED_OUT + bashunit::state::encode_field "$_BASHUNIT_TEST_TITLE" + encoded_test_title=$_BASHUNIT_STATE_ENCODED_OUT + bashunit::state::encode_field "$_BASHUNIT_TEST_HOOK_MESSAGE" + encoded_test_hook_message=$_BASHUNIT_STATE_ENCODED_OUT cat <