From f121674efcbd20e4fd341495c9cd4fc5ef75a15a Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Wed, 8 May 2024 01:05:06 -0700 Subject: [PATCH 01/23] Adding `assert_equals_golden` and `assert_output_equals_golden` Adding support for "golden files". Golden files are (often text) files that are checked into a repo and are used in testing for asserting strings against their content. They have a number of useful properties that make them a great alternative to single (possibly repetitive) assertions in files. Some benefits include: * WYSIWYG plaintext output assertions (separating asserted output from test case logic). * Test failure output that is searchable (asserted output is checked into repo as files). * Clear file diffs of test assertions during merge / code review. * Terse assertions in test cases (single assert instead of many verbose `assert_line` and `refute_line` for every line of output). * Reusable golden files (declared once, used for many test cases). * Clear intention (same exact expected output) when asserted against same goldens in multiple test cases. * Can be clearly diff'd across multiple lines in failure message(s). * Easily updated. This PR adds support to bats for golden files with the `assert_equals_golden` and `assert_output_equals_golden` test helper functions. `assert_equals_golden` takes 2 arguments, and , to assert is the same as the contents in . `assert_output_equals_golden` takes 1 argument, , to assert `output` is the same as the contents in . These functions support a number of features, including `--regexp` and automatic updating of golden files (via setting the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable). Golden file assertions will properly account for empty lines or trailing newlines (e.g. when asserting against output obtained by `run --keep-empty-lines`). This PR adds `assert_equals_golden.bats` which contains test cases for the newly added functionality. Note that the output of these functions (that is asserted on in tests) has incorrect "lines" count. This is due to an incompatibility between `run --keep-empty-lines` and how various bats-support helper functions work. See https://github.com/bats-core/bats-support/issues/11. --- load.bash | 1 + src/assert_equals_golden.bash | 553 ++++++ test/assert_equals_golden.bats | 3035 ++++++++++++++++++++++++++++++++ 3 files changed, 3589 insertions(+) create mode 100644 src/assert_equals_golden.bash create mode 100644 test/assert_equals_golden.bats diff --git a/load.bash b/load.bash index c67d9e8..a89df36 100644 --- a/load.bash +++ b/load.bash @@ -31,3 +31,4 @@ source "$(dirname "${BASH_SOURCE[0]}")/src/assert_line.bash" source "$(dirname "${BASH_SOURCE[0]}")/src/refute_line.bash" source "$(dirname "${BASH_SOURCE[0]}")/src/assert_regex.bash" source "$(dirname "${BASH_SOURCE[0]}")/src/refute_regex.bash" +source "$(dirname "${BASH_SOURCE[0]}")/src/assert_equals_golden.bash" diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash new file mode 100644 index 0000000..266608f --- /dev/null +++ b/src/assert_equals_golden.bash @@ -0,0 +1,553 @@ +# assert_equals_golden +# ============ +# +# Summary: Fail if the actual and golden file contents are not equal. +# +# Usage: assert_equals_golden [-e | --regexp | -d | --diff] [--stdin] [--allow-empty] [--] [- | ] +# +# Options: +# -e, --regexp Treat file contents of as an multiline extended regular expression. +# -d, --diff Displays `diff` between and golden contents instead of full strings. +# -, --stdin Read value from STDIN. Do not pass if set. +# The value being compared. May be `-` to use STDIN. Omit if `--stdin` is passed. +# A file that has contents which must match against . +# +# ```bash +# @test 'assert_equals_golden()' { +# assert_equals_golden 'have' 'some/path/golden_file.txt' +# } +# ``` +# +# IO: +# STDIN - actual value, if `--stdin` or `-` is supplied. +# STDERR - expected and actual values, or their diff, on failure +# Globals: +# BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - The golden file's contents will be updated to if it did not match. +# Returns: +# 0 - if is equal to file contents in +# 1 - otherwise +# +# Golden files hold the entirety of the expected output. +# Contents will properly/consistently match to empty lines / trailing new lines (when used with `run --keep-empty-lines` or similar). +# Golden files are, by default, not allowed to be empty. This is to catch common authoring errors. If intented, this can be overridden with `--allow-empty`. +# +# Golden files have a number of benefits when used for asserting against output, including: +# * WYSIWYG plaintext output assertions (separating asserted output from test case logic). +# * Test failure output that is searchable (asserted output is checked into repo as files). +# * Clear file diffs of test assertions during merge / code review. +# * Terse assertions in test cases (single assert instead of many verbose `assert_line` and `refute_line` for every line of output). +# * Reusable golden files (declared once, used for many test cases). +# * Clear intention (same exact expected output) when asserted against same goldens in multiple test cases. +# * Can be clearly diff'd across multiple lines in failure message(s). +# * Easily updated. +# +# The assertion string target, , can instead be supplied via STDIN. +# If `--stdin` is supplied, or if `-` is given as , STDIN will be read for the checked string. +# When suppliying `--stdin`, only 1 argument () should be supplied. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set, failed assertions will result in the golden file being updated. +# The golden file contents is updated to be able to pass upon subsequent runs. +# All tests that update goldens still fails (enforcing that all passing tests are achieved with pre-existing correct golden). +# This is set via an environment variable to allow mass golden file updates across many tests. +# +# ## Literal matching +# +# On failure, the expected and actual values are displayed. Line count is always displayed. +# +# ``` +# -- value does not match golden -- +# golden contents (1 lines): +# want +# actual output (1 lines): +# have +# -- +# ``` +# +# If `--diff` is given, the output is changed to `diff` between and the golden file contents. +# +# ``` +# -- value does not match golden -- +# 1c1 +# < have +# --- +# > want +# -- +# ``` +# +# ## Regular expression matching +# +# If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. +# This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. +# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. +# Each line in the existing golden will attempt to match to the line of , preferring longer lines. +# If no pre-existing golden line matches, that line will be updated with the exact line string from . +# Not all lines can be reused (e.g. multiline expressions), but the golden file can be manually changed after automatic update. +# +# `--diff` is not supported with `--regexp`. +# +assert_equals_golden() { + local -i is_mode_regexp=0 + local -i show_diff=0 + local -i use_stdin_set_by_opt=0 + local -i use_stdin_set_by_arg=0 + local -i allow_empty=0 + + while (( $# > 0 )); do + case "$1" in + -e|--regexp) + is_mode_regexp=1 + shift + ;; + -d|--diff) + show_diff=1; + shift + ;; + --stdin) + use_stdin_set_by_opt=1; + shift + ;; + --allow-empty) + allow_empty=1 + shift + ;; + --) + shift + break + ;; + -) + use_stdin_set_by_arg=1 + break + ;; + --*=|-*) + echo "Unsupported flag '$1'." \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + ;; + *) + break + ;; + esac + done + + if (( use_stdin_set_by_opt )) && [ $# -ne 1 ]; then + echo "Incorrect number of arguments: $#. Using stdin, expecting 1 argument." \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + elif (( ! use_stdin_set_by_opt )) && [ $# -ne 2 ] ; then + echo "Incorrect number of arguments: $#. Expected 2 arguments." \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + + if (( show_diff )) && (( is_mode_regexp )); then + echo "\`--diff' not supported with \`--regexp'" \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + + local value="$1" + local golden_file_path="${2-}" + if (( use_stdin_set_by_opt )) || (( use_stdin_set_by_arg )); then + value="$(cat - && printf '.')" + value="${value%.}" + fi + if (( use_stdin_set_by_opt )); then + golden_file_path="$1" + fi + + local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" + + if [ -z "$golden_file_path" ]; then + echo "Golden file path was not given or it was empty." \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + if [ ! -e "$golden_file_path" ]; then + echo "Golden file was not found. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + + local golden_file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" + if (( $? != 0 )); then + echo "Failed to read golden file. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + golden_file_contents="${golden_file_contents%.}" + if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then + echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + fi + + local -i assert_failed=0 + if (( is_mode_regexp )); then + if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then + echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ + | batslib_decorate 'ERROR: assert_equals_golden' \ + | fail + return $? + elif ! [[ "$value" =~ ^${golden_file_contents}$ ]]; then + assert_failed=1 + fi + elif [[ "$value" != "$golden_file_contents" ]]; then + assert_failed=1 + fi + + if (( assert_failed )); then + if ! (( update_goldens_on_failure )); then + if (( show_diff )); then + diff <(echo "$output") <(echo "$golden_file_contents") \ + | batslib_decorate 'value does not match golden' \ + | fail + elif (( is_mode_regexp )); then + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" \ + | batslib_decorate 'value does not match regexp golden' \ + | fail + else + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" \ + | batslib_decorate 'value does not match golden' \ + | fail + fi + else + if ! (( is_mode_regexp )); then + # Non-regex golden update is straight forward. + printf '%s' "$value" 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_equals_golden' \ + | fail + return $? + fi + else + # To do a best-approximation for regex goldens, + # try and use existing lines as a library for updated lines (preferring longer lines). + # This is done line by line on the asserted value. + # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). + # Any line guess which is not preferred can be manually corrected/updated by the author. + local -a output_lines=() + local -a sorted_golden_lines=() + local temp= + while IFS='' read -r temp; do + output_lines+=("$temp") + done < <(printf '%s' "$value" ; printf '\n') + while IFS='' read -r temp; do + sorted_golden_lines+=("$temp") + done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') + # First, clear out the golden file's contents (so new data can just be appended below). + : 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_equals_golden' \ + | fail + return $? + fi + # Go line by line over the output, looking for the best suggested replacement. + local best_guess_for_line= + for line_in_output in "${output_lines[@]}"; do + # Default the output line itself as the best guess for the new golden. + # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + for line_in_golden in "${sorted_golden_lines[@]}"; do + if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then + # If there's a line from the previous golden output that matches, use that is the best guess instead. + # No need to escape special characters, as `line_in_golden` is already in proper form. + best_guess_for_line="$line_in_golden" + break + fi + done + if [ -s "$golden_file_path" ]; then + printf '\n' >> "$golden_file_path" + fi + printf '%s' "$best_guess_for_line" >> "$golden_file_path" + done + fi + echo "Golden file updated after mismatch." \ + | batslib_decorate 'FAIL: assert_equals_golden' \ + | fail + return $? + fi + fi +} + +# assert_output_equals_golden +# ============ +# +# Summary: Fail if the `output` environment variable and golden file contents are not equal. +# +# Usage: assert_output_equals_golden [-e | --regexp | -d | --diff] [--allow-empty] [--] +# +# Options: +# -e, --regexp Treat file contents of as an multiline extended regular expression. +# -d, --diff Displays `diff` between `output` and golden contents instead of full strings. +# A file that has contents which must match against `output`. +# +# ```bash +# @test 'assert_output_equals_golden()' { +# run echo 'have' +# assert_output_equals_golden 'some/path/golden_file.txt' +# } +# ``` +# +# IO: +# STDERR - expected and actual outputs, or their diff, on failure +# Globals: +# output - the actual output asserted against golden file contents. +# BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - The golden file's contents will be updated to `output` if it did not match. +# Returns: +# 0 - if `output` is equal to file contents in +# 1 - otherwise +# +# Golden files hold the entirety of the expected output. +# Contents will properly/consistently match to empty lines / trailing new lines (when used with `run --keep-empty-lines` or similar). +# Golden files are, by default, not allowed to be empty. This is to catch common authoring errors. If intented, this can be overridden with `--allow-empty`. +# +# Golden files have a number of benefits when used for asserting against output, including: +# * WYSIWYG plaintext output assertions (separating asserted output from test case logic). +# * Test failure output that is searchable (asserted output is checked into repo as files). +# * Clear file diffs of test assertions during merge / code review. +# * Terse assertions in test cases (single assert instead of many verbose `assert_line` and `refute_line` for every line of output). +# * Reusable golden files (declared once, used for many test cases). +# * Clear intention (same exact expected output) when asserted against same goldens in multiple test cases. +# * Can be clearly diff'd across multiple lines in failure message(s). +# * Easily updated. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set, failed assertions will result in the golden file being updated. +# The golden file contents is updated to be able to pass upon subsequent runs. +# All tests that update goldens still fails (enforcing that all passing tests are achieved with pre-existing correct golden). +# This is set via an environment variable to allow mass golden file updates across many tests. +# +# ## Literal matching +# +# On failure, the expected and actual output are displayed. Line count is always displayed. +# +# ``` +# -- output does not match golden -- +# golden contents (1 lines): +# want +# actual output (1 lines): +# have +# -- +# ``` +# +# If `--diff` is given, the output is changed to `diff` between `output` and the golden file contents. +# +# ``` +# -- output does not match golden -- +# 1c1 +# < have +# --- +# > want +# -- +# ``` +# +# ## Regular expression matching +# +# If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. +# This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. +# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. +# Each line in the existing golden will attempt to match to the line of , preferring longer lines. +# If no pre-existing golden line matches, that line will be updated with the exact line string from . +# Not all lines can be reused (e.g. multiline expressions), but the golden file can be manually changed after automatic update. +# +# `--diff` is not supported with `--regexp`. +# +assert_output_equals_golden() { + local -i is_mode_regexp=0 + local -i show_diff=0 + local -i allow_empty=0 + : "${output?}" + + while (( "$#" )); do + case "$1" in + -e|--regexp) + is_mode_regexp=1 + shift + ;; + -d|--diff) + show_diff=1; + shift + ;; + --allow-empty) + allow_empty=1 + shift + ;; + --) + shift + break + ;; + --*=|-*) + echo "Unsupported flag '$1'." \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + ;; + *) + break + ;; + esac + done + + if [ $# -ne 1 ]; then + echo "Incorrect number of arguments: $#. Expected 1 argument." \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + + if (( show_diff )) && (( is_mode_regexp )); then + echo "\`--diff' not supported with \`--regexp'" \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + + local -r golden_file_path="${1-}" + local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:-0}" + + if [ -z "$golden_file_path" ]; then + echo "Golden file path was not given or it was empty." \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + if [ ! -e "$golden_file_path" ]; then + echo "Golden file was not found. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + + local golden_file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" + if [ $? -ne 0 ]; then + echo "Failed to read golden file. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + golden_file_contents="${golden_file_contents%.}" + if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then + echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + fi + + local -i assert_failed=0 + if (( is_mode_regexp )); then + if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then + echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ + | batslib_decorate 'ERROR: assert_output_equals_golden' \ + | fail + return $? + elif ! [[ "$output" =~ ^${golden_file_contents}$ ]]; then + assert_failed=1 + fi + elif [[ "$output" != "$golden_file_contents" ]]; then + assert_failed=1 + fi + + if (( assert_failed )); then + if ! (( update_goldens_on_failure )); then + if (( show_diff )); then + diff <(echo "$output") <(echo "$golden_file_contents") \ + | batslib_decorate 'output does not match golden' \ + | fail + elif (( is_mode_regexp )); then + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" \ + | batslib_decorate 'output does not match regexp golden' \ + | fail + else + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" \ + | batslib_decorate 'output does not match golden' \ + | fail + fi + else + if ! (( is_mode_regexp )); then + # Non-regex golden update is straight forward. + printf '%s' "$output" 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_output_equals_golden' \ + | fail + return $? + fi + else + # To do a best-approximation for regex goldens, + # try and use existing lines as a library for updated lines (preferring longer lines). + # This is done line by line on the output. + # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). + # Any line guess which is not preferred can be manually corrected/updated by the author. + local -a output_lines=() + local -a sorted_golden_lines=() + local temp= + while IFS='' read -r temp; do + output_lines+=("$temp") + done < <(printf '%s' "$output" ; printf '\n') + while IFS='' read -r temp; do + sorted_golden_lines+=("$temp") + done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') + # First, clear out the golden file's contents (so new data can just be appended below). + : 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_output_equals_golden' \ + | fail + return $? + fi + # Go line by line over the output, looking for the best suggested replacement. + local best_guess_for_line= + for line_in_output in "${output_lines[@]}"; do + # Default the output line itself as the best guess for the new golden. + # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + for line_in_golden in "${sorted_golden_lines[@]}"; do + if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then + # If there's a line from the previous golden output that matches, use that is the best guess instead. + # No need to escape special characters, as `line_in_golden` is already in proper form. + best_guess_for_line="$line_in_golden" + break + fi + done + if [ -s "$golden_file_path" ]; then + printf '\n' >> "$golden_file_path" + fi + printf '%s' "$best_guess_for_line" >> "$golden_file_path" + done + fi + echo "Golden file updated after mismatch." \ + | batslib_decorate 'FAIL: assert_output_equals_golden' \ + | fail + return $? + fi + fi +} diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats new file mode 100644 index 0000000..994d874 --- /dev/null +++ b/test/assert_equals_golden.bats @@ -0,0 +1,3035 @@ +#!/usr/bin/env bats + +load test_helper + +bats_require_minimum_version 1.5.0 + +# +# assert_equals_golden +# Literal matching +# + +@test "assert_equals_golden: succeeds if output and golden match" { + run printf 'a' + run assert_equals_golden "$output" <(printf 'a') + assert_test_pass +} + +@test "assert_equals_golden: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_equals_golden "$output" <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_equals_golden: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden "$output" <(printf 'a\n') + assert_test_pass +} + +@test "assert_equals_golden: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden "$output" <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_equals_golden: fails if output and golden do not match" { + run printf 'b' + run assert_equals_golden "$output" <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_equals_golden: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a + +actual output (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (3 lines): +a +b +c + +actual output (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (3 lines): +a +b +c +actual output (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden "$output" <(printf '\n') + + assert_test_pass +} + +@test "assert_equals_golden: fails if output is and golden are empty" { + run : + run assert_equals_golden "$output" <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_equals_golden: succeeds if output is and golden are empty when allowed" { + run : + run assert_equals_golden --allow-empty "$output" <(:) + + assert_test_pass +} + +@test "assert_equals_golden: succeeds if output is and golden are empty when allowed - kept empty lines" { + run --keep-empty-lines : + run assert_equals_golden --allow-empty "$output" <(:) + + assert_test_pass +} + +@test "assert_equals_golden: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --allow-empty "$output" <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if output is empty with newline golden" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails if output is empty with newline golden - kept empty lines" { + run --keep-empty-lines : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden "$output" <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden: fails with too few parameters" { + run assert_equals_golden + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 0. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden: fails with too many parameters" { + run assert_equals_golden a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 3. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden: fails with empty golden file path" { + run assert_equals_golden 'abc' '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_equals_golden: fails with nonexistent golden file" { + run assert_equals_golden 'abc' some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_equals_golden: fails with non-openable golden file" { + run assert_equals_golden 'abc' . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_equals_golden: '--' stops parsing options" { + run assert_equals_golden -- '--diff' <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_equals_golden: fails due to literal (non-wildcard) matching by default" { + run printf 'b' + run assert_equals_golden "$output" <(printf '*') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +* +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_equals_golden: fails due to literal (non-regex) matching by default" { + run printf 'b' + run assert_equals_golden "$output" <(printf '.*') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +.* +actual output (1 lines): +b +-- +ERR_MSG +} + +# +# assert_equals_golden +# Literal matching with stdin +# + +@test "assert_equals_golden --stdin: succeeds if output and golden match" { + run printf 'a' + run assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if output and golden match with '-' arg" { + run printf 'a' + run assert_equals_golden - <(printf 'a') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if multiline output and golden match with '-' arg" { + run printf 'a\nb\nc' + run assert_equals_golden - <(printf 'a\nb\nc') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden --stdin <(printf 'a\n') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if output and golden match and contain trailing newline with '-' arg" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden - <(printf 'a\n') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if multiline output and golden match and contain trailing newline with '-' arg" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden - <(printf 'a\nb\nc\n') < <(printf "$output") + assert_test_pass +} + +@test "assert_equals_golden --stdin: fails if output and golden do not match" { + run printf 'b' + run assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_equals_golden --stdin: fails if output and golden do not match with '-' arg" { + run printf 'b' + run assert_equals_golden - <(printf 'a') < <(printf "$output") + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_equals_golden --stdin: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\n') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a + +actual output (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (3 lines): +a +b +c + +actual output (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (3 lines): +a +b +c +actual output (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + + assert_test_pass +} + +@test "assert_equals_golden --stdin: fails if output is and golden are empty" { + run : + run assert_equals_golden --stdin <(:) < <(printf "$output") + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed" { + run : + run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed with '-' arg" { + run : + run assert_equals_golden --allow-empty - <(:) < <(printf "$output") + + assert_test_pass +} + +@test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed - kept empty lines" { + run --keep-empty-lines : + run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + + assert_test_pass +} + +@test "assert_equals_golden --stdin: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is newline with non-empty golden with '-' arg" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden - <(printf 'a') < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden with '-' arg" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --allow-empty - <(:) < <(printf "$output") + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is empty with newline golden" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is empty with newline golden with '-' arg" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden - <(printf '\n') < <(printf "$output") + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --stdin: fails if output is empty with newline golden - kept empty lines" { + run --keep-empty-lines : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +# +# assert_equals_golden +# Literal matching with diff output +# + +@test "assert_equals_golden --diff: succeeds if output and golden match" { + run printf 'a' + run assert_equals_golden --diff "$output" <(printf 'a') + assert_test_pass +} + +@test "assert_equals_golden --diff: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_equals_golden --diff "$output" <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_equals_golden --diff: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden --diff "$output" <(printf 'a\n') + assert_test_pass +} + +@test "assert_equals_golden --diff: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden --diff "$output" <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_equals_golden --diff: fails if output and golden do not match" { + run printf 'b' + run assert_equals_golden --diff "$output" <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +1c1 +< b +--- +> a +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + run assert_equals_golden --diff "$output" <(printf 'a\n') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + run assert_equals_golden --diff "$output" <(printf 'a\nb\nc\n') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +3a4 +> +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden --diff "$output" <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden --diff "$output" <(printf 'a\nb\nc') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +4d3 +< +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden --diff "$output" <(printf '\n') + + assert_test_pass +} + +@test "assert_equals_golden --diff: fails if output is and golden are empty" { + run : + run assert_equals_golden --diff "$output" <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: succeeds if output is and golden are empty when allowed" { + run : + run assert_equals_golden --diff --allow-empty "$output" <(:) + + assert_test_pass +} + +@test "assert_equals_golden --diff: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden --diff "$output" <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +1,2c1 +< +< +--- +> a +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden --diff --allow-empty "$output" <(:) + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails if output is empty with newline golden" { + run : + run assert_equals_golden --diff "$output" <(printf '\n') + + assert_test_fail <<'ERR_MSG' + +-- value does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails with too few parameters" { + run assert_equals_golden --diff + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 0. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails with too many parameters" { + run assert_equals_golden --diff a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 3. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails with empty golden file path" { + run assert_equals_golden --diff 'abc' '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails with nonexistent golden file" { + run assert_equals_golden --diff 'abc' some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: fails with non-openable golden file" { + run assert_equals_golden --diff 'abc' . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_equals_golden --diff: '--' stops parsing options" { + run assert_equals_golden --diff -- '--diff' <(printf '%s' '--diff') + + assert_test_pass +} + +# +# assert_equals_golden +# Regex matching +# + +@test "assert_equals_golden --regexp: succeeds if output and golden match" { + run printf 'a' + run assert_equals_golden --regexp "$output" <(printf 'a') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_equals_golden --regexp "$output" <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_equals_golden --regexp "$output" <(printf 'a\n') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_equals_golden --regexp "$output" <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_equals_golden --regexp: fails if output and golden do not match" { + run printf 'b' + run assert_equals_golden --regexp "$output" <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +a + +actual output (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (3 lines): +a +b +c + +actual output (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (3 lines): +a +b +c +actual output (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_equals_golden --regexp "$output" <(printf '\n') + + assert_test_pass +} + +@test "assert_equals_golden --regexp: fails if output is and golden are empty" { + run : + run assert_equals_golden --regexp "$output" <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: succeeds if output is and golden are empty when allowed" { + run : + run assert_equals_golden --regexp --allow-empty "$output" <(:) + + assert_test_pass +} + +@test "assert_equals_golden --regexp: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp --allow-empty "$output" <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if output is empty with newline golden" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails with too few parameters" { + run assert_equals_golden --regexp + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 0. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with too many parameters" { + run assert_equals_golden --regexp a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Incorrect number of arguments: 3. Expected 2 arguments. +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with empty golden file path" { + run assert_equals_golden --regexp 'abc' '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with nonexistent golden file" { + run assert_equals_golden --regexp 'abc' some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with non-openable golden file" { + run assert_equals_golden --regexp 'abc' . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: '--' stops parsing options" { + run assert_equals_golden --regexp -- '--diff' <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with special characters" { + run printf '[.?+' + run assert_equals_golden --regexp "$output" <(printf '\\[\\.\\?\\+') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with non-specific matching regex" { + run printf 'a' + run assert_equals_golden --regexp "$output" <(printf '.') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline non-specific exact matching regex" { + run printf 'a\nb' + run assert_equals_golden --regexp "$output" <(printf '...') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline non-specific greedy matching regex" { + run printf 'abc\nxyz' + run assert_equals_golden --regexp "$output" <(printf '.*') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline non-specific non-newline matching regex" { + run printf 'abc\nxyz' + run assert_equals_golden --regexp "$output" <(printf '[^\\n]+\n[^\\n]+') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with specific matching regex" { + run printf 'a' + run assert_equals_golden --regexp "$output" <(printf '[a]') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline specific matching regex" { + run printf 'a\nb' + run assert_equals_golden --regexp "$output" <(printf '[a]\n[b]') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline specific repeating matching regex" { + run printf 'aabbcc\nxxyyzz' + run assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with trailing newlines" { + run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' + run assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with special characters" { + run printf 'aabbcc\n[.?+\nxxyyzz' + run assert_equals_golden --regexp "$output" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with special characters and trailing newlines" { + run --keep-empty-lines printf 'aabbcc\n[.?+\nxxyyzz\n\n' + run assert_equals_golden --regexp "$output" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_equals_golden --regexp: succeeds with multiline start-end matching regex" { + run printf 'abc\ndef\nxyz' + run assert_equals_golden --regexp "$output" <(printf 'abc\n.*xyz') + assert_test_pass +} + +@test "assert_equals_golden --regexp: fails with non-specific non-matching regex - too many" { + run printf 'a' + run assert_equals_golden --regexp "$output" <(printf '..') + + assert_test_fail <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +.. +actual output (1 lines): +a +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with non-specific non-matching regex - too few" { + run printf 'ab' + run assert_equals_golden --regexp "$output" <(printf '.') + + assert_test_fail <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +. +actual output (1 lines): +ab +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with specific non-matching regex" { + run printf 'a' + run assert_equals_golden --regexp "$output" <(printf '[b]') + + assert_test_fail <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (1 lines): +[b] +actual output (1 lines): +a +-- +ERR_MSG +} + +@test "assert_equals_golden --regexp: fails with multiline specific matching regex with extra trailing newlines" { + run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (2 lines): +[abc]+ +[xyz]+ +actual output (3 lines): +aabbcc +xxyyzz + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails with multiline specific matching regex with missing trailing newlines" { + run printf 'aabbcc\nxxyyzz' + run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+\n\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- value does not match regexp golden -- +golden contents (3 lines): +[abc]+ +[xyz]+ + + +actual output (2 lines): +aabbcc +xxyyzz +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_equals_golden --regexp: fails if regex golden is not a valid extended regular expression" { + run assert_equals_golden --regexp "$output" <(printf '[.*') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Invalid extended regular expression in golden file: `[.*' +-- +ERR_MSG +} + +# +# assert_equals_golden +# Misc Error Handling +# + +@test "assert_equals_golden: fails with --regexp --diff" { + run assert_equals_golden --regexp --diff 'abc' <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +`--diff' not supported with `--regexp' +-- +ERR_MSG +} + +@test "assert_equals_golden: fails with unknown option" { + run assert_equals_golden --not-a-real-option 'abc' <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_equals_golden -- +Unsupported flag '--not-a-real-option'. +-- +ERR_MSG +} + +# +# assert_output_equals_golden +# Literal matching +# + +@test "assert_output_equals_golden: succeeds if output and golden match" { + run printf 'a' + run assert_output_equals_golden <(printf 'a') + assert_test_pass +} + +@test "assert_output_equals_golden: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_output_equals_golden <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_output_equals_golden: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_output_equals_golden <(printf 'a\n') + assert_test_pass +} + +@test "assert_output_equals_golden: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_output_equals_golden <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_output_equals_golden: fails if output and golden do not match" { + run printf 'b' + run assert_output_equals_golden <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +a + +actual output (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (3 lines): +a +b +c + +actual output (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (3 lines): +a +b +c +actual output (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_output_equals_golden <(printf '\n') + + assert_test_pass +} + +@test "assert_output_equals_golden: fails if output is and golden are empty" { + run : + run assert_output_equals_golden <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_output_equals_golden: succeeds if output is and golden are empty when allowed" { + run : + run assert_output_equals_golden --allow-empty <(:) + + assert_test_pass +} + +@test "assert_output_equals_golden: succeeds if output is and golden are empty when allowed - kept empty lines" { + run --keep-empty-lines : + run assert_output_equals_golden --allow-empty <(:) + + assert_test_pass +} + +@test "assert_output_equals_golden: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --allow-empty <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if output is empty with newline golden" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails if output is empty with newline golden - kept empty lines" { + run --keep-empty-lines : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden: fails with too few parameters" { + run assert_output_equals_golden + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 0. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails with too many parameters" { + run assert_output_equals_golden a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 3. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails with empty golden file path" { + run assert_output_equals_golden '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails with nonexistent golden file" { + run assert_output_equals_golden some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails with non-openable golden file" { + run assert_output_equals_golden . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_output_equals_golden: '--' stops parsing options" { + run printf '%s' '--diff' + run assert_output_equals_golden -- <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_output_equals_golden: fails due to literal (non-wildcard) matching by default" { + run printf 'b' + run assert_output_equals_golden <(printf '*') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +* +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails due to literal (non-regex) matching by default" { + run printf 'b' + run assert_output_equals_golden <(printf '.*') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +golden contents (1 lines): +.* +actual output (1 lines): +b +-- +ERR_MSG +} + +# +# assert_output_equals_golden +# Literal matching with diff output +# + +@test "assert_output_equals_golden --diff: succeeds if output and golden match" { + run printf 'a' + run assert_output_equals_golden --diff <(printf 'a') + assert_test_pass +} + +@test "assert_output_equals_golden --diff: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_output_equals_golden --diff <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_output_equals_golden --diff: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_output_equals_golden --diff <(printf 'a\n') + assert_test_pass +} + +@test "assert_output_equals_golden --diff: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_output_equals_golden --diff <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_output_equals_golden --diff: fails if output and golden do not match" { + run printf 'b' + run assert_output_equals_golden --diff <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +1c1 +< b +--- +> a +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + run assert_output_equals_golden --diff <(printf 'a\n') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + run assert_output_equals_golden --diff <(printf 'a\nb\nc\n') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +3a4 +> +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + run assert_output_equals_golden --diff <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_output_equals_golden --diff <(printf 'a\nb\nc') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +4d3 +< +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_output_equals_golden --diff <(printf '\n') + + assert_test_pass +} + +@test "assert_output_equals_golden --diff: fails if output is and golden are empty" { + run : + run assert_output_equals_golden --diff <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: succeeds if output is and golden are empty when allowed" { + run : + run assert_output_equals_golden --diff --allow-empty <(:) + + assert_test_pass +} + +@test "assert_output_equals_golden --diff: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + run assert_output_equals_golden --diff <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +1,2c1 +< +< +--- +> a +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + run assert_output_equals_golden --diff --allow-empty <(:) + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails if output is empty with newline golden" { + run : + run assert_output_equals_golden --diff <(printf '\n') + + assert_test_fail <<'ERR_MSG' + +-- output does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails with too few parameters" { + run assert_output_equals_golden --diff + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 0. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails with too many parameters" { + run assert_output_equals_golden --diff a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 3. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails with empty golden file path" { + run assert_output_equals_golden --diff '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails with nonexistent golden file" { + run assert_output_equals_golden --diff some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: fails with non-openable golden file" { + run assert_output_equals_golden --diff . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_output_equals_golden --diff: '--' stops parsing options" { + run printf '%s' '--diff' + run assert_output_equals_golden --diff -- <(printf '%s' '--diff') + + assert_test_pass +} + +# +# assert_output_equals_golden +# Regex matching +# + +@test "assert_output_equals_golden --regexp: succeeds if output and golden match" { + run printf 'a' + run assert_output_equals_golden --regexp <(printf 'a') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds if multiline output and golden match" { + run printf 'a\nb\nc' + run assert_output_equals_golden --regexp <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds if output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\n' + run assert_output_equals_golden --regexp <(printf 'a\n') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds if multiline output and golden match and contain trailing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + run assert_output_equals_golden --regexp <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: fails if output and golden do not match" { + run printf 'b' + run assert_output_equals_golden --regexp <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): +b +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails if output and golden do not match due to extra trailing newline" { + run printf 'a' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +a + +actual output (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if multiline output and golden do not match due to extra trailing newline" { + run printf 'a\nb\nc' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (3 lines): +a +b +c + +actual output (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if multiline output and golden do not match due to extra missing newline" { + run --keep-empty-lines printf 'a\nb\nc\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (3 lines): +a +b +c +actual output (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: succeeds if output is newline with newline golden" { + run --keep-empty-lines printf '\n' + run assert_output_equals_golden --regexp <(printf '\n') + + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: fails if output is and golden are empty" { + run : + run assert_output_equals_golden --regexp <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: succeeds if output is and golden are empty when allowed" { + run : + run assert_output_equals_golden --regexp --allow-empty <(:) + + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: fails if output is newline with non-empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +a +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if output is newline with allowed empty golden" { + run --keep-empty-lines printf '\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp --allow-empty <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (0 lines): + +actual output (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if output is empty with newline golden" { + run : + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): + + +actual output (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails with too few parameters" { + run assert_output_equals_golden --regexp + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 0. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with too many parameters" { + run assert_output_equals_golden --regexp a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Incorrect number of arguments: 3. Expected 1 argument. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with empty golden file path" { + run assert_output_equals_golden --regexp '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with nonexistent golden file" { + run assert_output_equals_golden --regexp some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with non-openable golden file" { + run assert_output_equals_golden --regexp . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: '--' stops parsing options" { + run printf '%s' '--diff' + run assert_output_equals_golden --regexp -- <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with special characters" { + run printf '[.?+' + run assert_output_equals_golden --regexp <(printf '\\[\\.\\?\\+') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with non-specific matching regex" { + run printf 'a' + run assert_output_equals_golden --regexp <(printf '.') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline non-specific exact matching regex" { + run printf 'a\nb' + run assert_output_equals_golden --regexp <(printf '...') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline non-specific greedy matching regex" { + run printf 'abc\nxyz' + run assert_output_equals_golden --regexp <(printf '.*') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline non-specific non-newline matching regex" { + run printf 'abc\nxyz' + run assert_output_equals_golden --regexp <(printf '[^\\n]+\n[^\\n]+') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with specific matching regex" { + run printf 'a' + run assert_output_equals_golden --regexp <(printf '[a]') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline specific matching regex" { + run printf 'a\nb' + run assert_output_equals_golden --regexp <(printf '[a]\n[b]') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline specific repeating matching regex" { + run printf 'aabbcc\nxxyyzz' + run assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline specific matching regex with trailing newlines" { + run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' + run assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline specific matching regex with special characters" { + run printf 'aabbcc\n[.?+\nxxyyzz' + run assert_output_equals_golden --regexp <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline specific matching regex with special characters and trailing newlines" { + run --keep-empty-lines printf 'aabbcc\n[.?+\nxxyyzz\n\n' + run assert_output_equals_golden --regexp <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: succeeds with multiline start-end matching regex" { + run printf 'abc\ndef\nxyz' + run assert_output_equals_golden --regexp <(printf 'abc\n.*xyz') + assert_test_pass +} + +@test "assert_output_equals_golden --regexp: fails with non-specific non-matching regex - too many" { + run printf 'a' + run assert_output_equals_golden --regexp <(printf '..') + + assert_test_fail <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +.. +actual output (1 lines): +a +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with non-specific non-matching regex - too few" { + run printf 'ab' + run assert_output_equals_golden --regexp <(printf '.') + + assert_test_fail <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +. +actual output (1 lines): +ab +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with specific non-matching regex" { + run printf 'a' + run assert_output_equals_golden --regexp <(printf '[b]') + + assert_test_fail <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (1 lines): +[b] +actual output (1 lines): +a +-- +ERR_MSG +} + +@test "assert_output_equals_golden --regexp: fails with multiline specific matching regex with extra trailing newlines" { + run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' + run --keep-empty-lines assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (2 lines): +[abc]+ +[xyz]+ +actual output (3 lines): +aabbcc +xxyyzz + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails with multiline specific matching regex with missing trailing newlines" { + run printf 'aabbcc\nxxyyzz' + run --keep-empty-lines assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+\n\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- output does not match regexp golden -- +golden contents (3 lines): +[abc]+ +[xyz]+ + + +actual output (2 lines): +aabbcc +xxyyzz +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_output_equals_golden --regexp: fails if regex golden is not a valid extended regular expression" { + run assert_output_equals_golden --regexp <(printf '[.*') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Invalid extended regular expression in golden file: `[.*' +-- +ERR_MSG +} + +# +# assert_output_equals_golden +# Misc Error Handling +# + +@test "assert_output_equals_golden: fails with --regexp --diff" { + run assert_output_equals_golden --regexp --diff <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +`--diff' not supported with `--regexp' +-- +ERR_MSG +} + +@test "assert_output_equals_golden: fails with unknown option" { + run assert_output_equals_golden --not-a-real-option <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_output_equals_golden -- +Unsupported flag '--not-a-real-option'. +-- +ERR_MSG +} + +# +# Automatic golden file updating +# + +@test "auto-update: assert_equals_golden: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run printf "$tested_output" + run assert_equals_golden "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden "$output" "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_equals_golden "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run printf "$tested_output" + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: updates golden for failure multiline with regex and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: updates golden for failure multiline with regex and special chars" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: updates golden for failure multiline with regex, special chars, and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_equals_golden --regexp "$output" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run printf "$tested_output" + run assert_output_equals_golden "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden --regexp: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden --regexp: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + run printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden --regexp: updates golden for failure multiline with regex and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden --regexp: updates golden for failure multiline with regex and special chars" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_output_equals_golden --regexp: updates golden for failure multiline with regex, special chars, and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno\n\n' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} From 71e2c5a59a0e2e8c93e237c2bfffd9d747c6a444 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Mon, 13 May 2024 03:12:24 -0700 Subject: [PATCH 02/23] * Fixing incorrect error message output when `assert_equals_golden` failed (using `$output` instead of passed string). * Updating `assert_equals_golden` tests in `test/assert_equals_golden.bats` to invalidate `output` and use another variable instead (to better catch any similar issues). --- src/assert_equals_golden.bash | 8 +- test/assert_equals_golden.bats | 510 +++++++++++++++++++++++---------- 2 files changed, 368 insertions(+), 150 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 266608f..b04317a 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -58,7 +58,7 @@ # -- value does not match golden -- # golden contents (1 lines): # want -# actual output (1 lines): +# actual value (1 lines): # have # -- # ``` @@ -212,19 +212,19 @@ assert_equals_golden() { if (( assert_failed )); then if ! (( update_goldens_on_failure )); then if (( show_diff )); then - diff <(echo "$output") <(echo "$golden_file_contents") \ + diff <(echo "$value") <(echo "$golden_file_contents") \ | batslib_decorate 'value does not match golden' \ | fail elif (( is_mode_regexp )); then batslib_print_kv_multi \ 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" \ + 'actual value' "$value" \ | batslib_decorate 'value does not match regexp golden' \ | fail else batslib_print_kv_multi \ 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" \ + 'actual value' "$value" \ | batslib_decorate 'value does not match golden' \ | fail fi diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index 994d874..b56df50 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -11,38 +11,48 @@ bats_require_minimum_version 1.5.0 @test "assert_equals_golden: succeeds if output and golden match" { run printf 'a' - run assert_equals_golden "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf 'a') assert_test_pass } @test "assert_equals_golden: succeeds if multiline output and golden match" { run printf 'a\nb\nc' - run assert_equals_golden "$output" <(printf 'a\nb\nc') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf 'a\nb\nc') assert_test_pass } @test "assert_equals_golden: succeeds if output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden "$output" <(printf 'a\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf 'a\n') assert_test_pass } @test "assert_equals_golden: succeeds if multiline output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden "$output" <(printf 'a\nb\nc\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf 'a\nb\nc\n') assert_test_pass } @test "assert_equals_golden: fails if output and golden do not match" { run printf 'b' - run assert_equals_golden "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf 'a') assert_test_fail <<'ERR_MSG' -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -50,8 +60,10 @@ ERR_MSG @test "assert_equals_golden: fails if output and golden do not match due to extra trailing newline" { run printf 'a' + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\n') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf 'a\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -61,7 +73,7 @@ ERR_MSG golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -73,8 +85,10 @@ ERR_MSG @test "assert_equals_golden: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\nb\nc\n') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf 'a\nb\nc\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -86,7 +100,7 @@ a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -100,8 +114,10 @@ ERR_MSG @test "assert_equals_golden: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf 'a') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -110,7 +126,7 @@ ERR_MSG -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -123,8 +139,10 @@ ERR_MSG @test "assert_equals_golden: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf 'a\nb\nc') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf 'a\nb\nc') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -135,7 +153,7 @@ golden contents (3 lines): a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -150,14 +168,18 @@ ERR_MSG @test "assert_equals_golden: succeeds if output is newline with newline golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden "$output" <(printf '\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf '\n') assert_test_pass } @test "assert_equals_golden: fails if output is and golden are empty" { run : - run assert_equals_golden "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(:) assert_test_fail <<'ERR_MSG' @@ -169,22 +191,28 @@ ERR_MSG @test "assert_equals_golden: succeeds if output is and golden are empty when allowed" { run : - run assert_equals_golden --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --allow-empty "$tested_value" <(:) assert_test_pass } @test "assert_equals_golden: succeeds if output is and golden are empty when allowed - kept empty lines" { run --keep-empty-lines : - run assert_equals_golden --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --allow-empty "$tested_value" <(:) assert_test_pass } @test "assert_equals_golden: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf 'a') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -193,7 +221,7 @@ ERR_MSG -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): -- @@ -207,7 +235,9 @@ ERR_MSG @test "assert_equals_golden: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --allow-empty "$tested_value" <(:) # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -216,7 +246,7 @@ ERR_MSG -- value does not match golden -- golden contents (0 lines): -actual output (1 lines): +actual value (1 lines): -- @@ -229,8 +259,10 @@ ERR_MSG @test "assert_equals_golden: fails if output is empty with newline golden" { run : + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf '\n') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf '\n') # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -239,7 +271,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -251,8 +283,10 @@ ERR_MSG @test "assert_equals_golden: fails if output is empty with newline golden - kept empty lines" { run --keep-empty-lines : + tested_value="$output" + output='UNUSED' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden "$output" <(printf '\n') + run --keep-empty-lines assert_equals_golden "$tested_value" <(printf '\n') # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -261,7 +295,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -334,14 +368,16 @@ ERR_MSG @test "assert_equals_golden: fails due to literal (non-wildcard) matching by default" { run printf 'b' - run assert_equals_golden "$output" <(printf '*') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf '*') assert_test_fail <<'ERR_MSG' -- value does not match golden -- golden contents (1 lines): * -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -349,14 +385,16 @@ ERR_MSG @test "assert_equals_golden: fails due to literal (non-regex) matching by default" { run printf 'b' - run assert_equals_golden "$output" <(printf '.*') + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" <(printf '.*') assert_test_fail <<'ERR_MSG' -- value does not match golden -- golden contents (1 lines): .* -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -369,62 +407,80 @@ ERR_MSG @test "assert_equals_golden --stdin: succeeds if output and golden match" { run printf 'a' - run assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if output and golden match with '-' arg" { run printf 'a' - run assert_equals_golden - <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden - <(printf 'a') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if multiline output and golden match" { run printf 'a\nb\nc' - run assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if multiline output and golden match with '-' arg" { run printf 'a\nb\nc' - run assert_equals_golden - <(printf 'a\nb\nc') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden - <(printf 'a\nb\nc') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden --stdin <(printf 'a\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf 'a\n') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if output and golden match and contain trailing newline with '-' arg" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden - <(printf 'a\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden - <(printf 'a\n') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if multiline output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if multiline output and golden match and contain trailing newline with '-' arg" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden - <(printf 'a\nb\nc\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden - <(printf 'a\nb\nc\n') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: fails if output and golden do not match" { run printf 'b' - run assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") assert_test_fail <<'ERR_MSG' -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -432,14 +488,16 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output and golden do not match with '-' arg" { run printf 'b' - run assert_equals_golden - <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden - <(printf 'a') < <(printf "$tested_value") assert_test_fail <<'ERR_MSG' -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -448,7 +506,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output and golden do not match due to extra trailing newline" { run printf 'a' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\n') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -458,7 +518,7 @@ ERR_MSG golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -471,7 +531,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -483,7 +545,7 @@ a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -498,7 +560,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -507,7 +571,7 @@ ERR_MSG -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -521,7 +585,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -532,7 +598,7 @@ golden contents (3 lines): a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -547,14 +613,18 @@ ERR_MSG @test "assert_equals_golden --stdin: succeeds if output is newline with newline golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(printf '\n') < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: fails if output is and golden are empty" { run : - run assert_equals_golden --stdin <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin <(:) < <(printf "$tested_value") assert_test_fail <<'ERR_MSG' @@ -566,21 +636,27 @@ ERR_MSG @test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed" { run : - run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed with '-' arg" { run : - run assert_equals_golden --allow-empty - <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --allow-empty - <(:) < <(printf "$tested_value") assert_test_pass } @test "assert_equals_golden --stdin: succeeds if output is and golden are empty when allowed - kept empty lines" { run --keep-empty-lines : - run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run assert_equals_golden --stdin --allow-empty <(:) < <(printf "$tested_value") assert_test_pass } @@ -588,7 +664,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -597,7 +675,7 @@ ERR_MSG -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): -- @@ -611,7 +689,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with non-empty golden with '-' arg" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden - <(printf 'a') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden - <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -620,7 +700,7 @@ ERR_MSG -- value does not match golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): -- @@ -634,7 +714,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin --allow-empty <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin --allow-empty <(:) < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -643,7 +725,7 @@ ERR_MSG -- value does not match golden -- golden contents (0 lines): -actual output (1 lines): +actual value (1 lines): -- @@ -657,7 +739,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden with '-' arg" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --allow-empty - <(:) < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --allow-empty - <(:) < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -666,7 +750,7 @@ ERR_MSG -- value does not match golden -- golden contents (0 lines): -actual output (1 lines): +actual value (1 lines): -- @@ -680,7 +764,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden" { run : # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -689,7 +775,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -702,7 +788,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden with '-' arg" { run : # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden - <(printf '\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden - <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -711,7 +799,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -724,7 +812,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden - kept empty lines" { run --keep-empty-lines : # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$output") + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -733,7 +823,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -750,31 +840,41 @@ ERR_MSG @test "assert_equals_golden --diff: succeeds if output and golden match" { run printf 'a' - run assert_equals_golden --diff "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a') assert_test_pass } @test "assert_equals_golden --diff: succeeds if multiline output and golden match" { run printf 'a\nb\nc' - run assert_equals_golden --diff "$output" <(printf 'a\nb\nc') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc') assert_test_pass } @test "assert_equals_golden --diff: succeeds if output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden --diff "$output" <(printf 'a\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\n') assert_test_pass } @test "assert_equals_golden --diff: succeeds if multiline output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden --diff "$output" <(printf 'a\nb\nc\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc\n') assert_test_pass } @test "assert_equals_golden --diff: fails if output and golden do not match" { run printf 'b' - run assert_equals_golden --diff "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a') assert_test_fail <<'ERR_MSG' @@ -789,7 +889,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if output and golden do not match due to extra trailing newline" { run printf 'a' - run assert_equals_golden --diff "$output" <(printf 'a\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\n') assert_test_fail <<'ERR_MSG' @@ -802,7 +904,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' - run assert_equals_golden --diff "$output" <(printf 'a\nb\nc\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc\n') assert_test_fail <<'ERR_MSG' @@ -815,7 +919,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden --diff "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a') assert_test_fail <<'ERR_MSG' @@ -828,7 +934,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden --diff "$output" <(printf 'a\nb\nc') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc') assert_test_fail <<'ERR_MSG' @@ -841,14 +949,18 @@ ERR_MSG @test "assert_equals_golden --diff: succeeds if output is newline with newline golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden --diff "$output" <(printf '\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf '\n') assert_test_pass } @test "assert_equals_golden --diff: fails if output is and golden are empty" { run : - run assert_equals_golden --diff "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(:) assert_test_fail <<'ERR_MSG' @@ -860,14 +972,18 @@ ERR_MSG @test "assert_equals_golden --diff: succeeds if output is and golden are empty when allowed" { run : - run assert_equals_golden --diff --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff --allow-empty "$tested_value" <(:) assert_test_pass } @test "assert_equals_golden --diff: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden --diff "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf 'a') assert_test_fail <<'ERR_MSG' @@ -883,7 +999,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden --diff --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff --allow-empty "$tested_value" <(:) assert_test_fail <<'ERR_MSG' @@ -896,7 +1014,9 @@ ERR_MSG @test "assert_equals_golden --diff: fails if output is empty with newline golden" { run : - run assert_equals_golden --diff "$output" <(printf '\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --diff "$tested_value" <(printf '\n') assert_test_fail <<'ERR_MSG' @@ -975,38 +1095,48 @@ ERR_MSG @test "assert_equals_golden --regexp: succeeds if output and golden match" { run printf 'a' - run assert_equals_golden --regexp "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'a') assert_test_pass } @test "assert_equals_golden --regexp: succeeds if multiline output and golden match" { run printf 'a\nb\nc' - run assert_equals_golden --regexp "$output" <(printf 'a\nb\nc') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc') assert_test_pass } @test "assert_equals_golden --regexp: succeeds if output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\n' - run assert_equals_golden --regexp "$output" <(printf 'a\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'a\n') assert_test_pass } @test "assert_equals_golden --regexp: succeeds if multiline output and golden match and contain trailing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - run assert_equals_golden --regexp "$output" <(printf 'a\nb\nc\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc\n') assert_test_pass } @test "assert_equals_golden --regexp: fails if output and golden do not match" { run printf 'b' - run assert_equals_golden --regexp "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'a') assert_test_fail <<'ERR_MSG' -- value does not match regexp golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): b -- ERR_MSG @@ -1015,7 +1145,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output and golden do not match due to extra trailing newline" { run printf 'a' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\n') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1025,7 +1157,7 @@ ERR_MSG golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -1038,7 +1170,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\nb\nc\n') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1050,7 +1184,7 @@ a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -1065,7 +1199,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1074,7 +1210,7 @@ ERR_MSG -- value does not match regexp golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): a -- @@ -1088,7 +1224,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a\nb\nc') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1099,7 +1237,7 @@ golden contents (3 lines): a b c -actual output (3 lines): +actual value (3 lines): a b c @@ -1114,14 +1252,18 @@ ERR_MSG @test "assert_equals_golden --regexp: succeeds if output is newline with newline golden" { run --keep-empty-lines printf '\n' - run assert_equals_golden --regexp "$output" <(printf '\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '\n') assert_test_pass } @test "assert_equals_golden --regexp: fails if output is and golden are empty" { run : - run assert_equals_golden --regexp "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(:) assert_test_fail <<'ERR_MSG' @@ -1133,7 +1275,9 @@ ERR_MSG @test "assert_equals_golden --regexp: succeeds if output is and golden are empty when allowed" { run : - run assert_equals_golden --regexp --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp --allow-empty "$tested_value" <(:) assert_test_pass } @@ -1141,7 +1285,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf 'a') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1150,7 +1296,7 @@ ERR_MSG -- value does not match regexp golden -- golden contents (1 lines): a -actual output (1 lines): +actual value (1 lines): -- @@ -1164,7 +1310,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp --allow-empty "$output" <(:) + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp --allow-empty "$tested_value" <(:) # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1173,7 +1321,7 @@ ERR_MSG -- value does not match regexp golden -- golden contents (0 lines): -actual output (1 lines): +actual value (1 lines): -- @@ -1187,7 +1335,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is empty with newline golden" { run : # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '\n') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '\n') # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. expected="$(cat <<'ERR_MSG' @@ -1196,7 +1346,7 @@ ERR_MSG golden contents (1 lines): -actual output (0 lines): +actual value (0 lines): -- @@ -1269,86 +1419,112 @@ ERR_MSG @test "assert_equals_golden --regexp: succeeds with special characters" { run printf '[.?+' - run assert_equals_golden --regexp "$output" <(printf '\\[\\.\\?\\+') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '\\[\\.\\?\\+') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with non-specific matching regex" { run printf 'a' - run assert_equals_golden --regexp "$output" <(printf '.') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '.') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline non-specific exact matching regex" { run printf 'a\nb' - run assert_equals_golden --regexp "$output" <(printf '...') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '...') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline non-specific greedy matching regex" { run printf 'abc\nxyz' - run assert_equals_golden --regexp "$output" <(printf '.*') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '.*') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline non-specific non-newline matching regex" { run printf 'abc\nxyz' - run assert_equals_golden --regexp "$output" <(printf '[^\\n]+\n[^\\n]+') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[^\\n]+\n[^\\n]+') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with specific matching regex" { run printf 'a' - run assert_equals_golden --regexp "$output" <(printf '[a]') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[a]') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline specific matching regex" { run printf 'a\nb' - run assert_equals_golden --regexp "$output" <(printf '[a]\n[b]') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[a]\n[b]') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline specific repeating matching regex" { run printf 'aabbcc\nxxyyzz' - run assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with trailing newlines" { run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' - run assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+\n\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+\n\n') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with special characters" { run printf 'aabbcc\n[.?+\nxxyyzz' - run assert_equals_golden --regexp "$output" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline specific matching regex with special characters and trailing newlines" { run --keep-empty-lines printf 'aabbcc\n[.?+\nxxyyzz\n\n' - run assert_equals_golden --regexp "$output" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+\n\n') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+\n\n') assert_test_pass } @test "assert_equals_golden --regexp: succeeds with multiline start-end matching regex" { run printf 'abc\ndef\nxyz' - run assert_equals_golden --regexp "$output" <(printf 'abc\n.*xyz') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf 'abc\n.*xyz') assert_test_pass } @test "assert_equals_golden --regexp: fails with non-specific non-matching regex - too many" { run printf 'a' - run assert_equals_golden --regexp "$output" <(printf '..') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '..') assert_test_fail <<'ERR_MSG' -- value does not match regexp golden -- golden contents (1 lines): .. -actual output (1 lines): +actual value (1 lines): a -- ERR_MSG @@ -1356,14 +1532,16 @@ ERR_MSG @test "assert_equals_golden --regexp: fails with non-specific non-matching regex - too few" { run printf 'ab' - run assert_equals_golden --regexp "$output" <(printf '.') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '.') assert_test_fail <<'ERR_MSG' -- value does not match regexp golden -- golden contents (1 lines): . -actual output (1 lines): +actual value (1 lines): ab -- ERR_MSG @@ -1371,14 +1549,16 @@ ERR_MSG @test "assert_equals_golden --regexp: fails with specific non-matching regex" { run printf 'a' - run assert_equals_golden --regexp "$output" <(printf '[b]') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[b]') assert_test_fail <<'ERR_MSG' -- value does not match regexp golden -- golden contents (1 lines): [b] -actual output (1 lines): +actual value (1 lines): a -- ERR_MSG @@ -1386,7 +1566,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails with multiline specific matching regex with extra trailing newlines" { run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1396,7 +1578,7 @@ ERR_MSG golden contents (2 lines): [abc]+ [xyz]+ -actual output (3 lines): +actual value (3 lines): aabbcc xxyyzz @@ -1411,7 +1593,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails with multiline specific matching regex with missing trailing newlines" { run printf 'aabbcc\nxxyyzz' - run --keep-empty-lines assert_equals_golden --regexp "$output" <(printf '[abc]+\n[xyz]+\n\n') + tested_value="$output" + output='UNUSED' + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+\n\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1423,7 +1607,7 @@ golden contents (3 lines): [xyz]+ -actual output (2 lines): +actual value (2 lines): aabbcc xxyyzz -- @@ -1435,7 +1619,9 @@ ERR_MSG } @test "assert_equals_golden --regexp: fails if regex golden is not a valid extended regular expression" { - run assert_equals_golden --regexp "$output" <(printf '[.*') + tested_value="$output" + output='UNUSED' + run assert_equals_golden --regexp "$tested_value" <(printf '[.*') assert_test_fail <<'ERR_MSG' @@ -2576,7 +2762,9 @@ ERR_MSG run printf "$tested_output" BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 - run assert_equals_golden "$output" "$temp_golden_file" + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" "$temp_golden_file" assert_test_fail <<'ERR_MSG' @@ -2588,7 +2776,9 @@ ERR_MSG [ "$(cat "$temp_golden_file")" = "$tested_output" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE run printf "$tested_output" - run assert_equals_golden "$output" "$temp_golden_file" + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" "$temp_golden_file" assert_test_pass } @@ -2604,7 +2794,9 @@ ERR_MSG run printf "$tested_output" BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 - run assert_equals_golden "$output" "$temp_golden_file" + tested_value="$output" + output='UNUSED' + run assert_equals_golden "$tested_value" "$temp_golden_file" assert_test_fail < Date: Tue, 14 May 2024 01:10:51 -0700 Subject: [PATCH 03/23] * Fixing a few more comments. --- test/assert_equals_golden.bats | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index b56df50..25de5d8 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -234,9 +234,9 @@ ERR_MSG @test "assert_equals_golden: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --allow-empty "$tested_value" <(:) # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -505,9 +505,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output and golden do not match due to extra trailing newline" { run printf 'a' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\n') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. @@ -530,9 +530,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc\n') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. @@ -559,9 +559,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -584,9 +584,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf 'a\nb\nc') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -663,9 +663,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -688,9 +688,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with non-empty golden with '-' arg" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden - <(printf 'a') < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -713,9 +713,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin --allow-empty <(:) < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -738,9 +738,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is newline with allowed empty golden with '-' arg" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --allow-empty - <(:) < <(printf "$tested_value") # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -763,9 +763,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden" { run : - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -787,9 +787,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden with '-' arg" { run : - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden - <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -811,9 +811,9 @@ ERR_MSG @test "assert_equals_golden --stdin: fails if output is empty with newline golden - kept empty lines" { run --keep-empty-lines : - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --stdin <(printf '\n') < <(printf "$tested_value") # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1144,9 +1144,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output and golden do not match due to extra trailing newline" { run printf 'a' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. @@ -1169,9 +1169,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. @@ -1198,9 +1198,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -1223,9 +1223,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if multiline output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\nb\nc\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a\nb\nc') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -1284,9 +1284,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is newline with non-empty golden" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf 'a') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -1309,9 +1309,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is newline with allowed empty golden" { run --keep-empty-lines printf '\n' - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp --allow-empty "$tested_value" <(:) # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -1334,9 +1334,9 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if output is empty with newline golden" { run : - # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '\n') # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. @@ -1568,6 +1568,7 @@ ERR_MSG run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -1595,6 +1596,7 @@ ERR_MSG run printf 'aabbcc\nxxyyzz' tested_value="$output" output='UNUSED' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_equals_golden --regexp "$tested_value" <(printf '[abc]+\n[xyz]+\n\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. @@ -2662,6 +2664,7 @@ ERR_MSG @test "assert_output_equals_golden --regexp: fails with multiline specific matching regex with extra trailing newlines" { run --keep-empty-lines printf 'aabbcc\nxxyyzz\n\n' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. @@ -2687,6 +2690,7 @@ ERR_MSG @test "assert_output_equals_golden --regexp: fails with multiline specific matching regex with missing trailing newlines" { run printf 'aabbcc\nxxyyzz' + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. run --keep-empty-lines assert_output_equals_golden --regexp <(printf '[abc]+\n[xyz]+\n\n') # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. From 8d530def1f588f1d9117d83a2417a77553ee3d69 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Wed, 15 May 2024 22:21:25 -0700 Subject: [PATCH 04/23] * Adding `assert_file_equals_golden` for easier assertions on files. * Adding new test cases for `assert_file_equals_golden`. --- src/assert_equals_golden.bash | 286 +++++++ test/assert_equals_golden.bats | 1313 ++++++++++++++++++++++++++++++++ 2 files changed, 1599 insertions(+) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index b04317a..8695693 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -551,3 +551,289 @@ assert_output_equals_golden() { fi fi } + +# assert_file_equals_golden +# ============ +# +# Summary: Fail if the target file and golden file contents are not equal. +# +# Usage: assert_file_equals_golden [-e | --regexp | -d | --diff] [--allow-empty] [--] +# +# Options: +# -e, --regexp Treat file contents of as an multiline extended regular expression. +# -d, --diff Displays `diff` between target file and golden contents instead of full strings. +# A file that has contents which must match against the target file's contents. +# +# ```bash +# @test 'assert_file_equals_golden()' { +# run echo 'have' +# assert_file_equals_golden 'generated/file.txt' 'some/path/golden_file.txt' +# } +# ``` +# +# IO: +# STDERR - expected and actual outputs, or their diff, on failure +# Globals: +# BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - The golden file's contents will be updated to the target file's contents if it did not match. +# Returns: +# 0 - if contents is equal to file contents in +# 1 - otherwise +# +# Golden files hold the entirety of the expected output. +# Contents will properly/consistently match to empty lines / trailing new lines (when used with `run --keep-empty-lines` or similar). +# Golden files are, by default, not allowed to be empty. This is to catch common authoring errors. If intented, this can be overridden with `--allow-empty`. +# +# Golden files have a number of benefits when used for asserting against output, including: +# * WYSIWYG plaintext output assertions (separating asserted output from test case logic). +# * Test failure output that is searchable (asserted output is checked into repo as files). +# * Clear file diffs of test assertions during merge / code review. +# * Terse assertions in test cases (single assert instead of many verbose `assert_line` and `refute_line` for every line of output). +# * Reusable golden files (declared once, used for many test cases). +# * Clear intention (same exact expected output) when asserted against same goldens in multiple test cases. +# * Can be clearly diff'd across multiple lines in failure message(s). +# * Easily updated. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set, failed assertions will result in the golden file being updated. +# The golden file contents is updated to be able to pass upon subsequent runs. +# All tests that update goldens still fails (enforcing that all passing tests are achieved with pre-existing correct golden). +# This is set via an environment variable to allow mass golden file updates across many tests. +# +# ## Literal matching +# +# On failure, the expected and actual output are displayed. Line count is always displayed. +# +# ``` +# -- file contents does not match golden -- +# golden contents (1 lines): +# want +# actual file contents (1 lines): +# have +# -- +# ``` +# +# If `--diff` is given, the output is changed to `diff` between target file and the golden file contents. +# +# ``` +# -- file contents does not match golden -- +# 1c1 +# < have +# --- +# > want +# -- +# ``` +# +# ## Regular expression matching +# +# If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. +# This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. +# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. +# +# If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. +# Each line in the existing golden will attempt to match to the line of , preferring longer lines. +# If no pre-existing golden line matches, that line will be updated with the exact line string from . +# Not all lines can be reused (e.g. multiline expressions), but the golden file can be manually changed after automatic update. +# +# `--diff` is not supported with `--regexp`. +# +assert_file_equals_golden() { + local -i is_mode_regexp=0 + local -i show_diff=0 + local -i allow_empty=0 + + while (( "$#" )); do + case "$1" in + -e|--regexp) + is_mode_regexp=1 + shift + ;; + -d|--diff) + show_diff=1; + shift + ;; + --allow-empty) + allow_empty=1 + shift + ;; + --) + shift + break + ;; + --*=|-*) + echo "Unsupported flag '$1'." \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + ;; + *) + break + ;; + esac + done + + if [ $# -ne 2 ]; then + echo "Incorrect number of arguments: $#. Expected 2 argument." \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + + if (( show_diff )) && (( is_mode_regexp )); then + echo "\`--diff' not supported with \`--regexp'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + + local -r target_file_path="${1-}" + local -r golden_file_path="${2-}" + local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:-0}" + + if [ -z "$target_file_path" ]; then + echo "Target file path was not given or it was empty." \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + if [ ! -e "$target_file_path" ]; then + echo "Target file was not found. File path: '$target_file_path'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + if [ -z "$golden_file_path" ]; then + echo "Golden file path was not given or it was empty." \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + if [ ! -e "$golden_file_path" ]; then + echo "Golden file was not found. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + + local target_file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + target_file_contents="$(cat "$target_file_path" 2>/dev/null && printf '.')" + if [ $? -ne 0 ]; then + echo "Failed to read target file. File path: '$target_file_path'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + target_file_contents="${target_file_contents%.}" + + local golden_file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" + if [ $? -ne 0 ]; then + echo "Failed to read golden file. File path: '$golden_file_path'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + golden_file_contents="${golden_file_contents%.}" + if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then + echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + fi + + local -i assert_failed=0 + if (( is_mode_regexp )); then + if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then + echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ + | batslib_decorate 'ERROR: assert_file_equals_golden' \ + | fail + return $? + elif ! [[ "$target_file_contents" =~ ^${golden_file_contents}$ ]]; then + assert_failed=1 + fi + elif [[ "$target_file_contents" != "$golden_file_contents" ]]; then + assert_failed=1 + fi + + if (( assert_failed )); then + if ! (( update_goldens_on_failure )); then + if (( show_diff )); then + diff <(echo "$target_file_contents") <(echo "$golden_file_contents") \ + | batslib_decorate 'file contents does not match golden' \ + | fail + elif (( is_mode_regexp )); then + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual file contents' "$target_file_contents" \ + | batslib_decorate 'file contents does not match regexp golden' \ + | fail + else + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual file contents' "$target_file_contents" \ + | batslib_decorate 'file contents does not match golden' \ + | fail + fi + else + if ! (( is_mode_regexp )); then + # Non-regex golden update is straight forward. + printf '%s' "$target_file_contents" 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_file_equals_golden' \ + | fail + return $? + fi + else + # To do a best-approximation for regex goldens, + # try and use existing lines as a library for updated lines (preferring longer lines). + # This is done line by line on the output. + # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). + # Any line guess which is not preferred can be manually corrected/updated by the author. + local -a output_lines=() + local -a sorted_golden_lines=() + local temp= + while IFS='' read -r temp; do + output_lines+=("$temp") + done < <(printf '%s' "$target_file_contents" ; printf '\n') + while IFS='' read -r temp; do + sorted_golden_lines+=("$temp") + done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') + # First, clear out the golden file's contents (so new data can just be appended below). + : 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate 'FAIL: assert_file_equals_golden' \ + | fail + return $? + fi + # Go line by line over the output, looking for the best suggested replacement. + local best_guess_for_line= + for line_in_output in "${output_lines[@]}"; do + # Default the output line itself as the best guess for the new golden. + # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + for line_in_golden in "${sorted_golden_lines[@]}"; do + if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then + # If there's a line from the previous golden output that matches, use that is the best guess instead. + # No need to escape special characters, as `line_in_golden` is already in proper form. + best_guess_for_line="$line_in_golden" + break + fi + done + if [ -s "$golden_file_path" ]; then + printf '\n' >> "$golden_file_path" + fi + printf '%s' "$best_guess_for_line" >> "$golden_file_path" + done + fi + echo "Golden file updated after mismatch." \ + | batslib_decorate 'FAIL: assert_file_equals_golden' \ + | fail + return $? + fi + fi +} diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index 25de5d8..0319f5d 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -2752,6 +2752,1101 @@ Unsupported flag '--not-a-real-option'. ERR_MSG } +# +# assert_file_equals_golden +# Literal matching +# + +@test "assert_file_equals_golden: succeeds if output and golden match" { + run assert_file_equals_golden <(printf 'a') <(printf 'a') + assert_test_pass +} + +@test "assert_file_equals_golden: succeeds if multiline output and golden match" { + run assert_file_equals_golden <(printf 'a\nb\nc') <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_file_equals_golden: succeeds if output and golden match and contain trailing newline" { + run assert_file_equals_golden <(printf 'a\n') <(printf 'a\n') + assert_test_pass +} + +@test "assert_file_equals_golden: succeeds if multiline output and golden match and contain trailing newline" { + run assert_file_equals_golden <(printf 'a\nb\nc\n') <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_file_equals_golden: fails if output and golden do not match" { + run assert_file_equals_golden <(printf 'b') <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +a +actual file contents (1 lines): +b +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails if output and golden do not match due to extra trailing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(printf 'a') <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +a + +actual file contents (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails if multiline output and golden do not match due to extra trailing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(printf 'a\nb\nc') <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (3 lines): +a +b +c + +actual file contents (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails if output and golden do not match due to extra missing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(printf 'a\n') <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +a +actual file contents (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails if multiline output and golden do not match due to extra missing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(printf 'a\nb\nc\n') <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (3 lines): +a +b +c +actual file contents (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: succeeds if output is newline with newline golden" { + run assert_file_equals_golden <(printf '\n') <(printf '\n') + + assert_test_pass +} + +@test "assert_file_equals_golden: fails if output is and golden are empty" { + run assert_file_equals_golden <(:) <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_file_equals_golden: succeeds if output is and golden are empty when allowed" { + run assert_file_equals_golden --allow-empty <(:) <(:) + + assert_test_pass +} + +@test "assert_file_equals_golden: fails if output is newline with non-empty golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(printf '\n') <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +a +actual file contents (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails if output is newline with allowed empty golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --allow-empty <(printf '\n') <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (0 lines): + +actual file contents (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails if output is empty with newline golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden <(:) <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): + + +actual file contents (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden: fails with too few parameters" { + run assert_file_equals_golden + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 0. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with too many parameters" { + run assert_file_equals_golden a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 3. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with empty target file path" { + run assert_file_equals_golden '' <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with empty golden file path" { + run assert_file_equals_golden <(print 'a') '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with nonexistent target file" { + run assert_file_equals_golden some/path/this_file_definitely_does_not_exist.txt <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with nonexistent golden file" { + run assert_file_equals_golden <(print 'a') some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with non-openable target file" { + run assert_file_equals_golden . <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read target file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with non-openable golden file" { + run assert_file_equals_golden <(print 'a') . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden: '--' stops parsing options" { + run assert_file_equals_golden -- <(printf '%s' '--diff') <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_file_equals_golden: fails due to literal (non-wildcard) matching by default" { + run assert_file_equals_golden <(printf 'b') <(printf '*') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +* +actual file contents (1 lines): +b +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails due to literal (non-regex) matching by default" { + run assert_file_equals_golden <(printf 'b') <(printf '.*') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +golden contents (1 lines): +.* +actual file contents (1 lines): +b +-- +ERR_MSG +} + +# +# assert_file_equals_golden +# Literal matching with diff output +# + +@test "assert_file_equals_golden --diff: succeeds if output and golden match" { + run assert_file_equals_golden --diff <(printf 'a') <(printf 'a') + assert_test_pass +} + +@test "assert_file_equals_golden --diff: succeeds if multiline output and golden match" { + run assert_file_equals_golden --diff <(printf 'a\nb\nc') <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_file_equals_golden --diff: succeeds if output and golden match and contain trailing newline" { + run assert_file_equals_golden --diff <(printf 'a\n') <(printf 'a\n') + assert_test_pass +} + +@test "assert_file_equals_golden --diff: succeeds if multiline output and golden match and contain trailing newline" { + run assert_file_equals_golden --diff <(printf 'a\nb\nc\n') <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_file_equals_golden --diff: fails if output and golden do not match" { + run assert_file_equals_golden --diff <(printf 'b') <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +1c1 +< b +--- +> a +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if output and golden do not match due to extra trailing newline" { + run assert_file_equals_golden --diff <(printf 'a') <(printf 'a\n') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { + run assert_file_equals_golden --diff <(printf 'a\nb\nc') <(printf 'a\nb\nc\n') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +3a4 +> +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { + run assert_file_equals_golden --diff <(printf 'a\n') <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if multiline output and golden do not match due to extra missing newline" { + run assert_file_equals_golden --diff <(printf 'a\nb\nc\n') <(printf 'a\nb\nc') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +4d3 +< +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: succeeds if output is newline with newline golden" { + run assert_file_equals_golden --diff <(printf '\n') <(printf '\n') + + assert_test_pass +} + +@test "assert_file_equals_golden --diff: fails if output is and golden are empty" { + run assert_file_equals_golden --diff <(:) <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: succeeds if output is and golden are empty when allowed" { + run assert_file_equals_golden --diff --allow-empty <(:) <(:) + + assert_test_pass +} + +@test "assert_file_equals_golden --diff: fails if output is newline with non-empty golden" { + run assert_file_equals_golden --diff <(printf '\n') <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +1,2c1 +< +< +--- +> a +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if output is newline with allowed empty golden" { + run assert_file_equals_golden --diff --allow-empty <(printf '\n') <(:) + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +2d1 +< +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails if output is empty with newline golden" { + run assert_file_equals_golden --diff <(:) <(printf '\n') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match golden -- +1a2 +> +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with too few parameters" { + run assert_file_equals_golden --diff + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 0. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with too many parameters" { + run assert_file_equals_golden --diff a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 3. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with empty target file path" { + run assert_file_equals_golden --diff '' <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with empty golden file path" { + run assert_file_equals_golden --diff <(print 'a') '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with nonexistent target file" { + run assert_file_equals_golden --diff some/path/this_file_definitely_does_not_exist.txt <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with nonexistent golden file" { + run assert_file_equals_golden --diff <(print 'a') some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with non-openable target file" { + run assert_file_equals_golden --diff . <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read target file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: fails with non-openable golden file" { + run assert_file_equals_golden --diff <(print 'a') . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --diff: '--' stops parsing options" { + run assert_file_equals_golden --diff -- <(printf '%s' '--diff') <(printf '%s' '--diff') + + assert_test_pass +} + +# +# assert_file_equals_golden +# Regex matching +# + +@test "assert_file_equals_golden --regexp: succeeds if output and golden match" { + run assert_file_equals_golden --regexp <(printf 'a') <(printf 'a') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds if multiline output and golden match" { + run assert_file_equals_golden --regexp <(printf 'a\nb\nc') <(printf 'a\nb\nc') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds if output and golden match and contain trailing newline" { + run assert_file_equals_golden --regexp <(printf 'a\n') <(printf 'a\n') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds if multiline output and golden match and contain trailing newline" { + run assert_file_equals_golden --regexp <(printf 'a\nb\nc\n') <(printf 'a\nb\nc\n') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: fails if output and golden do not match" { + run assert_file_equals_golden --regexp <(printf 'b') <(printf 'a') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +a +actual file contents (1 lines): +b +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails if output and golden do not match due to extra trailing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'a') <(printf 'a\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +a + +actual file contents (1 lines): +a +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if multiline output and golden do not match due to extra trailing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'a\nb\nc') <(printf 'a\nb\nc\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (3 lines): +a +b +c + +actual file contents (3 lines): +a +b +c +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if output and golden do not match due to extra missing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'a\n') <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +a +actual file contents (1 lines): +a + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if multiline output and golden do not match due to extra missing newline" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'a\nb\nc\n') <(printf 'a\nb\nc') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (3 lines): +a +b +c +actual file contents (3 lines): +a +b +c + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: succeeds if output is newline with newline golden" { + run assert_file_equals_golden --regexp <(printf '\n') <(printf '\n') + + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: fails if output is and golden are empty" { + run assert_file_equals_golden --regexp <(:) <(:) + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file contents is empty. This may be an authoring error. Use `--allow-empty` if this is intentional. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: succeeds if output is and golden are empty when allowed" { + run assert_file_equals_golden --regexp --allow-empty <(:) <(:) + + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: fails if output is newline with non-empty golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf '\n') <(printf 'a') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +a +actual file contents (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if output is newline with allowed empty golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp --allow-empty <(printf '\n') <(:) + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (0 lines): + +actual file contents (1 lines): + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if output is empty with newline golden" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(:) <(printf '\n') + + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): + + +actual file contents (0 lines): + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails with too few parameters" { + run assert_file_equals_golden --regexp + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 0. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with too many parameters" { + run assert_file_equals_golden --regexp a b c + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Incorrect number of arguments: 3. Expected 2 argument. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with empty target file path" { + run assert_file_equals_golden --regexp '' <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with empty golden file path" { + run assert_file_equals_golden --regexp <(print 'a') '' + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file path was not given or it was empty. +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with nonexistent target file" { + run assert_file_equals_golden --regexp some/path/this_file_definitely_does_not_exist.txt <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Target file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with nonexistent golden file" { + run assert_file_equals_golden --regexp <(print 'a') some/path/this_file_definitely_does_not_exist.txt + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Golden file was not found. File path: 'some/path/this_file_definitely_does_not_exist.txt' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with non-openable target file" { + run assert_file_equals_golden --regexp . <(print 'a') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read target file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with non-openable golden file" { + run assert_file_equals_golden --regexp <(print 'a') . + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Failed to read golden file. File path: '.' +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: '--' stops parsing options" { + run assert_file_equals_golden --regexp -- <(printf '%s' '--diff') <(printf '%s' '--diff') + + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with special characters" { + run assert_file_equals_golden --regexp <(printf '[.?+') <(printf '\\[\\.\\?\\+') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with non-specific matching regex" { + run assert_file_equals_golden --regexp <(printf 'a') <(printf '.') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline non-specific exact matching regex" { + run assert_file_equals_golden --regexp <(printf 'a\nb') <(printf '...') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline non-specific greedy matching regex" { + run assert_file_equals_golden --regexp <(printf 'abc\nxyz') <(printf '.*') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline non-specific non-newline matching regex" { + run assert_file_equals_golden --regexp <(printf 'abc\nxyz') <(printf '[^\\n]+\n[^\\n]+') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with specific matching regex" { + run assert_file_equals_golden --regexp <(printf 'a') <(printf '[a]') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline specific matching regex" { + run assert_file_equals_golden --regexp <(printf 'a\nb') <(printf '[a]\n[b]') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline specific repeating matching regex" { + run assert_file_equals_golden --regexp <(printf 'aabbcc\nxxyyzz') <(printf '[abc]+\n[xyz]+') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline specific matching regex with trailing newlines" { + run assert_file_equals_golden --regexp <(printf 'aabbcc\nxxyyzz\n\n') <(printf '[abc]+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline specific matching regex with special characters" { + run assert_file_equals_golden --regexp <(printf 'aabbcc\n[.?+\nxxyyzz') <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline specific matching regex with special characters and trailing newlines" { + run assert_file_equals_golden --regexp <(printf 'aabbcc\n[.?+\nxxyyzz\n\n') <(printf '[abc]+\n\\[\\.\\?\\+\n[xyz]+\n\n') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: succeeds with multiline start-end matching regex" { + run assert_file_equals_golden --regexp <(printf 'abc\ndef\nxyz') <(printf 'abc\n.*xyz') + assert_test_pass +} + +@test "assert_file_equals_golden --regexp: fails with non-specific non-matching regex - too many" { + run assert_file_equals_golden --regexp <(printf 'a') <(printf '..') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +.. +actual file contents (1 lines): +a +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with non-specific non-matching regex - too few" { + run assert_file_equals_golden --regexp <(printf 'ab') <(printf '.') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +. +actual file contents (1 lines): +ab +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with specific non-matching regex" { + run assert_file_equals_golden --regexp <(printf 'a') <(printf '[b]') + + assert_test_fail <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (1 lines): +[b] +actual file contents (1 lines): +a +-- +ERR_MSG +} + +@test "assert_file_equals_golden --regexp: fails with multiline specific matching regex with extra trailing newlines" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'aabbcc\nxxyyzz\n\n') <(printf '[abc]+\n[xyz]+') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix output "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (2 lines): +[abc]+ +[xyz]+ +actual file contents (3 lines): +aabbcc +xxyyzz + + +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails with multiline specific matching regex with missing trailing newlines" { + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf 'aabbcc\nxxyyzz') <(printf '[abc]+\n[xyz]+\n\n') + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat <<'ERR_MSG' + +-- file contents does not match regexp golden -- +golden contents (3 lines): +[abc]+ +[xyz]+ + + +actual file contents (2 lines): +aabbcc +xxyyzz +-- + +ERR_MSG + printf '.')" + expected="${expected%.}" + assert_test_fail "$expected" +} + +@test "assert_file_equals_golden --regexp: fails if regex golden is not a valid extended regular expression" { + run assert_file_equals_golden --regexp <(printf 'abc') <(printf '[.*') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Invalid extended regular expression in golden file: `[.*' +-- +ERR_MSG +} + +# +# assert_file_equals_golden +# Misc Error Handling +# + +@test "assert_file_equals_golden: fails with --regexp --diff" { + run assert_file_equals_golden --regexp --diff <(printf 'abc') <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +`--diff' not supported with `--regexp' +-- +ERR_MSG +} + +@test "assert_file_equals_golden: fails with unknown option" { + run assert_file_equals_golden --not-a-real-option <(printf 'abc') <(printf 'abc') + + assert_test_fail <<'ERR_MSG' + +-- ERROR: assert_file_equals_golden -- +Unsupported flag '--not-a-real-option'. +-- +ERR_MSG +} + # # Automatic golden file updating # @@ -3255,3 +4350,221 @@ ERR_MSG assert_test_pass } + +@test "auto-update: assert_file_equals_golden: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden --regexp: updates golden for failure" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$tested_output" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden --regexp: failure if golden file is not writable" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf 'wrong output' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + chmod a-w "$temp_golden_file" + + tested_output='abc' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail < "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = 'wrong output' ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden --regexp: updates golden for failure multiline with regex and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\njkl\n\nmno\n\n' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden --regexp: updates golden for failure multiline with regex and special chars" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_file_equals_golden --regexp: updates golden for failure multiline with regex, special chars, and trailing newlines" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='abc\ndef\nghi\n].{\njkl\n\nmno\n\n' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]\n\n')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} From 988e355f10ee089f5fc8b1fa18db777d3ed07022 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Mon, 20 May 2024 19:48:50 -0700 Subject: [PATCH 05/23] * Escaping `\` for regexp golden files. * Adding `\` to list of special characters in doc strings. * Adding test cases to cover all special characters with `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE`. * Cleaning up some unnecessary lines in a few existing `assert_equals_golden` tests. --- src/assert_equals_golden.bash | 12 ++--- test/assert_equals_golden.bats | 98 +++++++++++++++++++++++++++------- 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 8695693..2cf3a66 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -78,7 +78,7 @@ # # If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. # This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. -# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# Regular expression special characters (`][\.()*+?{}|^$\\`), when used as literals, must be escaped in the golden file. # The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. # # If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. @@ -266,7 +266,7 @@ assert_equals_golden() { for line_in_output in "${output_lines[@]}"; do # Default the output line itself as the best guess for the new golden. # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" for line_in_golden in "${sorted_golden_lines[@]}"; do if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then # If there's a line from the previous golden output that matches, use that is the best guess instead. @@ -364,7 +364,7 @@ assert_equals_golden() { # # If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. # This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. -# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# Regular expression special characters (`][\.()*+?{}|^$\\`), when used as literals, must be escaped in the golden file. # The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. # # If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. @@ -529,7 +529,7 @@ assert_output_equals_golden() { for line_in_output in "${output_lines[@]}"; do # Default the output line itself as the best guess for the new golden. # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" for line_in_golden in "${sorted_golden_lines[@]}"; do if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then # If there's a line from the previous golden output that matches, use that is the best guess instead. @@ -626,7 +626,7 @@ assert_output_equals_golden() { # # If `--regexp` is given, the golden file contents is treated as a multiline extended regular expression. # This allows for volatile output (e.g. timestamps, identifiers) and/or secrets to be removed from golden files, but still constrained for proper asserting. -# Regular expression special characters (`][\.()*+?{}|^$`), when used as literals, must be escaped in the golden file. +# Regular expression special characters (`][\.()*+?{}|^$\\`), when used as literals, must be escaped in the golden file. # The regular expression golden file contents respects `\n` characters and expressions which span multiple lines. # # If the `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` environment variable is set with `--regexp`, special logic is used to reuse lines where possible. @@ -815,7 +815,7 @@ assert_file_equals_golden() { for line_in_output in "${output_lines[@]}"; do # Default the output line itself as the best guess for the new golden. # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$])/\\\1/g')" + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" for line_in_golden in "${sorted_golden_lines[@]}"; do if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then # If there's a line from the previous golden output that matches, use that is the best guess instead. diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index 0319f5d..68d5770 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -3874,9 +3874,6 @@ ERR_MSG [ "$(cat "$temp_golden_file")" = "$tested_output" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden "$tested_value" "$temp_golden_file" assert_test_pass @@ -3928,9 +3925,6 @@ ERR_MSG [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run --keep-empty-lines printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden "$tested_value" "$temp_golden_file" assert_test_pass @@ -3959,9 +3953,6 @@ ERR_MSG [ "$(cat "$temp_golden_file")" = "$tested_output" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" assert_test_pass @@ -4013,9 +4004,6 @@ ERR_MSG [ "$(cat "$temp_golden_file")" = "$(printf "$tested_output")" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run --keep-empty-lines printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" assert_test_pass @@ -4045,9 +4033,6 @@ ERR_MSG cat "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n[d-l]{3}\n\n[^a].[op]\n\n')" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run --keep-empty-lines printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" assert_test_pass @@ -4077,9 +4062,6 @@ ERR_MSG cat "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]')" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE - run --keep-empty-lines printf "$tested_output" - tested_value="$output" - output='UNUSED' run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" assert_test_pass @@ -4109,11 +4091,37 @@ ERR_MSG cat "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf 'abc\n[d-l]{3}\n[d-l]{3}\n\\]\\.\\{\n[d-l]{3}\n\n[^a].[op]\n\n')" ] unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" + + assert_test_pass +} + +@test "auto-update: assert_equals_golden --regexp: updates golden for failure all special characters" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 tested_value="$output" output='UNUSED' run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '\\[\\]\n\\.\n\\(\\)\n\\*\n\\+\n\\?\n\\{\\}\n\\|\n\\^\n\\$\n\\\\')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" + assert_test_pass } @@ -4351,6 +4359,34 @@ ERR_MSG assert_test_pass } +@test "auto-update: assert_output_equals_golden --regexp: updates golden for failure all special characters" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + + run --keep-empty-lines printf "$tested_output" + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_output_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '\\[\\]\n\\.\n\\(\\)\n\\*\n\\+\n\\?\n\\{\\}\n\\|\n\\^\n\\$\n\\\\')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run --keep-empty-lines printf "$tested_output" + run assert_output_equals_golden --regexp "$temp_golden_file" + + assert_test_pass +} + @test "auto-update: assert_file_equals_golden: updates golden for failure" { temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" [ -f "$temp_golden_file" ] @@ -4568,3 +4604,29 @@ ERR_MSG assert_test_pass } + +@test "auto-update: assert_file_equals_golden --regexp: updates golden for failure all special characters" { + temp_golden_file="$(mktemp -t "bats_test_${BATS_TEST_NUMBER}.XXXXXXXX.txt")" + [ -f "$temp_golden_file" ] + printf '[^a].[op]\n[d-l]{3}' > "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] + + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + + BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_fail <<'ERR_MSG' + +-- FAIL: assert_file_equals_golden -- +Golden file updated after mismatch. +-- +ERR_MSG + + cat "$temp_golden_file" + [ "$(cat "$temp_golden_file")" = "$(printf '\\[\\]\n\\.\n\\(\\)\n\\*\n\\+\n\\?\n\\{\\}\n\\|\n\\^\n\\$\n\\\\')" ] + unset BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE + run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + assert_test_pass +} From 9501659ae2c5b27f269de0225c7b1f28b0715b3d Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Tue, 28 May 2024 00:44:16 -0700 Subject: [PATCH 06/23] * Adding always showing output/golden contents/diff when test fails (even if the golden ends up being updated). * Adding prefix of golden file path before error messages. * Simplifying return status from assert functions. * Updating tests to assert output with new changes. * Adding helper function to save tmp file path used in test cases (to then be used in assertion messages). * Adding a space after `\` in some test cases to handle/workaround `\\\n` in docstrings not being parsed properly by bash. --- src/assert_equals_golden.bash | 135 ++-- test/assert_equals_golden.bats | 1318 +++++++++++++++++++++++++------- 2 files changed, 1112 insertions(+), 341 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 2cf3a66..a1523a0 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -210,25 +210,34 @@ assert_equals_golden() { fi if (( assert_failed )); then - if ! (( update_goldens_on_failure )); then - if (( show_diff )); then - diff <(echo "$value") <(echo "$golden_file_contents") \ - | batslib_decorate 'value does not match golden' \ - | fail - elif (( is_mode_regexp )); then - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual value' "$value" \ - | batslib_decorate 'value does not match regexp golden' \ - | fail - else + if (( show_diff )); then + { + echo "Golden file: $golden_file_path" + diff <(echo "$value") <(echo "$golden_file_contents") + } \ + | batslib_decorate 'value does not match golden' \ + | fail + elif (( is_mode_regexp )); then + { + echo "Golden file: $golden_file_path" batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual value' "$value" \ - | batslib_decorate 'value does not match golden' \ - | fail - fi + 'golden contents' "$golden_file_contents" \ + 'actual value' "$value" + } \ + | batslib_decorate 'value does not match regexp golden' \ + | fail else + { + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual value' "$value" + } \ + | batslib_decorate 'value does not match golden' \ + | fail + fi + + if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then # Non-regex golden update is straight forward. printf '%s' "$value" 2>/dev/null > "$golden_file_path" @@ -284,9 +293,9 @@ assert_equals_golden() { echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_equals_golden' \ | fail - return $? fi fi + return $assert_failed } # assert_output_equals_golden @@ -473,25 +482,34 @@ assert_output_equals_golden() { fi if (( assert_failed )); then - if ! (( update_goldens_on_failure )); then - if (( show_diff )); then - diff <(echo "$output") <(echo "$golden_file_contents") \ - | batslib_decorate 'output does not match golden' \ - | fail - elif (( is_mode_regexp )); then - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" \ - | batslib_decorate 'output does not match regexp golden' \ - | fail - else + if (( show_diff )); then + { + echo "Golden file: $golden_file_path" + diff <(echo "$output") <(echo "$golden_file_contents") + } \ + | batslib_decorate 'output does not match golden' \ + | fail + elif (( is_mode_regexp )); then + { + echo "Golden file: $golden_file_path" batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" \ - | batslib_decorate 'output does not match golden' \ - | fail - fi + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" + } \ + | batslib_decorate 'output does not match regexp golden' \ + | fail else + { + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual output' "$output" + } \ + | batslib_decorate 'output does not match golden' \ + | fail + fi + + if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then # Non-regex golden update is straight forward. printf '%s' "$output" 2>/dev/null > "$golden_file_path" @@ -547,9 +565,9 @@ assert_output_equals_golden() { echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_output_equals_golden' \ | fail - return $? fi fi + return $assert_failed } # assert_file_equals_golden @@ -759,25 +777,34 @@ assert_file_equals_golden() { fi if (( assert_failed )); then - if ! (( update_goldens_on_failure )); then - if (( show_diff )); then - diff <(echo "$target_file_contents") <(echo "$golden_file_contents") \ - | batslib_decorate 'file contents does not match golden' \ - | fail - elif (( is_mode_regexp )); then - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual file contents' "$target_file_contents" \ - | batslib_decorate 'file contents does not match regexp golden' \ - | fail - else + if (( show_diff )); then + { + echo "Golden file: $golden_file_path" + diff <(echo "$target_file_contents") <(echo "$golden_file_contents") + } \ + | batslib_decorate 'file contents does not match golden' \ + | fail + elif (( is_mode_regexp )); then + { + echo "Golden file: $golden_file_path" batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual file contents' "$target_file_contents" \ - | batslib_decorate 'file contents does not match golden' \ - | fail - fi + 'golden contents' "$golden_file_contents" \ + 'actual file contents' "$target_file_contents" + } \ + | batslib_decorate 'file contents does not match regexp golden' \ + | fail else + { + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + 'actual file contents' "$target_file_contents" + } \ + | batslib_decorate 'file contents does not match golden' \ + | fail + fi + + if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then # Non-regex golden update is straight forward. printf '%s' "$target_file_contents" 2>/dev/null > "$golden_file_path" @@ -833,7 +860,7 @@ assert_file_equals_golden() { echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_file_equals_golden' \ | fail - return $? fi fi + return $assert_failed } diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index 68d5770..89a920f 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -4,6 +4,15 @@ load test_helper bats_require_minimum_version 1.5.0 +test_temp_golden_file='' +save_temp_file_path_and_run() { + local -r temp_file_arg="$#" + + test_temp_golden_file="${!temp_file_arg}" + + run "$@" +} + # # assert_equals_golden # Literal matching @@ -45,11 +54,12 @@ bats_require_minimum_version 1.5.0 run printf 'b' tested_value="$output" output='UNUSED' - run assert_equals_golden "$tested_value" <(printf 'a') + save_temp_file_path_and_run assert_equals_golden "$tested_value" <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -906,11 +941,12 @@ ERR_MSG run printf 'a\nb\nc' tested_value="$output" output='UNUSED' - run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc\n') + save_temp_file_path_and_run assert_equals_golden --diff "$tested_value" <(printf 'a\nb\nc\n') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -921,11 +957,12 @@ ERR_MSG run --keep-empty-lines printf 'a\n' tested_value="$output" output='UNUSED' - run assert_equals_golden --diff "$tested_value" <(printf 'a') + save_temp_file_path_and_run assert_equals_golden --diff "$tested_value" <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -1129,11 +1170,12 @@ ERR_MSG run printf 'b' tested_value="$output" output='UNUSED' - run assert_equals_golden --regexp "$tested_value" <(printf 'a') + save_temp_file_path_and_run assert_equals_golden --regexp "$tested_value" <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -2078,11 +2145,12 @@ ERR_MSG @test "assert_output_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { run printf 'a\nb\nc' - run assert_output_equals_golden --diff <(printf 'a\nb\nc\n') + save_temp_file_path_and_run assert_output_equals_golden --diff <(printf 'a\nb\nc\n') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -2091,11 +2159,12 @@ ERR_MSG @test "assert_output_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { run --keep-empty-lines printf 'a\n' - run assert_output_equals_golden --diff <(printf 'a') + save_temp_file_path_and_run assert_output_equals_golden --diff <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -2276,11 +2349,12 @@ ERR_MSG @test "assert_output_equals_golden --regexp: fails if output and golden do not match" { run printf 'b' - run assert_output_equals_golden --regexp <(printf 'a') + save_temp_file_path_and_run assert_output_equals_golden --regexp <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -3149,11 +3247,12 @@ ERR_MSG } @test "assert_file_equals_golden --diff: fails if multiline output and golden do not match due to extra trailing newline" { - run assert_file_equals_golden --diff <(printf 'a\nb\nc') <(printf 'a\nb\nc\n') + save_temp_file_path_and_run assert_file_equals_golden --diff <(printf 'a\nb\nc') <(printf 'a\nb\nc\n') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -3161,11 +3260,12 @@ ERR_MSG } @test "assert_file_equals_golden --diff: fails if output and golden do not match due to extra missing newline" { - run assert_file_equals_golden --diff <(printf 'a\n') <(printf 'a') + save_temp_file_path_and_run assert_file_equals_golden --diff <(printf 'a\n') <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < -- @@ -3366,11 +3470,12 @@ ERR_MSG } @test "assert_file_equals_golden --regexp: fails if output and golden do not match" { - run assert_file_equals_golden --regexp <(printf 'b') <(printf 'a') + save_temp_file_path_and_run assert_file_equals_golden --regexp <(printf 'b') <(printf 'a') - assert_test_fail <<'ERR_MSG' + assert_test_fail < "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] - tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\ ' run --keep-empty-lines printf "$tested_output" BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 tested_value="$output" output='UNUSED' - run assert_equals_golden --regexp "$tested_value" "$temp_golden_file" + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_equals_golden --regexp "$tested_value" "$temp_golden_file" + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat < "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] - tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\ ' run --keep-empty-lines printf "$tested_output" BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 - run assert_output_equals_golden --regexp "$temp_golden_file" + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_output_equals_golden --regexp "$temp_golden_file" + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat < "$temp_golden_file" [ "$(cat "$temp_golden_file")" = "$(printf '[^a].[op]\n[d-l]{3}')" ] - tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\' + tested_output='[]\n.\n()\n*\n+\n?\n{}\n|\n^\n$\n\\ ' BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE=1 - run assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + # Need to use `--keep-empty-lines` so that `${#lines[@]}` and `num_lines` can match in `assert_test_fail`. + run --keep-empty-lines assert_file_equals_golden --regexp <(printf "$tested_output") "$temp_golden_file" + + # TODO(https://github.com/bats-core/bats-support/issues/11): Fix golden "lines" count in expected message. + # Need to use variable to match trailing end lines caused by using `--keep-empty-lines`. + expected="$(cat < Date: Sun, 24 Aug 2025 10:18:55 -0700 Subject: [PATCH 07/23] * Checking `BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE` more consistently; set to 1 if set at all. --- src/assert_equals_golden.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index a1523a0..9e1c80e 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -434,7 +434,7 @@ assert_output_equals_golden() { fi local -r golden_file_path="${1-}" - local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:-0}" + local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" if [ -z "$golden_file_path" ]; then echo "Golden file path was not given or it was empty." \ @@ -705,7 +705,7 @@ assert_file_equals_golden() { local -r target_file_path="${1-}" local -r golden_file_path="${2-}" - local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:-0}" + local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" if [ -z "$target_file_path" ]; then echo "Target file path was not given or it was empty." \ From 1c89b79a288db5fb5fd1ce485073234c7c8c07e4 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 10:37:43 -0700 Subject: [PATCH 08/23] * Consolidate update golden logic into helper functions. --- src/assert_equals_golden.bash | 216 +++++++++++----------------------- 1 file changed, 69 insertions(+), 147 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 9e1c80e..0b7c2dc 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -239,56 +239,9 @@ assert_equals_golden() { if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - # Non-regex golden update is straight forward. - printf '%s' "$value" 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_equals_golden' \ - | fail - return $? - fi + _assert_golden_update_golden_file_contents_nonregexp 'assert_equals_golden' "$value" "$golden_file_path" else - # To do a best-approximation for regex goldens, - # try and use existing lines as a library for updated lines (preferring longer lines). - # This is done line by line on the asserted value. - # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). - # Any line guess which is not preferred can be manually corrected/updated by the author. - local -a output_lines=() - local -a sorted_golden_lines=() - local temp= - while IFS='' read -r temp; do - output_lines+=("$temp") - done < <(printf '%s' "$value" ; printf '\n') - while IFS='' read -r temp; do - sorted_golden_lines+=("$temp") - done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') - # First, clear out the golden file's contents (so new data can just be appended below). - : 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_equals_golden' \ - | fail - return $? - fi - # Go line by line over the output, looking for the best suggested replacement. - local best_guess_for_line= - for line_in_output in "${output_lines[@]}"; do - # Default the output line itself as the best guess for the new golden. - # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" - for line_in_golden in "${sorted_golden_lines[@]}"; do - if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then - # If there's a line from the previous golden output that matches, use that is the best guess instead. - # No need to escape special characters, as `line_in_golden` is already in proper form. - best_guess_for_line="$line_in_golden" - break - fi - done - if [ -s "$golden_file_path" ]; then - printf '\n' >> "$golden_file_path" - fi - printf '%s' "$best_guess_for_line" >> "$golden_file_path" - done + _assert_golden_update_golden_file_contents_regexp 'assert_equals_golden' "$value" "$golden_file_path" fi echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_equals_golden' \ @@ -511,56 +464,9 @@ assert_output_equals_golden() { if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - # Non-regex golden update is straight forward. - printf '%s' "$output" 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_output_equals_golden' \ - | fail - return $? - fi + _assert_golden_update_golden_file_contents_nonregexp 'assert_output_equals_golden' "$output" "$golden_file_path" else - # To do a best-approximation for regex goldens, - # try and use existing lines as a library for updated lines (preferring longer lines). - # This is done line by line on the output. - # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). - # Any line guess which is not preferred can be manually corrected/updated by the author. - local -a output_lines=() - local -a sorted_golden_lines=() - local temp= - while IFS='' read -r temp; do - output_lines+=("$temp") - done < <(printf '%s' "$output" ; printf '\n') - while IFS='' read -r temp; do - sorted_golden_lines+=("$temp") - done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') - # First, clear out the golden file's contents (so new data can just be appended below). - : 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_output_equals_golden' \ - | fail - return $? - fi - # Go line by line over the output, looking for the best suggested replacement. - local best_guess_for_line= - for line_in_output in "${output_lines[@]}"; do - # Default the output line itself as the best guess for the new golden. - # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" - for line_in_golden in "${sorted_golden_lines[@]}"; do - if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then - # If there's a line from the previous golden output that matches, use that is the best guess instead. - # No need to escape special characters, as `line_in_golden` is already in proper form. - best_guess_for_line="$line_in_golden" - break - fi - done - if [ -s "$golden_file_path" ]; then - printf '\n' >> "$golden_file_path" - fi - printf '%s' "$best_guess_for_line" >> "$golden_file_path" - done + _assert_golden_update_golden_file_contents_regexp 'assert_output_equals_golden' "$output" "$golden_file_path" fi echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_output_equals_golden' \ @@ -806,56 +712,9 @@ assert_file_equals_golden() { if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - # Non-regex golden update is straight forward. - printf '%s' "$target_file_contents" 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_file_equals_golden' \ - | fail - return $? - fi + _assert_golden_update_golden_file_contents_nonregexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" else - # To do a best-approximation for regex goldens, - # try and use existing lines as a library for updated lines (preferring longer lines). - # This is done line by line on the output. - # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). - # Any line guess which is not preferred can be manually corrected/updated by the author. - local -a output_lines=() - local -a sorted_golden_lines=() - local temp= - while IFS='' read -r temp; do - output_lines+=("$temp") - done < <(printf '%s' "$target_file_contents" ; printf '\n') - while IFS='' read -r temp; do - sorted_golden_lines+=("$temp") - done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') - # First, clear out the golden file's contents (so new data can just be appended below). - : 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then - echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate 'FAIL: assert_file_equals_golden' \ - | fail - return $? - fi - # Go line by line over the output, looking for the best suggested replacement. - local best_guess_for_line= - for line_in_output in "${output_lines[@]}"; do - # Default the output line itself as the best guess for the new golden. - # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" - for line_in_golden in "${sorted_golden_lines[@]}"; do - if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then - # If there's a line from the previous golden output that matches, use that is the best guess instead. - # No need to escape special characters, as `line_in_golden` is already in proper form. - best_guess_for_line="$line_in_golden" - break - fi - done - if [ -s "$golden_file_path" ]; then - printf '\n' >> "$golden_file_path" - fi - printf '%s' "$best_guess_for_line" >> "$golden_file_path" - done + _assert_golden_update_golden_file_contents_regexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" fi echo "Golden file updated after mismatch." \ | batslib_decorate 'FAIL: assert_file_equals_golden' \ @@ -864,3 +723,66 @@ assert_file_equals_golden() { fi return $assert_failed } + +_assert_golden_update_golden_file_contents_nonregexp() { + local -r assert_function_name="$1" + local -r new_golden_contents="$2" + local -r golden_file_path="$3" + + # Non-regex golden update is straight forward. + printf '%s' "$new_golden_contents" 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate "FAIL: $assert_function_name" \ + | fail + return $? + fi +} + +_assert_golden_update_golden_file_contents_regexp() { + local -r assert_function_name="$1" + local -r new_golden_contents="$2" + local -r golden_file_path="$3" + + # To do a best-approximation for regex goldens, + # try and use existing lines as a library for updated lines (preferring longer lines). + # This is done line by line on the output. + # Unfortunately, this does not handle multi-line regex in the golden (e.g. `(.*\n){10}`). + # Any line guess which is not preferred can be manually corrected/updated by the author. + local -a output_lines=() + local -a sorted_golden_lines=() + local temp= + while IFS='' read -r temp; do + output_lines+=("$temp") + done < <(printf '%s' "$new_golden_contents" ; printf '\n') + while IFS='' read -r temp; do + sorted_golden_lines+=("$temp") + done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') + # First, clear out the golden file's contents (so new data can just be appended below). + : 2>/dev/null > "$golden_file_path" + if [[ $? -ne 0 ]]; then + echo "Failed to write into golden file during update: '$golden_file_path'." \ + | batslib_decorate "FAIL: $assert_function_name" \ + | fail + return $? + fi + # Go line by line over the output, looking for the best suggested replacement. + local best_guess_for_line= + for line_in_output in "${output_lines[@]}"; do + # Default the output line itself as the best guess for the new golden. + # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" + for line_in_golden in "${sorted_golden_lines[@]}"; do + if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then + # If there's a line from the previous golden output that matches, use that is the best guess instead. + # No need to escape special characters, as `line_in_golden` is already in proper form. + best_guess_for_line="$line_in_golden" + break + fi + done + if [ -s "$golden_file_path" ]; then + printf '\n' >> "$golden_file_path" + fi + printf '%s' "$best_guess_for_line" >> "$golden_file_path" + done +} From 0b0f559a56584bf8e97dd8047bdf2d7f0fc14b95 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 10:45:15 -0700 Subject: [PATCH 09/23] * Simplifying some logic and properly putting fail-able calls into `if` (to work appropriately with `set -e`). --- src/assert_equals_golden.bash | 55 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 0b7c2dc..813557f 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -730,12 +730,10 @@ _assert_golden_update_golden_file_contents_nonregexp() { local -r golden_file_path="$3" # Non-regex golden update is straight forward. - printf '%s' "$new_golden_contents" 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then + # Write the contents to the golden file (and check for write errors). + if ! printf '%s' "$new_golden_contents" 2>/dev/null > "$golden_file_path"; then echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate "FAIL: $assert_function_name" \ - | fail - return $? + | batslib_decorate "FAIL: $assert_function_name" fi } @@ -758,31 +756,30 @@ _assert_golden_update_golden_file_contents_regexp() { while IFS='' read -r temp; do sorted_golden_lines+=("$temp") done < <(echo "$golden_file_contents" | awk '{ print length, $0 }' | sort -nrs | cut -d" " -f 2- ; printf '\n') - # First, clear out the golden file's contents (so new data can just be appended below). - : 2>/dev/null > "$golden_file_path" - if [[ $? -ne 0 ]]; then + + # First, clear out the golden file's contents so new data can just be appended below (and check for write errors). + if ! : 2>/dev/null > "$golden_file_path"; then echo "Failed to write into golden file during update: '$golden_file_path'." \ - | batslib_decorate "FAIL: $assert_function_name" \ - | fail - return $? - fi - # Go line by line over the output, looking for the best suggested replacement. - local best_guess_for_line= - for line_in_output in "${output_lines[@]}"; do - # Default the output line itself as the best guess for the new golden. - # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). - best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" - for line_in_golden in "${sorted_golden_lines[@]}"; do - if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then - # If there's a line from the previous golden output that matches, use that is the best guess instead. - # No need to escape special characters, as `line_in_golden` is already in proper form. - best_guess_for_line="$line_in_golden" - break + | batslib_decorate "FAIL: $assert_function_name" + else + # Go line by line over the output, looking for the best suggested replacement. + local best_guess_for_line= + for line_in_output in "${output_lines[@]}"; do + # Default the output line itself as the best guess for the new golden. + # Though, the output line needs to be properly escaped for when being used in regex matching (on subsequent runs of the test). + best_guess_for_line="$(echo "$line_in_output" | sed -E 's/([][\.()*+?{}|^$\\])/\\\1/g')" + for line_in_golden in "${sorted_golden_lines[@]}"; do + if [[ "$line_in_output" =~ ^${line_in_golden}$ ]]; then + # If there's a line from the previous golden output that matches, use that is the best guess instead. + # No need to escape special characters, as `line_in_golden` is already in proper form. + best_guess_for_line="$line_in_golden" + break + fi + done + if [ -s "$golden_file_path" ]; then + printf '\n' >> "$golden_file_path" fi + printf '%s' "$best_guess_for_line" >> "$golden_file_path" done - if [ -s "$golden_file_path" ]; then - printf '\n' >> "$golden_file_path" - fi - printf '%s' "$best_guess_for_line" >> "$golden_file_path" - done + fi } From 406315defa30776fac7926bad3d8b87c47eb5b21 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 14:22:29 -0700 Subject: [PATCH 10/23] * Consolidating print logic for common validation (checking arg count, compatible args, file paths, etc) into helper functions. --- src/assert_equals_golden.bash | 127 +++++++++++++++------------------- 1 file changed, 54 insertions(+), 73 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 813557f..3723255 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -134,22 +134,16 @@ assert_equals_golden() { done if (( use_stdin_set_by_opt )) && [ $# -ne 1 ]; then - echo "Incorrect number of arguments: $#. Using stdin, expecting 1 argument." \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + _assert_golden_print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 1 + return 1 elif (( ! use_stdin_set_by_opt )) && [ $# -ne 2 ] ; then - echo "Incorrect number of arguments: $#. Expected 2 arguments." \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + _assert_golden_print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 2 + return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - echo "\`--diff' not supported with \`--regexp'" \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + _assert_golden_print_diff_regexp_incompat_msg 'assert_equals_golden' + return 1 fi local value="$1" @@ -164,17 +158,8 @@ assert_equals_golden() { local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if [ -z "$golden_file_path" ]; then - echo "Golden file path was not given or it was empty." \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? - fi - if [ ! -e "$golden_file_path" ]; then - echo "Golden file was not found. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + if ! _assert_golden_validate_file_path 'assert_equals_golden' 'Golden file' "$golden_file_path"; then + return 1 fi local golden_file_contents= @@ -373,33 +358,20 @@ assert_output_equals_golden() { done if [ $# -ne 1 ]; then - echo "Incorrect number of arguments: $#. Expected 1 argument." \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + _assert_golden_print_incorrect_number_of_arguments_msg 'assert_output_equals_golden' "$#" 1 + return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - echo "\`--diff' not supported with \`--regexp'" \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + _assert_golden_print_diff_regexp_incompat_msg 'assert_output_equals_golden' + return 1 fi local -r golden_file_path="${1-}" local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if [ -z "$golden_file_path" ]; then - echo "Golden file path was not given or it was empty." \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? - fi - if [ ! -e "$golden_file_path" ]; then - echo "Golden file was not found. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + if ! _assert_golden_validate_file_path 'assert_output_equals_golden' 'Golden file' "$golden_file_path"; then + return 1 fi local golden_file_contents= @@ -596,46 +568,22 @@ assert_file_equals_golden() { done if [ $# -ne 2 ]; then - echo "Incorrect number of arguments: $#. Expected 2 argument." \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + _assert_golden_print_incorrect_number_of_arguments_msg 'assert_file_equals_golden' "$#" 2 + return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - echo "\`--diff' not supported with \`--regexp'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + _assert_golden_print_diff_regexp_incompat_msg 'assert_file_equals_golden' + return 1 fi local -r target_file_path="${1-}" local -r golden_file_path="${2-}" local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if [ -z "$target_file_path" ]; then - echo "Target file path was not given or it was empty." \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? - fi - if [ ! -e "$target_file_path" ]; then - echo "Target file was not found. File path: '$target_file_path'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? - fi - if [ -z "$golden_file_path" ]; then - echo "Golden file path was not given or it was empty." \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? - fi - if [ ! -e "$golden_file_path" ]; then - echo "Golden file was not found. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + if ! _assert_golden_validate_file_path 'assert_file_equals_golden' 'Target file' "$target_file_path" \ + && _assert_golden_validate_file_path 'assert_file_equals_golden' 'Golden file' "$golden_file_path"; then + return 1 fi local target_file_contents= @@ -724,6 +672,39 @@ assert_file_equals_golden() { return $assert_failed } +_assert_golden_print_incorrect_number_of_arguments_msg() { + local -r assert_function_name="$1" + local -r -i actual_arg_count="$2" + local -r -i expected_arg_count="$3" + + echo "Incorrect number of arguments: $actual_arg_count. Expected $expected_arg_count argument." \ + | batslib_decorate "ERROR: $assert_function_name" +} + +_assert_golden_print_diff_regexp_incompat_msg() { + local -r assert_function_name="$1" + + echo "\`--diff' not supported with \`--regexp'" \ + | batslib_decorate "ERROR: $assert_function_name" +} + +_assert_golden_validate_file_path() { + local -r assert_function_name="$1" + local -r file_description="$2" + local -r file_path="$3" + + if [ -z "$file_path" ]; then + echo "$file_description path was not given or it was empty." \ + | batslib_decorate "ERROR: $assert_function_name" + return 1 + fi + if [ ! -e "$file_path" ]; then + echo "$file_description was not found. File path: '$file_path'" \ + | batslib_decorate "ERROR: $assert_function_name" + return 1 + fi +} + _assert_golden_update_golden_file_contents_nonregexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" From f39cf1579f24e2edb691823d2e5da14e39622deb Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 14:47:19 -0700 Subject: [PATCH 11/23] * Consolidating reading of golden file contents into helper function. --- src/assert_equals_golden.bash | 74 ++++++++++++++--------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 3723255..6cf73b0 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -163,21 +163,8 @@ assert_equals_golden() { fi local golden_file_contents= - # Load the contents from the file. - # Append a period (to be removed on the next line) so that trailing new lines are preserved. - golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" - if (( $? != 0 )); then - echo "Failed to read golden file. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? - fi - golden_file_contents="${golden_file_contents%.}" - if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then - echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_equals_golden' "$golden_file_path")"; then + return 1 fi local -i assert_failed=0 @@ -375,21 +362,8 @@ assert_output_equals_golden() { fi local golden_file_contents= - # Load the contents from the file. - # Append a period (to be removed on the next line) so that trailing new lines are preserved. - golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" - if [ $? -ne 0 ]; then - echo "Failed to read golden file. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? - fi - golden_file_contents="${golden_file_contents%.}" - if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then - echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path")"; then + return 1 fi local -i assert_failed=0 @@ -599,21 +573,8 @@ assert_file_equals_golden() { target_file_contents="${target_file_contents%.}" local golden_file_contents= - # Load the contents from the file. - # Append a period (to be removed on the next line) so that trailing new lines are preserved. - golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" - if [ $? -ne 0 ]; then - echo "Failed to read golden file. File path: '$golden_file_path'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? - fi - golden_file_contents="${golden_file_contents%.}" - if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then - echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path")"; then + return 1 fi local -i assert_failed=0 @@ -705,6 +666,29 @@ _assert_golden_validate_file_path() { fi } +_assert_golden_read_golden_file_contents() { + local -r assert_function_name="$1" + local -r golden_file_path="$2" + + local golden_file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" + if [ $? -ne 0 ]; then + echo "Failed to read golden file. File path: '$golden_file_path'" \ + | batslib_decorate "ERROR: $assert_function_name" >&2 + return 1 + fi + golden_file_contents="${golden_file_contents%.}" + if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then + echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ + | batslib_decorate "ERROR: $assert_function_name" >&2 + return 1 + fi + + printf '%s' "$golden_file_contents" +} + _assert_golden_update_golden_file_contents_nonregexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" From a1e85b6d064a234db8017e535358781002d6f1fe Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 15:13:15 -0700 Subject: [PATCH 12/23] * Consolidating invalid regexp error message into helper function. * Message no longer prints contents (as it will be printed after). * No longer performs early return. * Still prints full assertion message and optionally does golden update (when enabled). --- src/assert_equals_golden.bash | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 6cf73b0..c010f28 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -170,10 +170,8 @@ assert_equals_golden() { local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + _assert_golden_print_invalid_extended_regular_expression_msg 'assert_equals_golden' + assert_failed=1 elif ! [[ "$value" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -369,10 +367,8 @@ assert_output_equals_golden() { local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + _assert_golden_print_invalid_extended_regular_expression_msg 'assert_output_equals_golden' + assert_failed=1 elif ! [[ "$output" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -580,10 +576,8 @@ assert_file_equals_golden() { local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - echo "Invalid extended regular expression in golden file: \`$golden_file_contents'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + _assert_golden_print_invalid_extended_regular_expression_msg 'assert_file_equals_golden' + assert_failed=1 elif ! [[ "$target_file_contents" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -689,6 +683,12 @@ _assert_golden_read_golden_file_contents() { printf '%s' "$golden_file_contents" } +_assert_golden_print_invalid_extended_regular_expression_msg() { + local -r assert_function_name="$1" + echo "Invalid extended regular expression in golden file." \ + | batslib_decorate "ERROR: $assert_function_name" +} + _assert_golden_update_golden_file_contents_nonregexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" From 3dc0396c3b56142a74ce3500785164545d6e302b Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 15:53:08 -0700 Subject: [PATCH 13/23] * Properly passing `allow_empty` flag into `_assert_golden_read_golden_file_contents`. * Consolidating all assertion error messages into helper functions. * Consolidating all updated golden messages into helper function. * Creating `_assert_golden_read_file_contents` general function. * `_assert_golden_read_golden_file_contents` now uses `_assert_golden_read_file_contents` (consolidated logic). * Updating `assert_file_equals_golden` to use `_assert_golden_read_file_contents`. --- src/assert_equals_golden.bash | 184 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 94 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index c010f28..b832b9e 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -163,7 +163,7 @@ assert_equals_golden() { fi local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_equals_golden' "$golden_file_path")"; then + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi @@ -181,30 +181,11 @@ assert_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - { - echo "Golden file: $golden_file_path" - diff <(echo "$value") <(echo "$golden_file_contents") - } \ - | batslib_decorate 'value does not match golden' \ - | fail + _assert_golden_print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_contents" elif (( is_mode_regexp )); then - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual value' "$value" - } \ - | batslib_decorate 'value does not match regexp golden' \ - | fail + _assert_golden_print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" else - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual value' "$value" - } \ - | batslib_decorate 'value does not match golden' \ - | fail + _assert_golden_print_not_matching_whole_contents_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -213,9 +194,7 @@ assert_equals_golden() { else _assert_golden_update_golden_file_contents_regexp 'assert_equals_golden' "$value" "$golden_file_path" fi - echo "Golden file updated after mismatch." \ - | batslib_decorate 'FAIL: assert_equals_golden' \ - | fail + _assert_golden_print_updated_golden_file_msg 'assert_equals_golden' fi fi return $assert_failed @@ -360,7 +339,7 @@ assert_output_equals_golden() { fi local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path")"; then + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi @@ -378,30 +357,11 @@ assert_output_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - { - echo "Golden file: $golden_file_path" - diff <(echo "$output") <(echo "$golden_file_contents") - } \ - | batslib_decorate 'output does not match golden' \ - | fail + _assert_golden_print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_contents" elif (( is_mode_regexp )); then - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" - } \ - | batslib_decorate 'output does not match regexp golden' \ - | fail + _assert_golden_print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" else - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual output' "$output" - } \ - | batslib_decorate 'output does not match golden' \ - | fail + _assert_golden_print_not_matching_whole_contents_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -410,9 +370,7 @@ assert_output_equals_golden() { else _assert_golden_update_golden_file_contents_regexp 'assert_output_equals_golden' "$output" "$golden_file_path" fi - echo "Golden file updated after mismatch." \ - | batslib_decorate 'FAIL: assert_output_equals_golden' \ - | fail + _assert_golden_print_updated_golden_file_msg 'assert_output_equals_golden' fi fi return $assert_failed @@ -557,19 +515,12 @@ assert_file_equals_golden() { fi local target_file_contents= - # Load the contents from the file. - # Append a period (to be removed on the next line) so that trailing new lines are preserved. - target_file_contents="$(cat "$target_file_path" 2>/dev/null && printf '.')" - if [ $? -ne 0 ]; then - echo "Failed to read target file. File path: '$target_file_path'" \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + if ! target_file_contents="$(_assert_golden_read_file_contents 'assert_file_equals_golden' 'target file' "$target_file_path")"; then + return 1 fi - target_file_contents="${target_file_contents%.}" local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path")"; then + if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi @@ -587,30 +538,11 @@ assert_file_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - { - echo "Golden file: $golden_file_path" - diff <(echo "$target_file_contents") <(echo "$golden_file_contents") - } \ - | batslib_decorate 'file contents does not match golden' \ - | fail + _assert_golden_print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_contents" elif (( is_mode_regexp )); then - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual file contents' "$target_file_contents" - } \ - | batslib_decorate 'file contents does not match regexp golden' \ - | fail + _assert_golden_print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$outarget_file_contentstput" "$golden_file_path" "$golden_file_contents" else - { - echo "Golden file: $golden_file_path" - batslib_print_kv_multi \ - 'golden contents' "$golden_file_contents" \ - 'actual file contents' "$target_file_contents" - } \ - | batslib_decorate 'file contents does not match golden' \ - | fail + _assert_golden_print_not_matching_whole_contents_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -619,9 +551,7 @@ assert_file_equals_golden() { else _assert_golden_update_golden_file_contents_regexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" fi - echo "Golden file updated after mismatch." \ - | batslib_decorate 'FAIL: assert_file_equals_golden' \ - | fail + _assert_golden_print_updated_golden_file_msg 'assert_file_equals_golden' fi fi return $assert_failed @@ -663,17 +593,12 @@ _assert_golden_validate_file_path() { _assert_golden_read_golden_file_contents() { local -r assert_function_name="$1" local -r golden_file_path="$2" + local -r -i allow_empty="$3" local golden_file_contents= - # Load the contents from the file. - # Append a period (to be removed on the next line) so that trailing new lines are preserved. - golden_file_contents="$(cat "$golden_file_path" 2>/dev/null && printf '.')" - if [ $? -ne 0 ]; then - echo "Failed to read golden file. File path: '$golden_file_path'" \ - | batslib_decorate "ERROR: $assert_function_name" >&2 + if ! golden_file_contents="$(_assert_golden_read_file_contents "$assert_function_name" 'golden file' "$golden_file_path")"; then return 1 fi - golden_file_contents="${golden_file_contents%.}" if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ | batslib_decorate "ERROR: $assert_function_name" >&2 @@ -683,12 +608,76 @@ _assert_golden_read_golden_file_contents() { printf '%s' "$golden_file_contents" } +_assert_golden_read_file_contents() { + local -r assert_function_name="$1" + local -r file_description="$2" + local -r file_path="$3" + + local file_contents= + # Load the contents from the file. + # Append a period (to be removed on the next line) so that trailing new lines are preserved. + file_contents="$(cat "$file_path" 2>/dev/null && printf '.')" + if [ $? -ne 0 ]; then + echo "Failed to read ${file_description}. File path: '$file_path'" \ + | batslib_decorate "ERROR: $assert_function_name" >&2 + return 1 + fi + file_contents="${file_contents%.}" + + printf '%s' "$file_contents" +} + _assert_golden_print_invalid_extended_regular_expression_msg() { local -r assert_function_name="$1" echo "Invalid extended regular expression in golden file." \ | batslib_decorate "ERROR: $assert_function_name" } +_assert_golden_print_not_matching_show_diff_msg() { + local -r assert_function_name="$1" + local -r contents_description="$2" + local -r actual_contents="$3" + local -r golden_file_path="$4" + + { + echo "Golden file: $golden_file_path" + diff <(echo "$actual_contents") <(echo "$golden_file_contents") + } \ + | batslib_decorate "${assert_function_name}: $contents_description does not match golden" +} + +_assert_golden_print_not_matching_regexp_msg() { + local -r assert_function_name="$1" + local -r contents_description="$2" + local -r actual_contents="$3" + local -r golden_file_path="$4" + local -r golden_file_contents="$5" + + { + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + "actual $contents_description" "$actual_contents" + } \ + | batslib_decorate "${assert_function_name}: $contents_description does not match regexp golden" +} + +_assert_golden_print_not_matching_whole_contents_msg() { + local -r assert_function_name="$1" + local -r contents_description="$2" + local -r actual_contents="$3" + local -r golden_file_path="$4" + local -r golden_file_contents="$5" + + { + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" \ + "actual $contents_description" "$actual_contents" + } \ + | batslib_decorate "${assert_function_name}: $contents_description does not match golden" +} + _assert_golden_update_golden_file_contents_nonregexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" @@ -748,3 +737,10 @@ _assert_golden_update_golden_file_contents_regexp() { done fi } + +_assert_golden_print_updated_golden_file_msg() { + local -r assert_function_name="$1" + + echo "Golden file updated after mismatch." \ + | batslib_decorate "FAIL: $assert_function_name" +} From 4f40bd397399bacaa94cba746003e6dd6c5d1392 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 15:57:10 -0700 Subject: [PATCH 14/23] * Fixing more `return`s. * Fixing more fail-able commands by putting directly in `if`. --- src/assert_equals_golden.bash | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index b832b9e..d4724ad 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -123,9 +123,8 @@ assert_equals_golden() { ;; --*=|-*) echo "Unsupported flag '$1'." \ - | batslib_decorate 'ERROR: assert_equals_golden' \ - | fail - return $? + | batslib_decorate 'ERROR: assert_equals_golden' + return 1 ;; *) break @@ -311,9 +310,8 @@ assert_output_equals_golden() { ;; --*=|-*) echo "Unsupported flag '$1'." \ - | batslib_decorate 'ERROR: assert_output_equals_golden' \ - | fail - return $? + | batslib_decorate 'ERROR: assert_output_equals_golden' + return 1 ;; *) break @@ -485,9 +483,8 @@ assert_file_equals_golden() { ;; --*=|-*) echo "Unsupported flag '$1'." \ - | batslib_decorate 'ERROR: assert_file_equals_golden' \ - | fail - return $? + | batslib_decorate 'ERROR: assert_file_equals_golden' + return 1 ;; *) break @@ -616,8 +613,7 @@ _assert_golden_read_file_contents() { local file_contents= # Load the contents from the file. # Append a period (to be removed on the next line) so that trailing new lines are preserved. - file_contents="$(cat "$file_path" 2>/dev/null && printf '.')" - if [ $? -ne 0 ]; then + if ! file_contents="$(cat "$file_path" 2>/dev/null && printf '.')"; then echo "Failed to read ${file_description}. File path: '$file_path'" \ | batslib_decorate "ERROR: $assert_function_name" >&2 return 1 @@ -629,6 +625,7 @@ _assert_golden_read_file_contents() { _assert_golden_print_invalid_extended_regular_expression_msg() { local -r assert_function_name="$1" + echo "Invalid extended regular expression in golden file." \ | batslib_decorate "ERROR: $assert_function_name" } From c1eba2dab305e0bcd799c0ca7cb1681c0bdf734b Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 15:58:43 -0700 Subject: [PATCH 15/23] * Making helper function names more unique and clear. --- src/assert_equals_golden.bash | 98 +++++++++++++++++------------------ 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index d4724ad..9a744c0 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -133,15 +133,15 @@ assert_equals_golden() { done if (( use_stdin_set_by_opt )) && [ $# -ne 1 ]; then - _assert_golden_print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 1 + __assert_golden__print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 1 return 1 elif (( ! use_stdin_set_by_opt )) && [ $# -ne 2 ] ; then - _assert_golden_print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 2 + __assert_golden__print_incorrect_number_of_arguments_msg 'assert_equals_golden' "$#" 2 return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - _assert_golden_print_diff_regexp_incompat_msg 'assert_equals_golden' + __assert_golden__print_diff_regexp_incompat_msg 'assert_equals_golden' return 1 fi @@ -157,19 +157,19 @@ assert_equals_golden() { local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if ! _assert_golden_validate_file_path 'assert_equals_golden' 'Golden file' "$golden_file_path"; then + if ! __assert_golden__validate_file_path 'assert_equals_golden' 'Golden file' "$golden_file_path"; then return 1 fi local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - _assert_golden_print_invalid_extended_regular_expression_msg 'assert_equals_golden' + __assert_golden__print_invalid_extended_regular_expression_msg 'assert_equals_golden' assert_failed=1 elif ! [[ "$value" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 @@ -180,20 +180,20 @@ assert_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - _assert_golden_print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_contents" elif (( is_mode_regexp )); then - _assert_golden_print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" else - _assert_golden_print_not_matching_whole_contents_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_whole_contents_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - _assert_golden_update_golden_file_contents_nonregexp 'assert_equals_golden' "$value" "$golden_file_path" + __assert_golden__update_golden_file_contents_nonregexp 'assert_equals_golden' "$value" "$golden_file_path" else - _assert_golden_update_golden_file_contents_regexp 'assert_equals_golden' "$value" "$golden_file_path" + __assert_golden__update_golden_file_contents_regexp 'assert_equals_golden' "$value" "$golden_file_path" fi - _assert_golden_print_updated_golden_file_msg 'assert_equals_golden' + __assert_golden__print_updated_golden_file_msg 'assert_equals_golden' fi fi return $assert_failed @@ -320,31 +320,31 @@ assert_output_equals_golden() { done if [ $# -ne 1 ]; then - _assert_golden_print_incorrect_number_of_arguments_msg 'assert_output_equals_golden' "$#" 1 + __assert_golden__print_incorrect_number_of_arguments_msg 'assert_output_equals_golden' "$#" 1 return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - _assert_golden_print_diff_regexp_incompat_msg 'assert_output_equals_golden' + __assert_golden__print_diff_regexp_incompat_msg 'assert_output_equals_golden' return 1 fi local -r golden_file_path="${1-}" local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if ! _assert_golden_validate_file_path 'assert_output_equals_golden' 'Golden file' "$golden_file_path"; then + if ! __assert_golden__validate_file_path 'assert_output_equals_golden' 'Golden file' "$golden_file_path"; then return 1 fi local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - _assert_golden_print_invalid_extended_regular_expression_msg 'assert_output_equals_golden' + __assert_golden__print_invalid_extended_regular_expression_msg 'assert_output_equals_golden' assert_failed=1 elif ! [[ "$output" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 @@ -355,20 +355,20 @@ assert_output_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - _assert_golden_print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_contents" elif (( is_mode_regexp )); then - _assert_golden_print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" else - _assert_golden_print_not_matching_whole_contents_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_whole_contents_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - _assert_golden_update_golden_file_contents_nonregexp 'assert_output_equals_golden' "$output" "$golden_file_path" + __assert_golden__update_golden_file_contents_nonregexp 'assert_output_equals_golden' "$output" "$golden_file_path" else - _assert_golden_update_golden_file_contents_regexp 'assert_output_equals_golden' "$output" "$golden_file_path" + __assert_golden__update_golden_file_contents_regexp 'assert_output_equals_golden' "$output" "$golden_file_path" fi - _assert_golden_print_updated_golden_file_msg 'assert_output_equals_golden' + __assert_golden__print_updated_golden_file_msg 'assert_output_equals_golden' fi fi return $assert_failed @@ -493,12 +493,12 @@ assert_file_equals_golden() { done if [ $# -ne 2 ]; then - _assert_golden_print_incorrect_number_of_arguments_msg 'assert_file_equals_golden' "$#" 2 + __assert_golden__print_incorrect_number_of_arguments_msg 'assert_file_equals_golden' "$#" 2 return 1 fi if (( show_diff )) && (( is_mode_regexp )); then - _assert_golden_print_diff_regexp_incompat_msg 'assert_file_equals_golden' + __assert_golden__print_diff_regexp_incompat_msg 'assert_file_equals_golden' return 1 fi @@ -506,25 +506,25 @@ assert_file_equals_golden() { local -r golden_file_path="${2-}" local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" - if ! _assert_golden_validate_file_path 'assert_file_equals_golden' 'Target file' "$target_file_path" \ - && _assert_golden_validate_file_path 'assert_file_equals_golden' 'Golden file' "$golden_file_path"; then + if ! __assert_golden__validate_file_path 'assert_file_equals_golden' 'Target file' "$target_file_path" \ + && __assert_golden__validate_file_path 'assert_file_equals_golden' 'Golden file' "$golden_file_path"; then return 1 fi local target_file_contents= - if ! target_file_contents="$(_assert_golden_read_file_contents 'assert_file_equals_golden' 'target file' "$target_file_path")"; then + if ! target_file_contents="$(__assert_golden__read_file_contents 'assert_file_equals_golden' 'target file' "$target_file_path")"; then return 1 fi local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path" "$allow_empty")"; then return 1 fi local -i assert_failed=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then - _assert_golden_print_invalid_extended_regular_expression_msg 'assert_file_equals_golden' + __assert_golden__print_invalid_extended_regular_expression_msg 'assert_file_equals_golden' assert_failed=1 elif ! [[ "$target_file_contents" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 @@ -535,26 +535,26 @@ assert_file_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - _assert_golden_print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_contents" elif (( is_mode_regexp )); then - _assert_golden_print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$outarget_file_contentstput" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$outarget_file_contentstput" "$golden_file_path" "$golden_file_contents" else - _assert_golden_print_not_matching_whole_contents_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_whole_contents_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then if ! (( is_mode_regexp )); then - _assert_golden_update_golden_file_contents_nonregexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" + __assert_golden__update_golden_file_contents_nonregexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" else - _assert_golden_update_golden_file_contents_regexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" + __assert_golden__update_golden_file_contents_regexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" fi - _assert_golden_print_updated_golden_file_msg 'assert_file_equals_golden' + __assert_golden__print_updated_golden_file_msg 'assert_file_equals_golden' fi fi return $assert_failed } -_assert_golden_print_incorrect_number_of_arguments_msg() { +__assert_golden__print_incorrect_number_of_arguments_msg() { local -r assert_function_name="$1" local -r -i actual_arg_count="$2" local -r -i expected_arg_count="$3" @@ -563,14 +563,14 @@ _assert_golden_print_incorrect_number_of_arguments_msg() { | batslib_decorate "ERROR: $assert_function_name" } -_assert_golden_print_diff_regexp_incompat_msg() { +__assert_golden__print_diff_regexp_incompat_msg() { local -r assert_function_name="$1" echo "\`--diff' not supported with \`--regexp'" \ | batslib_decorate "ERROR: $assert_function_name" } -_assert_golden_validate_file_path() { +__assert_golden__validate_file_path() { local -r assert_function_name="$1" local -r file_description="$2" local -r file_path="$3" @@ -587,13 +587,13 @@ _assert_golden_validate_file_path() { fi } -_assert_golden_read_golden_file_contents() { +__assert_golden__read_golden_file_contents() { local -r assert_function_name="$1" local -r golden_file_path="$2" local -r -i allow_empty="$3" local golden_file_contents= - if ! golden_file_contents="$(_assert_golden_read_file_contents "$assert_function_name" 'golden file' "$golden_file_path")"; then + if ! golden_file_contents="$(__assert_golden__read_file_contents "$assert_function_name" 'golden file' "$golden_file_path")"; then return 1 fi if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then @@ -605,7 +605,7 @@ _assert_golden_read_golden_file_contents() { printf '%s' "$golden_file_contents" } -_assert_golden_read_file_contents() { +__assert_golden__read_file_contents() { local -r assert_function_name="$1" local -r file_description="$2" local -r file_path="$3" @@ -623,14 +623,14 @@ _assert_golden_read_file_contents() { printf '%s' "$file_contents" } -_assert_golden_print_invalid_extended_regular_expression_msg() { +__assert_golden__print_invalid_extended_regular_expression_msg() { local -r assert_function_name="$1" echo "Invalid extended regular expression in golden file." \ | batslib_decorate "ERROR: $assert_function_name" } -_assert_golden_print_not_matching_show_diff_msg() { +__assert_golden__print_not_matching_show_diff_msg() { local -r assert_function_name="$1" local -r contents_description="$2" local -r actual_contents="$3" @@ -643,7 +643,7 @@ _assert_golden_print_not_matching_show_diff_msg() { | batslib_decorate "${assert_function_name}: $contents_description does not match golden" } -_assert_golden_print_not_matching_regexp_msg() { +__assert_golden__print_not_matching_regexp_msg() { local -r assert_function_name="$1" local -r contents_description="$2" local -r actual_contents="$3" @@ -659,7 +659,7 @@ _assert_golden_print_not_matching_regexp_msg() { | batslib_decorate "${assert_function_name}: $contents_description does not match regexp golden" } -_assert_golden_print_not_matching_whole_contents_msg() { +__assert_golden__print_not_matching_whole_contents_msg() { local -r assert_function_name="$1" local -r contents_description="$2" local -r actual_contents="$3" @@ -675,7 +675,7 @@ _assert_golden_print_not_matching_whole_contents_msg() { | batslib_decorate "${assert_function_name}: $contents_description does not match golden" } -_assert_golden_update_golden_file_contents_nonregexp() { +__assert_golden__update_golden_file_contents_nonregexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" local -r golden_file_path="$3" @@ -688,7 +688,7 @@ _assert_golden_update_golden_file_contents_nonregexp() { fi } -_assert_golden_update_golden_file_contents_regexp() { +__assert_golden__update_golden_file_contents_regexp() { local -r assert_function_name="$1" local -r new_golden_contents="$2" local -r golden_file_path="$3" @@ -735,7 +735,7 @@ _assert_golden_update_golden_file_contents_regexp() { fi } -_assert_golden_print_updated_golden_file_msg() { +__assert_golden__print_updated_golden_file_msg() { local -r assert_function_name="$1" echo "Golden file updated after mismatch." \ From 4db39f256c2c69c89bfd08b200eb28cd20e3da3b Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 16:26:02 -0700 Subject: [PATCH 16/23] * Fixing typo on variable name. --- src/assert_equals_golden.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 9a744c0..bc887be 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -537,7 +537,7 @@ assert_file_equals_golden() { if (( show_diff )); then __assert_golden__print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_contents" elif (( is_mode_regexp )); then - __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$outarget_file_contentstput" "$golden_file_path" "$golden_file_contents" + __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" else __assert_golden__print_not_matching_whole_contents_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" fi From 56cfdb55bfc301635cd3939a9633a283cc2dc137 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 17:24:45 -0700 Subject: [PATCH 17/23] * Switching from echoing in helper functions to using namerefs. * Simplifies output streams. * Properly handles trailing newlines. --- src/assert_equals_golden.bash | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index bc887be..ba1f592 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -162,7 +162,7 @@ assert_equals_golden() { fi local golden_file_contents= - if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! __assert_golden__read_golden_file_contents 'assert_equals_golden' "$golden_file_path" "$allow_empty" 'golden_file_contents'; then return 1 fi @@ -337,7 +337,7 @@ assert_output_equals_golden() { fi local golden_file_contents= - if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! __assert_golden__read_golden_file_contents 'assert_output_equals_golden' "$golden_file_path" "$allow_empty" 'golden_file_contents'; then return 1 fi @@ -512,12 +512,12 @@ assert_file_equals_golden() { fi local target_file_contents= - if ! target_file_contents="$(__assert_golden__read_file_contents 'assert_file_equals_golden' 'target file' "$target_file_path")"; then + if ! __assert_golden__read_file_contents 'assert_file_equals_golden' 'target file' "$target_file_path" 'target_file_contents'; then return 1 fi local golden_file_contents= - if ! golden_file_contents="$(__assert_golden__read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path" "$allow_empty")"; then + if ! __assert_golden__read_golden_file_contents 'assert_file_equals_golden' "$golden_file_path" "$allow_empty" 'golden_file_contents'; then return 1 fi @@ -591,36 +591,34 @@ __assert_golden__read_golden_file_contents() { local -r assert_function_name="$1" local -r golden_file_path="$2" local -r -i allow_empty="$3" + local -r output_variable_name="$4" - local golden_file_contents= - if ! golden_file_contents="$(__assert_golden__read_file_contents "$assert_function_name" 'golden file' "$golden_file_path")"; then + local -n golden_file_contents_ref="$output_variable_name" + if ! __assert_golden__read_file_contents "$assert_function_name" 'golden file' "$golden_file_path" 'golden_file_contents_ref'; then return 1 fi - if [ -z "$golden_file_contents" ] && ! (( allow_empty )); then + if [ -z "$golden_file_contents_ref" ] && ! (( allow_empty )); then echo "Golden file contents is empty. This may be an authoring error. Use \`--allow-empty\` if this is intentional." \ - | batslib_decorate "ERROR: $assert_function_name" >&2 + | batslib_decorate "ERROR: $assert_function_name" return 1 fi - - printf '%s' "$golden_file_contents" } __assert_golden__read_file_contents() { local -r assert_function_name="$1" local -r file_description="$2" local -r file_path="$3" + local -r output_variable_name="$4" - local file_contents= + local -n file_contents_ref="$output_variable_name" # Load the contents from the file. # Append a period (to be removed on the next line) so that trailing new lines are preserved. - if ! file_contents="$(cat "$file_path" 2>/dev/null && printf '.')"; then + if ! file_contents_ref="$(cat "$file_path" 2>/dev/null && printf '.')"; then echo "Failed to read ${file_description}. File path: '$file_path'" \ - | batslib_decorate "ERROR: $assert_function_name" >&2 + | batslib_decorate "ERROR: $assert_function_name" return 1 fi - file_contents="${file_contents%.}" - - printf '%s' "$file_contents" + file_contents_ref="${file_contents_ref%.}" } __assert_golden__print_invalid_extended_regular_expression_msg() { From accd5a3390e83c1fb04893b7074c3fb5b676333c Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 17:25:43 -0700 Subject: [PATCH 18/23] * Updating assertions in tests to match updated message output. --- test/assert_equals_golden.bats | 276 ++++++++++++++++----------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index 89a920f..b641eaa 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -58,7 +58,7 @@ save_temp_file_path_and_run() { assert_test_fail < @@ -2149,7 +2149,7 @@ ERR_MSG assert_test_fail < @@ -2163,7 +2163,7 @@ ERR_MSG assert_test_fail < @@ -2353,7 +2353,7 @@ ERR_MSG assert_test_fail < @@ -3251,7 +3251,7 @@ ERR_MSG assert_test_fail < @@ -3264,7 +3264,7 @@ ERR_MSG assert_test_fail < @@ -3474,7 +3474,7 @@ ERR_MSG assert_test_fail < Date: Sun, 24 Aug 2025 20:42:21 -0700 Subject: [PATCH 20/23] * Moving "print_updated_golden_file_msg" call inside respective "update_golden_file_contents", so then it is only called when they succeed. --- src/assert_equals_golden.bash | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 4bbb36c..08b947a 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -193,7 +193,6 @@ assert_equals_golden() { else __assert_golden__update_golden_file_contents_regexp 'assert_equals_golden' "$value" "$golden_file_path" fi - __assert_golden__print_updated_golden_file_msg 'assert_equals_golden' fi fi return $assert_failed @@ -368,7 +367,6 @@ assert_output_equals_golden() { else __assert_golden__update_golden_file_contents_regexp 'assert_output_equals_golden' "$output" "$golden_file_path" fi - __assert_golden__print_updated_golden_file_msg 'assert_output_equals_golden' fi fi return $assert_failed @@ -548,7 +546,6 @@ assert_file_equals_golden() { else __assert_golden__update_golden_file_contents_regexp 'assert_file_equals_golden' "$target_file_contents" "$golden_file_path" fi - __assert_golden__print_updated_golden_file_msg 'assert_file_equals_golden' fi fi return $assert_failed @@ -688,6 +685,8 @@ __assert_golden__update_golden_file_contents_nonregexp() { if ! printf '%s' "$new_golden_contents" 2>/dev/null > "$golden_file_path"; then echo "Failed to write into golden file during update: '$golden_file_path'." \ | batslib_decorate "FAIL: $assert_function_name" + else + __assert_golden__print_updated_golden_file_msg "$assert_function_name" fi } @@ -735,6 +734,8 @@ __assert_golden__update_golden_file_contents_regexp() { fi printf '%s' "$best_guess_for_line" >> "$golden_file_path" done + + __assert_golden__print_updated_golden_file_msg "$assert_function_name" fi } From a60ea2ac017030b582e32de8abe50826ff26fa60 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Sun, 24 Aug 2025 20:52:14 -0700 Subject: [PATCH 21/23] * Fixing missing param passed for "show_diff" error message. --- src/assert_equals_golden.bash | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index 08b947a..ae30cd8 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -180,7 +180,7 @@ assert_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - __assert_golden__print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" elif (( is_mode_regexp )); then __assert_golden__print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" else @@ -354,7 +354,7 @@ assert_output_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - __assert_golden__print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" elif (( is_mode_regexp )); then __assert_golden__print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" else @@ -533,7 +533,7 @@ assert_file_equals_golden() { if (( assert_failed )); then if (( show_diff )); then - __assert_golden__print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_contents" + __assert_golden__print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" elif (( is_mode_regexp )); then __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" else @@ -635,6 +635,7 @@ __assert_golden__print_not_matching_show_diff_msg() { local -r contents_description="$2" local -r actual_contents="$3" local -r golden_file_path="$4" + local -r golden_file_contents="$5" { echo "Golden file: $golden_file_path" From f1ae552d96f871a9950aaba78d1f2ffde0d4622d Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Tue, 26 Aug 2025 00:16:30 -0700 Subject: [PATCH 22/23] * Updating logic to not do regex check after failing valid regex check. * Fixing file path validation check in `assert_file_equals_golden`. * Updating invalid regex error message to contain golden file name and contents. --- src/assert_equals_golden.bash | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/assert_equals_golden.bash b/src/assert_equals_golden.bash index ae30cd8..8e4fe44 100644 --- a/src/assert_equals_golden.bash +++ b/src/assert_equals_golden.bash @@ -167,10 +167,12 @@ assert_equals_golden() { fi local -i assert_failed=0 + local -i invalid_regexp=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then __assert_golden__print_invalid_extended_regular_expression_msg 'assert_equals_golden' assert_failed=1 + invalid_regexp=1 elif ! [[ "$value" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -181,10 +183,10 @@ assert_equals_golden() { if (( assert_failed )); then if (( show_diff )); then __assert_golden__print_not_matching_show_diff_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" - elif (( is_mode_regexp )); then - __assert_golden__print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" - else + elif ! (( is_mode_regexp )); then __assert_golden__print_not_matching_whole_contents_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" + elif ! (( invalid_regexp )); then + __assert_golden__print_not_matching_regexp_msg 'assert_equals_golden' 'value' "$value" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -341,10 +343,12 @@ assert_output_equals_golden() { fi local -i assert_failed=0 + local -i invalid_regexp=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then __assert_golden__print_invalid_extended_regular_expression_msg 'assert_output_equals_golden' assert_failed=1 + invalid_regexp=1 elif ! [[ "$output" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -355,10 +359,10 @@ assert_output_equals_golden() { if (( assert_failed )); then if (( show_diff )); then __assert_golden__print_not_matching_show_diff_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" - elif (( is_mode_regexp )); then - __assert_golden__print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" - else + elif ! (( is_mode_regexp )); then __assert_golden__print_not_matching_whole_contents_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" + elif ! (( invalid_regexp )); then + __assert_golden__print_not_matching_regexp_msg 'assert_output_equals_golden' 'output' "$output" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -505,7 +509,7 @@ assert_file_equals_golden() { local -r -i update_goldens_on_failure="${BATS_ASSERT_UPDATE_GOLDENS_ON_FAILURE:+1}" if ! __assert_golden__validate_file_path 'assert_file_equals_golden' 'Target file' "$target_file_path" \ - && __assert_golden__validate_file_path 'assert_file_equals_golden' 'Golden file' "$golden_file_path"; then + || ! __assert_golden__validate_file_path 'assert_file_equals_golden' 'Golden file' "$golden_file_path"; then return 1 fi @@ -520,10 +524,12 @@ assert_file_equals_golden() { fi local -i assert_failed=0 + local -i invalid_regexp=0 if (( is_mode_regexp )); then if [[ ! '' =~ ^${golden_file_contents}$ ]] && [[ '' =~ ^${golden_file_contents}$ ]] || (( $? == 2 )); then __assert_golden__print_invalid_extended_regular_expression_msg 'assert_file_equals_golden' assert_failed=1 + invalid_regexp=1 elif ! [[ "$target_file_contents" =~ ^${golden_file_contents}$ ]]; then assert_failed=1 fi @@ -534,10 +540,10 @@ assert_file_equals_golden() { if (( assert_failed )); then if (( show_diff )); then __assert_golden__print_not_matching_show_diff_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" - elif (( is_mode_regexp )); then - __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" - else + elif ! (( is_mode_regexp )); then __assert_golden__print_not_matching_whole_contents_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" + elif ! (( invalid_regexp )); then + __assert_golden__print_not_matching_regexp_msg 'assert_file_equals_golden' 'file contents' "$target_file_contents" "$golden_file_path" "$golden_file_contents" fi if (( update_goldens_on_failure )); then @@ -625,8 +631,12 @@ __assert_golden__read_file_contents() { __assert_golden__print_invalid_extended_regular_expression_msg() { local -r assert_function_name="$1" - - echo "Invalid extended regular expression in golden file." \ + { + echo "Invalid extended regular expression in golden file." + echo "Golden file: $golden_file_path" + batslib_print_kv_multi \ + 'golden contents' "$golden_file_contents" + } \ | batslib_decorate "ERROR: $assert_function_name" } From ef9a633674911963f8d7e04622ac7d06cd143fb2 Mon Sep 17 00:00:00 2001 From: Cauhx Milloy Date: Tue, 26 Aug 2025 00:18:00 -0700 Subject: [PATCH 23/23] * Updating assertion for invalid regex test cases. * Fixing assertion for argument count test cases on `assert_file_equals_golden`. --- test/assert_equals_golden.bats | 39 +++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/test/assert_equals_golden.bats b/test/assert_equals_golden.bats index b641eaa..bd8583f 100644 --- a/test/assert_equals_golden.bats +++ b/test/assert_equals_golden.bats @@ -1677,12 +1677,15 @@ ERR_MSG @test "assert_equals_golden --regexp: fails if regex golden is not a valid extended regular expression" { tested_value="$output" output='UNUSED' - run assert_equals_golden --regexp "$tested_value" <(printf '[.*') + save_temp_file_path_and_run assert_equals_golden --regexp "$tested_value" <(printf '[.*') - assert_test_fail <<'ERR_MSG' + assert_test_fail <