3
# Copyright (c) 2010 Novell Inc, John Shi
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of version 2 of the GNU General Public License as
8
# published by the Free Software Foundation.
10
# This program is distributed in the hope that it would be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
# Further, this software is distributed without any warranty that it is
15
# free of the rightful claim of any third person regarding infringement
16
# or the like. Any license provided herein, whether implied or
17
# otherwise, applies only to this software file. Patent licenses, if
18
# any, provided herein do not apply to combinations of this program with
19
# other software, or any other product whatsoever.
21
# You should have received a copy of the GNU General Public License
22
# along with this program; if not, write the Free Software Foundation,
23
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
30
echo "ERROR: $str" >&2
39
echo "WARNING: $str" >&2
47
die "${agent}: line ${line_num}: ${str}"
50
# add quotes to string for Here Documents
62
echo "$str" | sed "s/$a/$a$b$a$b$a/g; 1 s/^/$a/; $ s/$/$a/"
71
echo "$str" | awk -F'"' '{
72
if (NF > 0 && NF%2 == 0)
74
for (i=1; i<=NF; i++) {
78
split($i, str, /[[:blank:]]+/);
79
for (j=0; j<length(str); j++) {
80
sb = sub(/#.*/, "", str[j]);
91
# phase 1: parse the string to 'command' and 'argument collection'.
94
trunk[0]="${line%%[[:blank:]]*}"
95
trunk[1]="${line#*[[:blank:]]}"
98
# phase 2: split the argument collection.
103
# Some of statements need one parameter at least.
104
if [ "$line" = "${trunk[0]}" ]; then
105
parse_die "missing parameter."
109
branch=($(explode "${trunk[1]}"))
110
if [ $? -ne 0 ]; then
111
parse_die "missing '\"'."
117
local agent line trunk branch macro num host
120
if [ ! -r "$opt_cfgsdir/$agent" ]; then
121
die "${agent}: configuration file not found."
124
rm -f $CASES_DIR/${agent}_macro.*
125
rm -f $CASES_DIR/${agent}.preparse
128
while read -r line; do
137
case "${trunk[0]}" in
140
macro="$CASES_DIR/${agent}_macro.${branch[0]}"
144
host=$(echo "${trunk[0]}" | awk -F@ '{print $2}')
146
if [ ! -r "$CASES_DIR/${agent}_macro.${branch[0]}" ]; then
147
parse_die "Macro '${branch[0]}' not found."
149
if [ -n "$host" ]; then
150
line="$(sed -e 's/^\([^[:blank:]]*\)@[^[:blank:]]*/\1/' -e "s/^[^[:blank:]]*/&@$host/" "$CASES_DIR/${agent}_macro.${branch[0]}")"
152
line="$(<"$CASES_DIR/${agent}_macro.${branch[0]}")"
164
if [ -n "$macro" ]; then
165
if ! touch "$macro"; then
166
die "No permission to create macro file: ${macro}."
168
echo "$line$num" >>"$macro"
170
echo "$line$num" >>"$CASES_DIR/${agent}.preparse"
172
done <"$opt_cfgsdir/$agent"
174
rm -f $CASES_DIR/${agent}_macro.*
181
if [ -n "$sh" ]; then
183
if [ -n "\$OCFT_VERBOSE" ]; then
188
for host in $hosts; do
189
echo "backbash_stop $host" >>$sh
200
local agents i line stat sh trunk branch atexit_num host hosts
202
if [ $# -eq 0 ]; then
203
agents=($opt_cfgsdir/*)
208
for agent in "${agents[@]}"; do
210
agent="$(basename "$agent")"
211
rm -f $CASES_DIR/*_${agent}.sh
212
rm -f $CASES_DIR/${agent}_setup
214
echo "Making '$agent': "
215
preparse_cfg "$agent"
216
while read -r line; do
217
line_num="${line##* }"
222
case "${trunk[0]}" in
236
sh="$CASES_DIR/${i}_${agent}.sh"
237
echo " - case ${i}: ${branch[0]}"
242
# Summary: ${branch[0]}
244
. $OCFT_DIR/caselib || {
245
echo "ERROR: '$OCFT_DIR/caselib' not found."
249
MYROOT="$cfg_agent_root"
251
if [ -n "$cfg_install_package" ]; then
253
agent_install ${cfg_install_package[@]}
256
if [ -r "$CASES_DIR/${agent}_setup" ]; then
258
agent_setup $agent <<'CMD'
259
$(cat "$CASES_DIR/${agent}_setup")
264
if [ -n "\$OCFT_VERBOSE" ]; then
265
echo -e $(add_quotes 1 "Starting '\\033[33m${agent}\\033[0m' case $i '\\033[33m${branch[0]}\\033[0m':")
267
echo -n "'${agent}' case ${i}: "
279
case "${trunk[0]}" in
282
cfg_agent_root="${branch[0]}"
286
cfg_install_package=("${branch[@]}")
290
if ! echo "${branch[0]}" | grep -qxE '[0-9]+'; then
291
parse_die "numeric argument required."
293
cfg_hang_timeout="${branch[0]}"
296
parse_die "unimplemented statement: ${trunk[0]}"
301
echo "$line" >>$CASES_DIR/${agent}_setup
304
host=$(echo ${trunk[0]} | awk -F@ '{print $2}')
305
if [ -n "$host" ]; then
306
if ! echo "$hosts" | grep -q "$host"; then
307
hosts=$hosts$'\n'$host
309
# Initialize remote shell
312
OCFT_VERBOSE=\$OCFT_VERBOSE
315
backbash $host <$OCFT_DIR/caselib
316
backbash $host <<'CMD'
317
MYROOT="$cfg_agent_root"
319
if [ -n "$cfg_install_package" ]; then
321
agent_install ${cfg_install_package[@]}
324
if [ -r "$CASES_DIR/${agent}_setup" ]; then
326
agent_setup $agent <<'END'
327
$(cat "$CASES_DIR/${agent}_setup")
336
# CASE statement: $line" >>$sh
338
if [ -n "$host" ]; then
339
echo "backbash $host <<'CMD'" >>$sh
342
case "${trunk[0]}" in
345
if [ -n "\$OCFT_VERBOSE" ]; then
346
echo $(add_quotes 2 " \${showhost}Setting agent environment: export ${trunk[1]}")
349
check_success \$? $(add_quotes 1 "export ${trunk[1]}")
354
if [ -n "\$OCFT_VERBOSE" ]; then
355
echo $(add_quotes 2 " \${showhost}Removing agent environment: unset ${trunk[1]}")
358
check_success \$? $(add_quotes 1 "unset ${trunk[1]}")
363
if [ -z "${branch[1]}" ]; then
364
if [ "${branch[0]}" = "start" ]; then
366
agent_run $(add_quotes 1 "$agent") status $cfg_hang_timeout
368
if [ \$rc -eq \$OCF_ERR_UNIMPLEMENTED ]; then
369
agent_run $(add_quotes 1 "$agent") monitor $cfg_hang_timeout
373
if [ \$rc -eq \$OCF_SUCCESS ]; then
374
: #The status I want, so I can do nothing.
375
elif [ \$rc -eq \$OCF_NOT_RUNNING ]; then
376
if [ -n "\$OCFT_VERBOSE" ]; then
377
echo $(add_quotes 2 " \${showhost}Running agent: ./$agent start")
379
agent_run $(add_quotes 1 "$agent") start $cfg_hang_timeout
380
check_success \$? $(add_quotes 1 "./$agent start")
382
check_success \$rc $(add_quotes 1 "./$agent status|monitor")
385
elif [ "${branch[0]}" = "stop" ]; then
387
agent_run $(add_quotes 1 "$agent") status $cfg_hang_timeout
389
if [ \$rc -eq \$OCF_ERR_UNIMPLEMENTED ]; then
390
agent_run $(add_quotes 1 "$agent") monitor $cfg_hang_timeout
394
if [ \$rc -eq \$OCF_NOT_RUNNING ]; then
395
: #The status I want, so I can do nothing.
396
elif [ \$rc -eq \$OCF_SUCCESS ]; then
397
if [ -n "\$OCFT_VERBOSE" ]; then
398
echo $(add_quotes 2 " \${showhost}Running agent: ./$agent stop")
400
agent_run $(add_quotes 1 "$agent") stop $cfg_hang_timeout
401
check_success \$? $(add_quotes 1 "./$agent stop")
403
check_success \$rc $(add_quotes 1 "./$agent status|monitor")
406
elif [ "${branch[0]}" = "status" -o "${branch[0]}" = "monitor" ]; then
408
agent_run $(add_quotes 1 "$agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
412
agent_run $(add_quotes 1 "$agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
413
check_success \$? $(add_quotes 1 "./$agent ${branch[0]}")
418
test -n $(add_quotes 2 "\$${branch[1]}")
419
check_success \$? $(add_quotes 1 "test -n \"\$${branch[1]}\"")
420
if [ -n "\$OCFT_VERBOSE" ]; then
421
echo $(add_quotes 2 " \${showhost}Running agent: ./$agent ${branch[0]}")
423
agent_run $(add_quotes 1 "$agent") $(add_quotes 1 "${branch[0]}") $cfg_hang_timeout
425
if [ -n "\$OCFT_VERBOSE" ]; then
426
echo -n " \${showhost}Checking return value:"
428
if [ -n "\${retval[ret]}" ]; then
429
retstr="\${retval[ret]}"
433
if [ \$ret -eq \$${branch[1]} ]; then
434
if [ -n "\$OCFT_VERBOSE" ]; then
435
echo -e $(add_quotes 2 " \\033[32mOK\\033[0m. The return value '\\033[34m\$retstr\\033[0m' == '\\033[34m${branch[1]}\\033[0m'")
437
echo -e "\t\\033[32mOK\\033[0m."
440
if [ -n "\$OCFT_VERBOSE" ]; then
441
echo -en $(add_quotes 2 " \\033[31mFAILED\\033[0m. The return value '\\033[34m\$retstr\\033[0m' != '\\033[34m${branch[1]}\\033[0m'. ")
443
echo -en "\t\\033[31mFAILED\\033[0m. Agent returns unexpected value: '\$retstr'. "
445
echo "See details below:"
446
cat /tmp/.ocft_runlog
455
if [ -n "\$OCFT_VERBOSE" ]; then
456
echo $(add_quotes 2 " \${showhost}Setting system environment: ${trunk[1]}")
458
echo $(add_quotes 1 "${trunk[1]}") | /bin/bash
459
check_success \$? $(add_quotes 1 "${trunk[1]}")
462
BashAtExit|BashAtExit@*)
465
atexit${atexit_num}()
467
if [ -n "\$OCFT_VERBOSE" ]; then
468
echo $(add_quotes 2 " \${showhost}Setting system environment: ${trunk[1]}")
470
echo $(add_quotes 1 "${trunk[1]}") | /bin/bash
476
parse_die "unimplemented statement: ${trunk[0]}"
479
if [ -n "$host" ]; then
484
parse_die "unimplemented statement: ${trunk[0]}"
487
done <$CASES_DIR/${agent}.preparse
488
rm -f $CASES_DIR/${agent}.preparse
489
rm -f $CASES_DIR/${agent}_setup
496
local sh shs agents line ret
498
if ! cd $CASES_DIR >/dev/null 2>&1; then
499
die "cases directory not found."
502
export OCFT_VERBOSE=$opt_verbose
504
if [ $# -eq 0 ]; then
505
agents=($(ls -1 *.sh 2>/dev/null | sed 's/.*_\([^_]*\)\.sh$/\1/' | sort | uniq))
510
for shs in "${agents[@]}"; do
511
for sh in $(ls -1 *_${shs}.sh 2>/dev/null | sort -n); do
514
if [ $ret -eq 3 ]; then
515
die "core function failed, break all tests."
517
if [ $ret -eq 2 ]; then
518
warn "core function failed, break all tests of '$shs'."
522
done | while read -r line; do
524
echo "$(date '+%F %T'): $line" | cat -A |
525
sed -r 's/\^\[\[[0-9]+m|\^I|.$//g' >>ocft.log
533
if [ $# -eq 0 ]; then
534
rm -f $CASES_DIR/*.sh
537
rm -f $CASES_DIR/*_${shs}.sh
545
$0 ACTION [OPTION] [agent1 [agent2] [...]]
547
make [-d dir] Generate the testing shell scripts.
548
-d The directory that contains
549
configuration of cases.
550
test [-v] Execute the testing shell scripts.
551
-v Verbose output mode.
552
clean Delete the testing shell scripts.
553
help [-v] Show this help and exit.
554
-v Show HOWTO and exit.
556
See '$OCFT_DIR/README' for detail.
565
- Ocft is a testing tool for resource agents. Instead of the policy of HA,
566
it mainly concerns whether resource agents run correct locally. It can
567
design types of complicated environments to test the reliability of
568
resource agents. Precisely, it is to display whether resource agents can
569
return to correct or expected value. The advantage of the tool provides
570
us with competence to design conditions which can be recorded or reproduced.
571
Hence it is useful to debuggers.
574
** Test case generator (@sbindir@/ocft)
575
- Turning configuration files of test case to executable scripts.
577
** Configuration file ($CONFIGS_DIR/)
578
- Every configuration file directs only one resource agent and share the same
579
name with resource agent but contains more test cases.
581
** The testing script ($CASES_DIR/)
582
- After the generator reads configuration files and generates many testing
583
scripts and the script is underway, the test begins.
585
* How to customize the environment of testing
586
- Ocft designs the running conditions through two ways, one is changing the
587
environment variables of resource agents (it is the interface left by OCF itself),
588
the other is modifying the OS environment of resource agents, such as altering
589
the permission of some key file or IP address of the machine.
592
- Firstly, you need to sketch the all complex and uncommon environments against
593
a certain resource agent and keep in mind what consequences may be caused by
594
these uncommon environments.
595
Secondly, write the designed conditions and foreknown consequences into
596
configuration files, and then run the generator to translate the test case to
598
Finally, you need running these scripts to observe the output and learn
599
the running status of each test case, which will compares the predicated result
600
with the actual one. If they differ, you will be able to find the bugs of the
609
OCFT_DIR=@datadir@/@PACKAGE_NAME@/ocft
610
CONFIGS_DIR=@datadir@/@PACKAGE_NAME@/ocft/configs
611
CASES_DIR=/var/lib/@PACKAGE_NAME@/ocft/cases
617
# default configuration
624
opt_cfgsdir=$CONFIGS_DIR
631
if [ "$1" = "-d" ]; then
632
if [ ! -d "$2" ]; then
639
if [ ! -d "$CASES_DIR" ]; then
640
mkdir -p "$CASES_DIR" || die "Can not create directory: ${CASES_DIR}."
645
if [ "$1" = "-v" ]; then
655
if [ "$1" = "-v" ]; then