1#!/bin/bash 2 3WHITE="$(tput setaf 9 2>/dev/null || echo -n '')" 4YELLOW="$(tput setaf 3 2>/dev/null || echo -n '')" 5GREEN="$(tput setaf 2 2>/dev/null || echo -n '')" 6RED="$(tput setaf 1 2>/dev/null || echo -n '')" 7OFFSET=( ) 8STEP=" " 9 10function with_program () { 11 local program="${1:?}" 12 hash "$program" &>/dev/null || { 13 function expect_run () { 14 echo 1>&2 "${WHITE} - skipped (missing program)" 15 } 16 function expect_run_sh () { 17 echo 1>&2 "${WHITE} - skipped (missing program)" 18 } 19 } 20} 21 22function title () { 23 echo "$WHITE-----------------------------------------------------" 24 echo "${GREEN}$*" 25 echo "$WHITE-----------------------------------------------------" 26} 27 28function _context () { 29 local name="${1:?}" 30 shift 31 echo 1>&2 "${YELLOW}${OFFSET[*]:-}[$name] $*" 32 OFFSET+=("$STEP") 33} 34 35function step () { 36 _note step "${WHITE}" "$*" 37} 38 39function stepn () { 40 step "$*" $'\n' 41} 42 43function with () { 44 _context with "$*" 45} 46 47function when () { 48 _context when "$*" 49} 50 51function _note () { 52 local name="${1:?}" 53 local color="${2:-}" 54 shift 2 55 echo 1>&2 -n "${OFFSET[*]:-}${color}[$name] ${*// /}" 56} 57 58function it () { 59 _note it "${GREEN}" "$*" 60} 61 62function precondition () { 63 _note precondition "${WHITE}" "$*" 64} 65 66function shortcoming () { 67 _note shortcoming "${RED}" "$*" 68} 69 70function step () { 71 _note step "${WHITE}" "$*" 72} 73 74function stepn () { 75 step "$*" $'\n' 76} 77 78function fail () { 79 echo 1>&2 "${RED} $*" 80 exit 1 81} 82 83function sandbox () { 84 sandbox_tempdir="$(mktemp -t sandbox.XXXXXX -d)" 85 # shellcheck disable=2064 86 trap "popd >/dev/null" EXIT 87 pushd "$sandbox_tempdir" >/dev/null \ 88 || fail "Could not change directory into temporary directory." 89 90 local custom_init="${1:-}" 91 if [ -n "$custom_init" ]; then 92 eval "$custom_init" 93 fi 94} 95 96function expect_equals () { 97 expect_run 0 test "${1:?}" = "${2:?}" 98} 99 100function expect_exists () { 101 expect_run 0 test -e "${1:?}" 102} 103 104function expect_run_sh () { 105 expect_run "${1:?}" bash -c -eu -o pipefail "${2:?}" 106} 107 108function expect_snapshot () { 109 local expected=${1:?} 110 local actual=${2:?} 111 if ! [ -e "$expected" ]; then 112 mkdir -p "${expected%/*}" 113 cp -R "$actual" "$expected" 114 fi 115 expect_run 0 diff -r -N "$expected" "$actual" 116} 117 118function expect_run () { 119 local expected_exit_code=$1 120 shift 121 local output= 122 set +e 123 if [[ -n "${SNAPSHOT_FILTER-}" ]]; then 124 output="$("$@" 2>&1 | "$SNAPSHOT_FILTER")" 125 else 126 output="$("$@" 2>&1)" 127 fi 128 129 local actual_exit_code=$? 130 if [[ "$actual_exit_code" == "$expected_exit_code" ]]; then 131 if [[ -n "${WITH_SNAPSHOT-}" ]]; then 132 local expected="$WITH_SNAPSHOT" 133 if ! [ -f "$expected" ]; then 134 mkdir -p "${expected%/*}" 135 echo -n "$output" > "$expected" || exit 1 136 fi 137 if ! diff "$expected" <(echo -n "$output"); then 138 echo 1>&2 "${RED} - FAIL" 139 echo 1>&2 "${WHITE}\$ $*" 140 echo 1>&2 "Output snapshot did not match snapshot at '$expected'" 141 echo 1>&2 "$output" 142 if [ -n "${ON_ERROR:-}" ]; then 143 eval "$ON_ERROR" 144 fi 145 exit 1 146 fi 147 fi 148 echo 1>&2 149 else 150 echo 1>&2 "${RED} - FAIL" 151 echo 1>&2 "${WHITE}\$ $*" 152 echo 1>&2 "${RED}Expected actual status $actual_exit_code to be $expected_exit_code" 153 echo 1>&2 "$output" 154 if [ -n "${ON_ERROR:-}" ]; then 155 eval "$ON_ERROR" 156 fi 157 exit 1 158 fi 159 set -e 160} 161