Skip to content

A snapshot of a value that is exactly -n, -e or -E is recorded empty #1402

Closed

Description

@Chemaclass

Problem

A snapshot whose value is exactly -n, -e, -E or a combination of those letters is recorded as an empty file, so the next run fails against it.

Reproduced on main 776997e9, macOS arm64, Bash 3.2.57 and Bash 5.3:

function test_snapshot_dash_n() {
  assert_match_snapshot "-n"
}

First run: ✎ Snapshot: Snapshot dash n, and the recorded .snapshot file is 0 bytes. Second run: ✗ Failed: Snapshot dash n. --snapshot-update writes the same empty file.

Where

src/assert/snapshot.sh:405 (bashunit::snapshot::initialize) and :434 (bashunit::snapshot::update) write the value with echo "$content". Bash's echo consumes a first argument made only of -n, -e or -E flags.

Why it matters

Snapshots capture command output verbatim; a command that prints a flag name is not unusual. The failure appears one run later with no hint about the cause, and the file looks like an empty snapshot was intended.

Suggested change

Write with printf '%s\n' "$content" in both places. The comparison side already strips trailing newlines, so existing snapshot files keep matching.

Acceptance criteria

  • assert_match_snapshot "-n" records -n and passes on the second run; the same for -e and -E.
  • Existing snapshot files are unaffected.
  • A test covers it and fails on the current code.

Proposed fix

Replace echo "$content" >"$path" in bashunit::snapshot::initialize (src/assert/snapshot.sh:405) and echo "$actual" >"$path" in bashunit::snapshot::update (:434) with printf '%s\n' "$content" >"$path" and printf '%s\n' "$actual" >"$path". Public behaviour that must not change: the on-disk format (value plus one trailing newline), which compare reads with $(<file) and already strips. Bash 3.0: printf '%s\n' is a builtin on every version. No docs change. CHANGELOG: one line under Unreleased, Fixed.

Agent brief

  • Branch: fix/1402-snapshot-dash-value from fresh origin/main. Commit: fix(assert): record a snapshot whose value is an echo flag, body Closes #1402.
  • Files: src/assert/snapshot.sh; test in tests/unit/assert/snapshot_test.sh, next to test_creates_a_snapshot (line 13), copying its temp-dir snapshot path shape.
  • RED first:
function test_creates_a_snapshot_whose_value_is_an_echo_flag() {
  local snapshot_path="$(bashunit::temp_dir)/snapshot_test_sh.test_creates_a_snapshot_whose_value_is_an_echo_flag.snapshot"
  assert_match_snapshot "-n" "$snapshot_path"
  assert_same "-n" "$(cat "$snapshot_path")"
}

Run only that file: ./bashunit tests/unit/assert/snapshot_test.sh.

  • Non-goals: the placeholder matcher, --snapshot-prune, and the comparison path; assert_files_equals passes when a file does not exist #1397 is separate.
  • Gate, once, when the change is complete: ./bashunit tests/, ./bashunit --parallel --simple --strict tests/, make sa, make lint. make lint is the formatting authority; never shfmt -w; 2-space indent.
  • Done when: every acceptance box is checked, the gate is green, CHANGELOG is updated, and a PR is open with the pr skill.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

agent-readyScoped, reproduced and testable; an agent can take it without more questionsarea:assertCode under src or scripts for assertbugSomething isn't workinggood first issueGood for newcomersp3Edge case, message or docs mismatch

Type

No type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions