blob: c9687e5fe904e60e0e51ab6041a54936c9bd580a (
plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#!/bin/env bash
###############################################################################
# runTests.sh
#
# Usage: runTests.sh [testFile]
# where testFile defaults to testCases.in
#
# Processes a test file such as the testCases.in included with this package
###############################################################################
# Process one line from the test cases file. Invoked below through mapfile.
function _shellmath_runTests()
{
local lineNumber=$1
local text=$2
# Trim leading whitespace
[[ $text =~ ^[$' \t']*(.*) ]]
text=${BASH_REMATCH[1]}
# Skip comments and blank lines
[[ "$text" =~ ^# || -z $text ]] && return 0
# Check for line continuation
local len="${#text}"
if [[ ${text:$((len-1))} == '\' ]]; then
# Eat the continuation character and add to the buffer
__shellfloat_commandBuffer+="${text/%\\/ }"
# Defer processing
return
# No line continuation
else
# Assemble the command
local command=${__shellfloat_commandBuffer}${text}
__shellfloat_commandBuffer=""
words=($command)
# Expand first word to an assertion function
case ${words[0]} in
Code)
words[0]=_shellmath_assert_return${words[0]}
# Validate next word as a positive integer
if [[ ! "${words[1]}" =~ ^[0-9]+$ ]]; then
echo Line: "$lineNumber": Command "$command"
echo FAIL: \"Code\" requires integer return code
return 1
else
nextWord=2
fi
;;
String)
words[0]=_shellmath_assert_return${words[0]}
# Allow multiword arguments if quoted
if [[ ${words[1]} =~ ^\" ]]; then
if [[ ${words[1]} =~ \"$ ]]; then
nextWord=2
else
for ((nextWord=2;;nextWord++)); do
if [[ ${words[nextWord]} =~ \"$ ]]; then
((nextWord++))
break
fi
done
fi
else
nextWord=2
fi
;;
Both)
;;
*)
echo -e ${RED}FAIL${NO_COLOR} Line "$lineNumber": Command "$command": Code or String indicator required
return 2
;;
esac
# Expand the next word to a shellmath function name
words[nextWord]=_shellmath_${words[nextWord]}
if ! type -t "${words[nextWord]}" >/dev/null; then
echo "${RED}FAIL${NO_COLOR} Line $lineNumber: Command "$command": Syntax error. Required: String|Code value operation args..."
return 3
fi
# Run the command, being respectful of shell metacharacters
fullCommand="${words[*]}"
eval "$fullCommand"
local returnString
_shellmath_getReturnValue returnString
echo -e "$returnString" Line "$lineNumber": "$command"
fi
}
function _main()
{
source shellmath.sh
source assert.sh
# Initialize certain globals. As "public" functions, the arithmetic
# functions need to do this themselves, but there are some "private"
# functions that need this here when they are auto-tested.
_shellmath_precalc; __shellmath_didPrecalc=$__shellmath_true
# Process the test file line-by-line using the above runTests() function
mapfile -t -c 1 -C _shellmath_runTests -O 1 < "${1:-testCases.in}"
exit 0
}
_main "$@"
|