forked from illusori/bash-tap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbash-tap-mock
executable file
·106 lines (92 loc) · 3.41 KB
/
bash-tap-mock
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/bin/bash
#
# While not directly TAP-specific, being able to mock stuff
# in tests is pretty useful.
#
# If you're using bash-tap-bootstrap, then just source this
# file in your tests from the bash-tap directory found by
# the bootstrap by including this line after you've sourced
# bash-tap-bootstrap:
#
# . "$BASH_TAP_ROOT/bash-tap-mock"
#
# If you're not using bash-tap-bootstrap then copy this file
# to your test directory and source it with:
#
# . $(dirname $0)/bash-tap-mock
#
# It's important to note that if you're capturing the arguments
# passed to your mock function in a variable, and want that
# variable to be accessible to your tests, you must ensure that
# the mocked function is executed in the current shell and not
# a subshell. In particular, this means you cannot use $() or
# `` to capture output of the function at the same time, as these
# invoke a subshell - the mock will happen, but any variables you
# set within your mock will only exist within the subshell.
# If you wish to capture output at the same time, you need to
# make use of the start_output_capture and finish_output_capture
# helper functons in bash-tap, or manually use file-descriptor
# redirects yourself to achieve the same effect.
bash_tap_mock_version='1.0.2'
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# Being run directly, probably by test harness running entire dir.
echo "1..0 # SKIP bash-tap-mock isn't a test file"
exit 0
fi
function mock_function() {
local original_name="$1"
local mock_name="$2"
local save_original_as="_btm_mocked_${original_name}"
if [ -z $(declare -F "$save_original_as") ]; then
_btm_copy_function "$original_name" "$save_original_as"
fi
_btm_copy_function "$mock_name" "$original_name"
}
function restore_mocked_function() {
local original_name="$1"
local save_original_as="_btm_mocked_${original_name}"
if [ ! -z $(declare -F "$save_original_as") ]; then
_btm_copy_function "$save_original_as" "$original_name"
unset -f "$save_original_as"
else
_btm_caller_error "Can't find saved original function '$original_name' to restore"
fi
}
function mock_command() {
local command_name="$1"
local mock_name="$2"
if [ ! -z $(declare -F "$command_name") ]; then
# It's not actually a command, it's a function, mock that
mock_function "$command_name" "$mock_name"
else
_btm_copy_function "$mock_name" "$command_name"
fi
}
function restore_mocked_command() {
local command_name="$1"
local save_original_as="_btm_mocked_${command_name}"
if [ ! -z $(declare -F "$save_original_as") ]; then
# Was actually a function mock not a command mock.
restore_mocked_function "$command_name"
else
unset -f "$command_name" >/dev/null
fi
}
# Copied from http://stackoverflow.com/a/1203628/870000
function _btm_copy_function() {
declare -F $1 >/dev/null || _btm_caller_error "Can't find function '$1' to copy"
eval "$(echo "${2}()"; declare -f ${1} | tail -n +2)"
}
# Report an error from the POV of the first calling point outside this file
function _btm_caller_error() {
local message="$*"
local thisfile="${BASH_SOURCE[0]}"
local file="$thisfile"
local frame_num=2
until [ "$file" != "$thisfile" ]; do
frame=$(caller "$frame_num")
IFS=' ' read line func file <<<"$frame"
done
echo "Error: $message, on line $line of $file" >&2
exit 255
}