-
Notifications
You must be signed in to change notification settings - Fork 0
/
assert.bash
75 lines (74 loc) · 2.64 KB
/
assert.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# for assertions everywhere!
# usage: assert [condition] [message]
# if condition is false, print message and exit
assert() {
[ -v EDIT ] && unset EDIT && edit_function "${FUNCNAME[0]}" "$BASH_SOURCE" && return
local arg1 comp arg2 message comp_result
arg1="$1"
comp="$2"
arg2="$3"
if [[ -z "$arg1" || -z "$comp" || -z "$arg2" ]]; then
echo "Insufficient arguments to assert in ${BASH_SOURCE[1]}: $*" >&2
return 0 # because returning 1 would cause the shell to exit during sourcing
fi
message="$4"
# We add a form feed character at the end of both due to how Bash command substitution
# gobbles up trailing newlines (and that's POSIX!).
arg1_enc=$(binhex "$arg1\f")
arg2_enc=$(binhex "$arg2\f")
comp_result=false # default to false
case $comp in
= | == )
# comparison_encoded="[ \"$arg1_enc\" $comp \"$arg2_enc\" ]"
[ "$arg1_enc" = "$arg2_enc" ] && comp_result=true
comparison="[ \"$arg1\" $comp \"$arg2\" ]"
;;
!= | !== )
# comparison_encoded="[ \"$arg1_enc\" \!= \"$arg2_enc\" ]"
[ "$arg1_enc" != "$arg2_enc" ] && comp_result=true
comparison="[ \"$arg1\" \!= \"$arg2\" ]"
;;
=~ ) # can't do encoded regex comparisons, so just do a plaintext comparison
# comparison_encoded="[[ \"$arg1\" =~ $arg2 ]]"
[[ "$arg1" =~ $arg2 ]] && comp_result=true
comparison="[[ \"$arg1\" =~ $arg2 ]]"
;;
!=~ | !~ )
# comparison_encoded="[[ ! \"$arg1\" =~ $arg2 ]]"
[[ ! "$arg1" =~ $arg2 ]] && comp_result=true
comparison="[[ ! \"$arg1\" =~ $arg2 ]]"
;;
* )
echo "Unknown comparison operator: $comp" >&2
return 1
;;
esac
if $comp_result; then
return 0
else
# These values (BASH_SOURCE and BASH_LINENO) seem valid when triggered in my dotfiles, but not from my shell.
# Not sure how to fix yet.
local actualfile
local linenum
if [ -t 0 ]; then # if stdin is a tty
actualfile="tty"
linenum=$(history 1 | awk '{print $1}')
else # if this is run from a script
# As to why we need the 1th index of BASH_SOURCE but the 0th index of BASH_LINENO, I have no idea. But it works.
actualfile="$(readlink -f ${BASH_SOURCE[1]})"
linenum="${BASH_LINENO[0]}"
fi
case $comp in
=~ | !=~ | !~ ) # regex comparisons
echo "Assertion failed: \"$arg1\" $comp $arg2 @ ${actualfile}:${linenum}" >&2
;;
*) # non-regex comparisons
echo "Assertion failed: \"$arg1\" $comp \"$arg2\" @ ${actualfile}:${linenum}" >&2
;;
esac
[ -n "$message" ] && echo $message >&2
return 1
fi
}
# this is at the bottom because it depends on assert
source_relative_once binhex.bash