-
Notifications
You must be signed in to change notification settings - Fork 0
/
runtests.sh
executable file
·411 lines (345 loc) · 10.5 KB
/
runtests.sh
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#!/bin/bash
# sets up and launches cs100-runtests
# prints usage to stderr then quits
usage() {
cat >&2 <<EOF
Usage: $(basename $0) [shell [testFile]]
EOF
exit 1
}
######################################
# setup (data / functions)
# file edit grades in. Changeable at a later day.
gradeFile=grade
# unique session and window name
session="$USER-runtests"
window="$USER-runtests-window"
# prints what's passed in in red
red() {
echo -en "\033[1;31m"
echo -n "$@"
echo -en "\033[0m"
}
######################################
# parameters
# shell. Defaults to "bin/rshell"
shell=${1:-bin/rshell}
# test case file
testCaseFile=$2
if [ "$shell" != "--controller" ]
then
command -v $shell &>/dev/null || {
red "$shell"
echo ": not found" >&2
usage
}
# make new session or attach previous if one already exists opens vim on the
# grade file
tmux -2 new-session -d -n $window -s $session "vim $gradeFile" || {
tmux kill-session -t $session
tmux -2 new-session -d -n $window -s $session "vim $gradeFile" || {
echo "There was a serious problem" >&2; exit 1
}
}
### session settings
# Mouse support
tmux set-option -t $session mouse-select-pane on
tmux set-option -t $session mouse-resize-pane on
tmux set-option -t $session mouse-select-window on
# Set the default terminal mode to 256color mode
tmux set-option -t $session default-terminal "screen-256color"
# new panes start in current directory
tmux set-option -t $session default-path "$PWD"
# don't stop server when there are no attached clients
tmux set-option -t $session exit-unattached off
# if the session becomes unattached, don't kill it
tmux set-option -t $session destroy-unattached off
### window settings
# mouse support for window
tmux set-window-option -t $session:$window mode-mouse on
tmux set-window-option -t $session:$window allow-rename off
# split current window vertically, ends up as the top right pane
tmux split-window -h "sh"
# after pane is created, it is selected
# calling list-window and printing pane_pid will give the pid of sh
# running in that pane
upperRightPID=`tmux list-pane -t $session -F '#{pane_pid}' | tail -1`
#echo upperRightPID:$upperRightPID
# split right pane horizontally, ends up as the bottom right pane
tmux split-window -v -t 1 "$0 --controller $upperRightPID $shell $testCaseFile"
# show linenumbers in vim (pane 0)
tmux send-keys -t 0 ":set number" C-m C-l
tmux -2 attach -t $session >/dev/null
else
# todo: add cppcheck, valgind, checksyscalls, etc
#echo >>$gradeFile
#echo "cppcheck output:" >>$gradeFile
#cppcheck src/ &>>$gradeFile
#echo >>$gradeFile
#echo "valgrind output:" >>$gradeFile
#cppcheck src/ &>>$gradeFile
#echo >>$gradeFile
upperRightPID=$2
shell=$3
starterTestCaseFile=$4
tempFile=$(mktemp)
prevCommand="next"
commandIndex=0
declare -a commandArray
# function to print its parameters in red
# does not insert a newline after printing
cleanupAndQuit() {
rm -rf $tempFile
tmux kill-session -t $session
}
trap cleanupAndQuit SIGINT SIGQUIT SIGTERM SIGTSTP
readTestCases() {
if [ -z "$1" ]
then
return
elif [ ! -f $1 ]
then
red "$1"; echo ": file not found"
return
fi
index=0
commandArray=()
while read -r line
do
commandArray[$index]="$line"
index=`bc <<< "$index + 1"`
done <$1
unset index
echo "Successfully loaded test cases from \"$1\""
}
shellUp() {
if [ ! -z $disabled ]
then
return 1
fi
if [ `ps --ppid $upperRightPID | wc -l` -le 1 ]
then
red "shell is not running. starting a new instance... "
tmux send-keys -t 1 C-c
tmux send-keys -t 1 "$shell" C-m
#tmux send-keys -t 1 "valgrind --leak-check=full $shell" C-m
if [ `ps --ppid $upperRightPID | wc -l` -le 1 ]
then
red "failed"; echo
disabled=true
return 1
else
red "success"; echo
return 0
fi
elif [ ! -z `ps --ppid $upperRightPID -o state | grep T` ]
then
red "shell is stopped. attempting to restart... "
tmux send-keys -t 1 C-c
tmux send-keys -t 1 fg C-m
usleep 500000
if [ ! -z `ps --ppid $upperRightPID -o state | grep T` ]
then
red "failed"; echo
disabled=true
return 1
else
red "success"; echo
return 0
fi
fi
}
executeCommand() {
shellUp
if [ ! -z $disabled ]
then
red "The controller is disabled. This means that the shell has likely"; echo
red "encountered a serious issue and will not stay running."; echo
return
fi
for charIndex in $(seq 0 `bc <<< "${#1} - 1"`)
do
# send one char
# assumes shell is in pane 1
tmux send-keys -t 1 "${1:$charIndex:1}"
done
tmux send-keys -t 1 C-m
}
fullGrade() {
line=$1
outOf=$(cat $gradeFile | head -$line | tail -1 |
grep -o '/[[:blank:]]*[[:digit:]][[:digit:].]*[[:blank:]]*\]' |
grep -o '[[:digit:].]*')
#echo line:$line
#echo amt:$amt
changeGrade $line $outOf
#sed "$line"'s/\[.*\//\['$outOf'\//' $gradeFile >$tempFile &&
#cp $tempFile $gradeFile
}
changeGrade() {
line=$1
amt=$2
if [[ $line =~ ^[0-9]+$ ]] # line is made of only numbers
then
if [[ $amt =~ ^[0-9][0-9.]*$ ]] # amt is made of only numbers and '.'
then
sed "$line"'s/\[.*\//\['$amt'\//' $gradeFile >$tempFile &&
cp $tempFile $gradeFile
else
red $amt; echo ": invalid amount"
fi
else
red $line; echo ": invalid line number"
fi
}
parseGradeFile() {
grep -o '\[[[:blank:]]*[[:digit:].]*[[:blank:]]*/[[:blank:]]*[[:digit:]][[:digit:].]*[[:blank:]]*\]' |
grep -o '[[:blank:][:digit:]/.]*'
}
updateTotal() {
earned=0
total=0
for val in $(cat $gradeFile | parseGradeFile | cut -d/ -f1)
do
earned=`bc <<< "$earned + $val"`
done
for val in $(cat $gradeFile | parseGradeFile | cut -d/ -f2)
do
total=`bc <<< "$total + $val"`
done
sed '1s/.*/'"$earned \\/ $total"'/' $gradeFile >$tempFile &&
cp $tempFile $gradeFile
}
updateVim() {
tmux send-keys -t 0 ':e!' C-m 'gg' C-l
}
controllerUsage() {
echo -e "Valid commands:"
echo -e "n\t\t - next test case"
echo -e "p\t\t - previous test case"
echo -e "\t\t + b is an alias of p"
echo
echo -e "g <line> <amt>\t - assign <amt> points to <line> in grade file"
echo -e "f <line>\t - assign full points to <line> in grade file"
echo -e "zero\t\t - make all grades [ 0 / total ]"
echo -e "full\t\t - make all grades [ total / total ]"
echo
echo -e "h\t\t - print this message"
echo -e "c\t\t - clear the screen"
echo -e "e\t\t - exit"
echo -e "\t\t + q is an alias of e"
}
controller() {
cmd=$1
line=$2
file=$2
amt=$3
if [ ! -z "$cmd" ]
then
prevCommand="$@"
fi
case "$cmd" in
"") # same as previous
controller $prevCommand
;;
"h")
;&
"h?")
;&
"?h")
;&
"?")
;&
"??")
;&
"help")
controllerUsage
;;
"c")
;&
"clear")
clear
;;
"l") # load testcase
;&
"load") # load testcase
readTestCases $file
;;
"n") # next one command
;&
"next") # next one command
if [ $commandIndex -lt ${#commandArray[@]} ]
then
executeCommand "${commandArray[$commandIndex]}"
commandIndex=`bc <<< "$commandIndex + 1"`
else
red "no more test cases"; echo
fi
;;
"b") # back one command
;&
"back")
;&
"p")
;&
"previous")
if [ $commandIndex -gt 0 ]
then
commandIndex=`bc <<< "$commandIndex - 1"`
executeCommand "${commandArray[$commandIndex]}"
else
red "no previous test case"; echo
fi
;;
"g")
;&
"grade") # grade <line> <amt>
changeGrade $line $amt
updateTotal
updateVim
;;
"f") # full grade <line>
fullGrade $line
updateTotal
updateVim
;;
"zero") # zero all grades
for zeroLine in `seq 1 $(cat $gradeFile | wc -l)`
do
changeGrade $zeroLine 0
done
updateTotal
updateVim
;;
"full") # max all grades
for fullLine in `seq 1 $(cat $gradeFile | wc -l)`
do
fullGrade $fullLine >/dev/null
done
updateTotal
updateVim
;;
"q")
;&
"quit")
;&
"e")
;&
"exit")
cleanupAndQuit
;;
*)
red $cmd
echo ": invalid command (try h?)"
esac
}
# stuff to do before starting:
shellUp
readTestCases $starterTestCaseFile
controllerUsage
while read -p "command [$prevCommand]: " args
do
controller $args
done
cleanupAndQuit
fi