Skip to content

Commit 197f4b2

Browse files
committed
refactor(compat): inline regex matching and remove bashunit::regex_match wrapper
1 parent eda74cc commit 197f4b2

8 files changed

Lines changed: 151 additions & 131 deletions

File tree

src/assert.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ function bashunit::run_command_or_eval() {
8787
if [[ "$cmd" =~ $_re ]]; then
8888
eval "${cmd#eval }" &>/dev/null
8989
else
90-
_re='^alias'
91-
if [[ "$(command -v "$cmd")" =~ $_re ]]; then
92-
eval "$cmd" &>/dev/null
93-
else
94-
"$cmd" &>/dev/null
90+
_re='^alias'
91+
if [[ "$(command -v "$cmd")" =~ $_re ]]; then
92+
eval "$cmd" &>/dev/null
93+
else
94+
"$cmd" &>/dev/null
95+
fi
9596
fi
9697
return $?
9798
}

src/benchmark.sh

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,34 @@ function bashunit::benchmark::parse_annotations() {
1616
local annotation
1717
annotation=$(awk "/function[[:space:]]+${fn_name}[[:space:]]*\(/ {print prev; exit} {prev=\$0}" "$script")
1818

19-
if bashunit::regex_match "$annotation" '@revs=([0-9]+)'; then
20-
revs="${BASH_REMATCH[1]}"
21-
elif bashunit::regex_match "$annotation" '@revolutions=([0-9]+)'; then
19+
local _re='@revs=([0-9]+)'
20+
if [[ "$annotation" =~ $_re ]]; then
2221
revs="${BASH_REMATCH[1]}"
22+
else
23+
_re='@revolutions=([0-9]+)'
24+
if [[ "$annotation" =~ $_re ]]; then
25+
revs="${BASH_REMATCH[1]}"
26+
fi
2327
fi
2428

25-
if bashunit::regex_match "$annotation" '@its=([0-9]+)'; then
26-
its="${BASH_REMATCH[1]}"
27-
elif bashunit::regex_match "$annotation" '@iterations=([0-9]+)'; then
29+
_re='@its=([0-9]+)'
30+
if [[ "$annotation" =~ $_re ]]; then
2831
its="${BASH_REMATCH[1]}"
32+
else
33+
_re='@iterations=([0-9]+)'
34+
if [[ "$annotation" =~ $_re ]]; then
35+
its="${BASH_REMATCH[1]}"
36+
fi
2937
fi
3038

31-
if bashunit::regex_match "$annotation" '@max_ms=([0-9.]+)'; then
32-
max_ms="${BASH_REMATCH[1]}"
33-
elif bashunit::regex_match "$annotation" '@max_ms=([0-9.]+)'; then
39+
_re='@max_ms=([0-9.]+)'
40+
if [[ "$annotation" =~ $_re ]]; then
3441
max_ms="${BASH_REMATCH[1]}"
42+
else
43+
_re='@max_ms=([0-9.]+)'
44+
if [[ "$annotation" =~ $_re ]]; then
45+
max_ms="${BASH_REMATCH[1]}"
46+
fi
3547
fi
3648

3749
if [[ -n "$max_ms" ]]; then

src/console_header.sh

Lines changed: 96 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,27 @@ function bashunit::console_header::print_help() {
6363
Usage: bashunit <command> [arguments] [options]
6464
6565
Commands:
66-
test [path] Run tests (default command)
67-
bench [path] Run benchmarks
68-
assert <fn> <args> Run standalone assertion
69-
doc [filter] Display assertion documentation
70-
init [dir] Initialize a new test directory
71-
learn Start interactive tutorial
72-
upgrade Upgrade bashunit to latest version
66+
test [path] Run tests (default command)
67+
bench [path] Run benchmarks
68+
assert <fn> <args> Run standalone assertion
69+
doc [filter] Display assertion documentation
70+
init [dir] Initialize a new test directory
71+
learn Start interactive tutorial
72+
upgrade Upgrade bashunit to latest version
7373
7474
Global Options:
75-
-h, --help Show this help message
76-
-v, --version Display the current version
75+
-h, --help Show this help message
76+
-v, --version Display the current version
7777
7878
Run 'bashunit <command> --help' for command-specific options.
7979
8080
Examples:
81-
bashunit test tests/ Run all tests in directory
82-
bashunit tests/ Run all tests (shorthand)
83-
bashunit bench Run all benchmarks
84-
bashunit assert equals "foo" "foo" Run standalone assertion
85-
bashunit doc contains Show docs for 'contains' assertions
86-
bashunit init Initialize test directory
81+
bashunit test tests/ Run all tests in directory
82+
bashunit tests/ Run all tests (shorthand)
83+
bashunit bench Run all benchmarks
84+
bashunit assert equals "foo" "foo" Run standalone assertion
85+
bashunit doc contains Show docs for 'contains' assertions
86+
bashunit init Initialize test directory
8787
8888
More info: https://bashunit.typeddevs.com/command-line
8989
EOF
@@ -92,57 +92,57 @@ EOF
9292
function bashunit::console_header::print_test_help() {
9393
cat <<EOF
9494
Usage: bashunit test [path] [options]
95-
bashunit [path] [options]
95+
bashunit [path] [options]
9696
9797
Run test files. If no path is provided, searches for tests in BASHUNIT_DEFAULT_PATH.
9898
9999
Arguments:
100-
path File or directory containing tests
101-
- Directories: runs all '*test.sh' files
102-
- Wildcards: supported to match multiple files
100+
path File or directory containing tests
101+
- Directories: runs all '*test.sh' files
102+
- Wildcards: supported to match multiple files
103103
104104
Options:
105-
-a, --assert <fn> <args> Run a standalone assert function (deprecated: use 'bashunit assert')
106-
-e, --env, --boot <file> Load a custom env/bootstrap file (supports args)
107-
-f, --filter <name> Only run tests matching the name
108-
--log-junit <file> Write JUnit XML report
109-
-p, --parallel Run tests in parallel
110-
--no-parallel Run tests sequentially
111-
-r, --report-html <file> Write HTML report
112-
-s, --simple Simple output (dots)
113-
--detailed Detailed output (default)
114-
-R, --run-all Run all assertions (don't stop on first failure)
115-
-S, --stop-on-failure Stop on first failure
116-
-vvv, --verbose Show execution details
117-
--debug [file] Enable shell debug mode
118-
--no-output Suppress all output
119-
--failures-only Only show failures (suppress passed/skipped/incomplete)
120-
--no-progress Suppress real-time progress, show only final results
121-
--show-output Show test output on failure (default: enabled)
122-
--no-output-on-failure Hide test output on failure
123-
--strict Enable strict shell mode (set -euo pipefail)
124-
--skip-env-file Skip .env loading, use shell environment only
125-
-l, --login Run tests in login shell context
126-
--no-color Disable colored output (honors NO_COLOR env var)
127-
-h, --help Show this help message
105+
-a, --assert <fn> <args> Run a standalone assert function (deprecated: use 'bashunit assert')
106+
-e, --env, --boot <file> Load a custom env/bootstrap file (supports args)
107+
-f, --filter <name> Only run tests matching the name
108+
--log-junit <file> Write JUnit XML report
109+
-p, --parallel Run tests in parallel
110+
--no-parallel Run tests sequentially
111+
-r, --report-html <file> Write HTML report
112+
-s, --simple Simple output (dots)
113+
--detailed Detailed output (default)
114+
-R, --run-all Run all assertions (don't stop on first failure)
115+
-S, --stop-on-failure Stop on first failure
116+
-vvv, --verbose Show execution details
117+
--debug [file] Enable shell debug mode
118+
--no-output Suppress all output
119+
--failures-only Only show failures (suppress passed/skipped/incomplete)
120+
--no-progress Suppress real-time progress, show only final results
121+
--show-output Show test output on failure (default: enabled)
122+
--no-output-on-failure Hide test output on failure
123+
--strict Enable strict shell mode (set -euo pipefail)
124+
--skip-env-file Skip .env loading, use shell environment only
125+
-l, --login Run tests in login shell context
126+
--no-color Disable colored output (honors NO_COLOR env var)
127+
-h, --help Show this help message
128128
129129
Coverage:
130-
--coverage Enable code coverage tracking
131-
--coverage-paths <paths> Source paths to track (default: auto-discover)
132-
--coverage-exclude <pats> Patterns to exclude (comma-separated)
133-
--coverage-report [file] Output file (default: coverage/lcov.info)
134-
--coverage-report-html [dir] HTML report (default: coverage/html)
135-
--coverage-min <pct> Fail if coverage below percentage
136-
--no-coverage-report Disable file output, console only
130+
--coverage Enable code coverage tracking
131+
--coverage-paths <paths> Source paths to track (default: auto-discover)
132+
--coverage-exclude <pats> Patterns to exclude (comma-separated)
133+
--coverage-report [file] Output file (default: coverage/lcov.info)
134+
--coverage-report-html [dir] HTML report (default: coverage/html)
135+
--coverage-min <pct> Fail if coverage below percentage
136+
--no-coverage-report Disable file output, console only
137137
138138
Examples:
139-
bashunit test tests/
140-
bashunit test tests/unit/ --parallel
141-
bashunit test --filter "user" tests/
142-
bashunit test -a equals "foo" "foo"
143-
bashunit test tests/ --coverage
144-
bashunit test tests/ --coverage --coverage-min 80
145-
bashunit test tests/ --coverage-report-html
139+
bashunit test tests/
140+
bashunit test tests/unit/ --parallel
141+
bashunit test --filter "user" tests/
142+
bashunit test -a equals "foo" "foo"
143+
bashunit test tests/ --coverage
144+
bashunit test tests/ --coverage --coverage-min 80
145+
bashunit test tests/ --coverage-report-html
146146
EOF
147147
}
148148

@@ -153,23 +153,23 @@ Usage: bashunit bench [path] [options]
153153
Run benchmark files. Searches for '*bench.sh' files.
154154
155155
Arguments:
156-
path File or directory containing benchmarks
156+
path File or directory containing benchmarks
157157
158158
Options:
159-
-e, --env, --boot <file> Load a custom env/bootstrap file (supports args)
160-
-f, --filter <name> Only run benchmarks matching the name
161-
-s, --simple Simple output
162-
--detailed Detailed output (default)
163-
-vvv, --verbose Show execution details
164-
--skip-env-file Skip .env loading, use shell environment only
165-
-l, --login Run in login shell context
166-
--no-color Disable colored output (honors NO_COLOR env var)
167-
-h, --help Show this help message
159+
-e, --env, --boot <file> Load a custom env/bootstrap file (supports args)
160+
-f, --filter <name> Only run benchmarks matching the name
161+
-s, --simple Simple output
162+
--detailed Detailed output (default)
163+
-vvv, --verbose Show execution details
164+
--skip-env-file Skip .env loading, use shell environment only
165+
-l, --login Run in login shell context
166+
--no-color Disable colored output (honors NO_COLOR env var)
167+
-h, --help Show this help message
168168
169169
Examples:
170-
bashunit bench
171-
bashunit bench benchmarks/
172-
bashunit bench --filter "parse"
170+
bashunit bench
171+
bashunit bench benchmarks/
172+
bashunit bench --filter "parse"
173173
EOF
174174
}
175175

@@ -196,15 +196,15 @@ Usage: bashunit init [directory]
196196
Initialize a new test directory with sample files.
197197
198198
Arguments:
199-
directory Target directory (default: tests)
199+
directory Target directory (default: tests)
200200
201201
Creates:
202-
- bootstrap.sh Setup file for test configuration
203-
- example_test.sh Sample test file to get started
202+
- bootstrap.sh Setup file for test configuration
203+
- example_test.sh Sample test file to get started
204204
205205
Examples:
206-
bashunit init Create tests/ directory
207-
bashunit init spec Create spec/ directory
206+
bashunit init Create tests/ directory
207+
bashunit init spec Create spec/ directory
208208
EOF
209209
}
210210

@@ -215,16 +215,16 @@ Usage: bashunit learn
215215
Start the interactive learning tutorial.
216216
217217
The tutorial includes 10 progressive lessons:
218-
1. Basics - Your First Test
219-
2. Assertions - Testing Different Conditions
220-
3. Setup & Teardown - Managing Test Lifecycle
221-
4. Testing Functions - Unit Testing Patterns
222-
5. Testing Scripts - Integration Testing
223-
6. Mocking - Test Doubles and Mocks
224-
7. Spies - Verifying Function Calls
225-
8. Data Providers - Parameterized Tests
226-
9. Exit Codes - Testing Success and Failure
227-
10. Complete Challenge - Real World Scenario
218+
1. Basics - Your First Test
219+
2. Assertions - Testing Different Conditions
220+
3. Setup & Teardown - Managing Test Lifecycle
221+
4. Testing Functions - Unit Testing Patterns
222+
5. Testing Scripts - Integration Testing
223+
6. Mocking - Test Doubles and Mocks
224+
7. Spies - Verifying Function Calls
225+
8. Data Providers - Parameterized Tests
226+
9. Exit Codes - Testing Success and Failure
227+
10. Complete Challenge - Real World Scenario
228228
229229
Your progress is saved automatically.
230230
EOF
@@ -243,28 +243,28 @@ EOF
243243
function bashunit::console_header::print_assert_help() {
244244
cat <<EOF
245245
Usage: bashunit assert <function> [args...]
246-
bashunit assert "<command>" <assertion1> <arg1> [<assertion2> <arg2>...]
246+
bashunit assert "<command>" <assertion1> <arg1> [<assertion2> <arg2>...]
247247
248248
Run standalone assertion(s) without creating a test file.
249249
250250
Single assertion:
251-
bashunit assert equals "foo" "foo"
252-
bashunit assert same "1" "1"
253-
bashunit assert contains "world" "hello world"
254-
bashunit assert exit_code 0 "echo 'success'"
251+
bashunit assert equals "foo" "foo"
252+
bashunit assert same "1" "1"
253+
bashunit assert contains "world" "hello world"
254+
bashunit assert exit_code 0 "echo 'success'"
255255
256256
Multiple assertions on command output:
257-
bashunit assert "echo 'error' && exit 1" exit_code "1" contains "error"
258-
bashunit assert "./my_script.sh" exit_code "0" contains "success" not_contains "error"
257+
bashunit assert "echo 'error' && exit 1" exit_code "1" contains "error"
258+
bashunit assert "./my_script.sh" exit_code "0" contains "success" not_contains "error"
259259
260260
Arguments:
261-
function Assertion function name (with or without 'assert_' prefix)
262-
command Command to execute (for multi-assertion mode)
263-
assertion Assertion name (exit_code, contains, equals, etc.)
264-
arg Expected value for the assertion
261+
function Assertion function name (with or without 'assert_' prefix)
262+
command Command to execute (for multi-assertion mode)
263+
assertion Assertion name (exit_code, contains, equals, etc.)
264+
arg Expected value for the assertion
265265
266266
Note: You can also use 'bashunit test --assert <fn> <args>' (deprecated).
267-
The 'bashunit assert' subcommand is the recommended approach.
267+
The 'bashunit assert' subcommand is the recommended approach.
268268
269269
More info: https://bashunit.typeddevs.com/standalone
270270
EOF

src/coverage.sh

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -358,22 +358,27 @@ function bashunit::coverage::is_executable_line() {
358358
[[ -z "${line// /}" ]] && return 1
359359

360360
# Skip comment-only lines (including shebang)
361-
bashunit::regex_match "$line" '^[[:space:]]*#' && return 1
361+
local _re='^[[:space:]]*#'
362+
[[ "$line" =~ $_re ]] && return 1
362363

363364
# Skip function declaration lines (but not single-line functions with body)
364-
bashunit::regex_match "$line" "$_BASHUNIT_COVERAGE_FUNC_PATTERN" && return 1
365+
[[ "$line" =~ $_BASHUNIT_COVERAGE_FUNC_PATTERN ]] && return 1
365366

366367
# Skip lines with only braces
367-
bashunit::regex_match "$line" '^[[:space:]]*[\{\}][[:space:]]*$' && return 1
368+
_re='^[[:space:]]*[\{\}][[:space:]]*$'
369+
[[ "$line" =~ $_re ]] && return 1
368370

369371
# Skip control flow keywords (then, else, fi, do, done, esac, in, ;;, ;&, ;;&)
370-
bashunit::regex_match "$line" '^[[:space:]]*(then|else|fi|do|done|esac|in|;;|;;&|;&)[[:space:]]*(#.*)?$' && return 1
372+
_re='^[[:space:]]*(then|else|fi|do|done|esac|in|;;|;;&|;&)[[:space:]]*(#.*)?$'
373+
[[ "$line" =~ $_re ]] && return 1
371374

372375
# Skip case patterns like "--option)" or "*)"
373-
bashunit::regex_match "$line" '^[[:space:]]*[^\)]+\)[[:space:]]*$' && return 1
376+
_re='^[[:space:]]*[^\)]+\)[[:space:]]*$'
377+
[[ "$line" =~ $_re ]] && return 1
374378

375379
# Skip standalone ) for arrays/subshells
376-
bashunit::regex_match "$line" '^[[:space:]]*\)[[:space:]]*(#.*)?$' && return 1
380+
_re='^[[:space:]]*\)[[:space:]]*(#.*)?$'
381+
[[ "$line" =~ $_re ]] && return 1
377382

378383
return 0
379384
}
@@ -494,10 +499,14 @@ function bashunit::coverage::extract_functions() {
494499
local fn_name=""
495500

496501
# Match: function name() or function name {
497-
if bashunit::regex_match "$line" '^[[:space:]]*(function[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_:]*)[[:space:]]*\(\)[[:space:]]*\{?[[:space:]]*(#.*)?$'; then
498-
fn_name="${BASH_REMATCH[2]}"
499-
elif bashunit::regex_match "$line" '^[[:space:]]*(function[[:space:]]+)([a-zA-Z_][a-zA-Z0-9_:]*)[[:space:]]*\{[[:space:]]*(#.*)?$'; then
502+
local _re='^[[:space:]]*(function[[:space:]]+)?([a-zA-Z_][a-zA-Z0-9_:]*)[[:space:]]*\(\)[[:space:]]*\{?[[:space:]]*(#.*)?$'
503+
if [[ "$line" =~ $_re ]]; then
500504
fn_name="${BASH_REMATCH[2]}"
505+
else
506+
_re='^[[:space:]]*(function[[:space:]]+)([a-zA-Z_][a-zA-Z0-9_:]*)[[:space:]]*\{[[:space:]]*(#.*)?$'
507+
if [[ "$line" =~ $_re ]]; then
508+
fn_name="${BASH_REMATCH[2]}"
509+
fi
501510
fi
502511

503512
if [[ -n "$fn_name" ]]; then
@@ -512,7 +521,8 @@ function bashunit::coverage::extract_functions() {
512521
brace_count=$((brace_count + ${#open_braces} - ${#close_braces}))
513522

514523
# Single-line function
515-
if [[ $brace_count -eq 0 ]] && bashunit::regex_match "$line" '\{' && bashunit::regex_match "$line" '\}'; then
524+
local _re_ob='\{' _re_cb='\}'
525+
if [[ $brace_count -eq 0 ]] && [[ "$line" =~ $_re_ob ]] && [[ "$line" =~ $_re_cb ]]; then
516526
echo "${current_fn}:${fn_start}:${lineno}"
517527
in_function=0
518528
current_fn=""

0 commit comments

Comments
 (0)