Part of #761.
Problem
When --tag/--exclude-tag is used, bashunit::helper::get_tags_for_function (src/helpers.sh:670) runs per test function, and twice per function: once during early load filtering (src/runner.sh:411) and again in call_test_functions (src/runner.sh:733).
Each call forks heavily: grep -n | head to locate the function, then a backward line-by-line walk where every line forks sed -n "${N}p" plus up to three "$GREP" -cE probes (src/helpers.sh:~690-715). That is O(comment-lines) forks per function, times two.
Measured (macOS bash 3.2, commit 1ae3e82): 100 tagged tests with --tag foo run in ~2.10s vs ~0.68s untagged baseline — ~14ms extra per test, and it grows with the size of the comment block above each function.
Task
Mirror the existing single-pass provider map (bashunit::helper::build_provider_map, src/helpers.sh:327, added in #763/PR #767 — use it as the template):
- Add
bashunit::helper::build_tags_map "$script": one awk pass per file emitting <fn>\t<tag1,tag2,...> records into two parallel indexed arrays (Bash 3.0: no associative arrays), cached by script path so both call sites (src/runner.sh:411 and src/runner.sh:733) share one scan.
- Add a pure-bash lookup
bashunit::helper::tags_for_function writing to a _BASHUNIT_TAGS_OUT slot, and convert both call sites.
- The awk pass must reproduce the current walk semantics exactly (see
src/helpers.sh:670-720): collect # @tag <name> comment lines above the function definition, continue walking up through other comment lines, stop at the first blank or non-comment line; function defined as function test_x or test_x(). Multiple @tag lines accumulate comma-separated in the same order the current code produces.
- Keep
get_tags_for_function as a wrapper (or delete it if nothing else calls it — grep first).
Tests first (TDD)
tests/functional already covers tag filtering — run it before and after. Add unit tests for the new map builder: multiple tags, tag after a non-tag comment, blank line breaking the association, both function-definition styles, two files back to back (cache invalidation by path).
Constraints
- Bash 3.0+ only; no associative arrays — use the parallel-array pattern from
build_provider_map.
--tag/--exclude-tag semantics and output must be unchanged.
Acceptance criteria
Line references valid at commit 1ae3e82.
Part of #761.
Problem
When
--tag/--exclude-tagis used,bashunit::helper::get_tags_for_function(src/helpers.sh:670) runs per test function, and twice per function: once during early load filtering (src/runner.sh:411) and again incall_test_functions(src/runner.sh:733).Each call forks heavily:
grep -n | headto locate the function, then a backward line-by-line walk where every line forkssed -n "${N}p"plus up to three"$GREP" -cEprobes (src/helpers.sh:~690-715). That is O(comment-lines) forks per function, times two.Measured (macOS bash 3.2, commit 1ae3e82): 100 tagged tests with
--tag foorun in ~2.10s vs ~0.68s untagged baseline — ~14ms extra per test, and it grows with the size of the comment block above each function.Task
Mirror the existing single-pass provider map (
bashunit::helper::build_provider_map,src/helpers.sh:327, added in #763/PR #767 — use it as the template):bashunit::helper::build_tags_map "$script": oneawkpass per file emitting<fn>\t<tag1,tag2,...>records into two parallel indexed arrays (Bash 3.0: no associative arrays), cached by script path so both call sites (src/runner.sh:411andsrc/runner.sh:733) share one scan.bashunit::helper::tags_for_functionwriting to a_BASHUNIT_TAGS_OUTslot, and convert both call sites.src/helpers.sh:670-720): collect# @tag <name>comment lines above the function definition, continue walking up through other comment lines, stop at the first blank or non-comment line; function defined asfunction test_xortest_x(). Multiple@taglines accumulate comma-separated in the same order the current code produces.get_tags_for_functionas a wrapper (or delete it if nothing else calls it — grep first).Tests first (TDD)
tests/functionalalready covers tag filtering — run it before and after. Add unit tests for the new map builder: multiple tags, tag after a non-tag comment, blank line breaking the association, both function-definition styles, two files back to back (cache invalidation by path).Constraints
build_provider_map.--tag/--exclude-tagsemantics and output must be unchanged.Acceptance criteria
./bashunit tests/and./bashunit --parallel tests/pass.make sa,make lintpass;shfmt -w .produces no diff.--tagin the PR (baseline above).Line references valid at commit 1ae3e82.