#!/usr/bin/env bash set -e # shellcheck source=lib/bats-core/formatter.bash source "$BATS_ROOT/$BATS_LIBDIR/bats-core/formatter.bash" BASE_PATH=. BATS_ENABLE_TIMING= while [[ "$#" -ne 0 ]]; do case "$1" in -T) BATS_ENABLE_TIMING="-T" ;; --base-path) shift normalize_base_path BASE_PATH "$1" ;; esac shift done update_count_column_width() { count_column_width=$((${#count} * 2 + 2)) if [[ -n "$BATS_ENABLE_TIMING" ]]; then # additional space for ' in %s sec' count_column_width=$((count_column_width + ${#SECONDS} + 8)) fi # also update dependent value update_count_column_left } update_screen_width() { screen_width="$(tput cols)" # also update dependent value update_count_column_left } update_count_column_left() { count_column_left=$((screen_width - count_column_width)) } # avoid unset variables count=0 screen_width=80 update_count_column_width update_screen_width test_result= trap update_screen_width WINCH begin() { test_result= # reset to avoid carrying over result state from previous test line_backoff_count=0 go_to_column 0 update_count_column_width buffer_with_truncation $((count_column_left - 1)) ' %s' "$name" clear_to_end_of_line go_to_column $count_column_left if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer "%${#count}s/${count} in %s sec" "$index" "$SECONDS" else buffer "%${#count}s/${count}" "$index" fi go_to_column 1 } finish_test() { move_up $line_backoff_count go_to_column 0 buffer "$@" if [[ -n "${TIMEOUT-}" ]]; then set_color 2 if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer ' [%s (timeout: %s)]' "$TIMING" "$TIMEOUT" else buffer ' [timeout: %s]' "$TIMEOUT" fi else if [[ -n "$BATS_ENABLE_TIMING" ]]; then set_color 2 buffer ' [%s]' "$TIMING" fi fi advance move_down $((line_backoff_count - 1)) } pass() { local TIMING="${1:-}" finish_test ' ✓ %s' "$name" test_result=pass } skip() { local reason="$1" TIMING="${2:-}" if [[ -n "$reason" ]]; then reason=": $reason" fi finish_test ' - %s (skipped%s)' "$name" "$reason" test_result=skip } fail() { local TIMING="${1:-}" set_color 1 bold finish_test ' ✗ %s' "$name" test_result=fail } timeout() { local TIMING="${1:-}" set_color 3 bold TIMEOUT="${2:-}" finish_test ' ✗ %s' "$name" test_result=timeout } log() { case ${test_result} in pass) clear_color ;; fail) set_color 1 ;; timeout) set_color 3 ;; esac buffer ' %s\n' "$1" clear_color } summary() { if [ "$failures" -eq 0 ]; then set_color 2 bold else set_color 1 bold fi buffer '\n%d test' "$count" if [[ "$count" -ne 1 ]]; then buffer 's' fi buffer ', %d failure' "$failures" if [[ "$failures" -ne 1 ]]; then buffer 's' fi if [[ "$skipped" -gt 0 ]]; then buffer ', %d skipped' "$skipped" fi if ((timed_out > 0)); then buffer ', %d timed out' "$timed_out" fi not_run=$((count - passed - failures - skipped - timed_out)) if [[ "$not_run" -gt 0 ]]; then buffer ', %d not run' "$not_run" fi if [[ -n "$BATS_ENABLE_TIMING" ]]; then buffer " in $SECONDS seconds" fi buffer '\n' clear_color } buffer_with_truncation() { local width="$1" shift local string # shellcheck disable=SC2059 printf -v 'string' -- "$@" if [[ "${#string}" -gt "$width" ]]; then buffer '%s...' "${string:0:$((width - 4))}" else buffer '%s' "$string" fi } move_up() { if [[ $1 -gt 0 ]]; then # avoid moving if we got 0 buffer '\x1B[%dA' "$1" fi } move_down() { if [[ $1 -gt 0 ]]; then # avoid moving if we got 0 buffer '\x1B[%dB' "$1" fi } go_to_column() { local column="$1" buffer '\x1B[%dG' $((column + 1)) } clear_to_end_of_line() { buffer '\x1B[K' } advance() { clear_to_end_of_line buffer '\n' clear_color } set_color() { local color="$1" local weight=22 if [[ "${2:-}" == 'bold' ]]; then weight=1 fi buffer '\x1B[%d;%dm' "$((30 + color))" "$weight" } clear_color() { buffer '\x1B[0m' } _buffer= buffer() { local content # shellcheck disable=SC2059 printf -v content -- "$@" _buffer+="$content" } prefix_buffer_with() { local old_buffer="$_buffer" _buffer='' "$@" _buffer="$_buffer$old_buffer" } flush() { printf '%s' "$_buffer" _buffer= } finish() { flush printf '\n' } trap finish EXIT trap '' INT bats_tap_stream_plan() { count="$1" index=0 passed=0 failures=0 skipped=0 timed_out=0 name= update_count_column_width } bats_tap_stream_begin() { index="$1" name="$2" begin flush } bats_tap_stream_ok() { index="$1" name="$2" ((++passed)) pass "${BATS_FORMATTER_TEST_DURATION:-}" } bats_tap_stream_skipped() { index="$1" name="$2" ((++skipped)) skip "$3" "${BATS_FORMATTER_TEST_DURATION:-}" } bats_tap_stream_not_ok() { index="$1" name="$2" if [[ ${BATS_FORMATTER_TEST_TIMEOUT-x} != x ]]; then timeout "${BATS_FORMATTER_TEST_DURATION:-}" "${BATS_FORMATTER_TEST_TIMEOUT}s" ((++timed_out)) else fail "${BATS_FORMATTER_TEST_DURATION:-}" ((++failures)) fi } bats_tap_stream_comment() { # local scope=$2 # count the lines we printed after the begin text, if [[ $line_backoff_count -eq 0 && $scope == begin ]]; then # if this is the first line after begin, go down one line buffer "\n" ((++line_backoff_count)) # prefix-increment to avoid "error" due to returning 0 fi ((++line_backoff_count)) ((line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length log "$1" } bats_tap_stream_suite() { #test_file="$1" line_backoff_count=0 index= # indicate filename for failures local file_name="${1#"$BASE_PATH"}" name="File $file_name" set_color 4 bold buffer "%s\n" "$file_name" clear_color } line_backoff_count=0 bats_tap_stream_unknown() { # local scope=$2 # count the lines we printed after the begin text, (or after suite, in case of syntax errors) if [[ $line_backoff_count -eq 0 && ($scope == begin || $scope == suite) ]]; then # if this is the first line after begin, go down one line buffer "\n" ((++line_backoff_count)) # prefix-increment to avoid "error" due to returning 0 fi ((++line_backoff_count)) ((line_backoff_count += ${#1} / screen_width)) # account for linebreaks due to length buffer "%s\n" "$1" flush } bats_parse_internal_extended_tap summary