subcommand 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ #!/bin/sh
2
+ test_description="Testing out boo_zoo "
3
+ . ./test-lib.sh
4
+
5
+
6
+
7
+
8
+ test_todo_session "Testing of boo_zoo" <<EOF
9
+ >>> ruby bin/subcommand.rb boo
10
+ cmd: foo
11
+ options ......
12
+ {:force=>true}
13
+ ARGV:
14
+ []
15
+ >>> end
16
+ >>> ruby bin/subcommand.rb boo ruby
17
+ cmd: foo
18
+ options ......
19
+ {:force=>true}
20
+ ARGV:
21
+ ["ruby"]
22
+ >>> end
23
+ >>> ruby bin/subcommand.rb zoo
24
+ cmd: foo
25
+ options ......
26
+ {}
27
+ ARGV:
28
+ ["ruby"]
29
+ >>> end
30
+ >>> ruby bin/subcommand.rb zoo duby
31
+ cmd: foo
32
+ options ......
33
+ {}
34
+ ARGV:
35
+ ["ruby", "duby"]
36
+ >>> end
37
+ >>> ruby bin/subcommand.rb help zoo
38
+ Usage: foo [options]
39
+ desc for foo
40
+ -f, --[no-]force force verbosely
41
+ >>> end
42
+
43
+ EOF
44
+ test_done
data/tests/test-lib.sh ADDED
@@ -0,0 +1,618 @@
1
+ #!/bin/sh
2
+ #
3
+ # Copyright (c) 2005 Junio C Hamano
4
+ #
5
+
6
+ # if --tee was passed, write the output not only to the terminal, but
7
+ # additionally to the file test-results/$BASENAME.out, too.
8
+ case "$TEST_TEE_STARTED, $* " in
9
+ done,*)
10
+ # do not redirect again
11
+ ;;
12
+ *' --tee '*|*' --va'*)
13
+ mkdir -p test-results
14
+ BASE=test-results/$(basename "$0" .sh)
15
+ (TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1;
16
+ echo $? > $BASE.exit) | tee $BASE.out
17
+ test "$(cat $BASE.exit)" = 0
18
+ exit
19
+ ;;
20
+ esac
21
+
22
+ # Keep the original TERM for say_color
23
+ ORIGINAL_TERM=$TERM
24
+
25
+ # For repeatability, reset the environment to known value.
26
+ LANG=C
27
+ LC_ALL=C
28
+ PAGER=cat
29
+ TZ=UTC
30
+ TERM=dumb
31
+ export LANG LC_ALL PAGER TERM TZ
32
+ EDITOR=:
33
+ VISUAL=:
34
+
35
+ # Protect ourselves from common misconfiguration to export
36
+ # CDPATH into the environment
37
+ unset CDPATH
38
+
39
+ # Protect ourselves from using predefined TODOTXT_CFG_FILE
40
+ unset TODOTXT_CFG_FILE $(set|sed '/^TODOTXT_/!d;s/=.*//')
41
+ # To prevent any damage if someone has still those exported somehow in his env:
42
+ unset TODO_FILE DONE_FILE REPORT_FILE TMP_FILE
43
+
44
+ # Each test should start with something like this, after copyright notices:
45
+ #
46
+ # test_description='Description of this test...
47
+ # This test checks if command xyzzy does the right thing...
48
+ # '
49
+ # . ./test-lib.sh
50
+ [ "x$ORIGINAL_TERM" != "xdumb" ] && (
51
+ TERM=$ORIGINAL_TERM &&
52
+ export TERM &&
53
+ [ -t 1 ] &&
54
+ tput bold >/dev/null 2>&1 &&
55
+ tput setaf 1 >/dev/null 2>&1 &&
56
+ tput sgr0 >/dev/null 2>&1
57
+ ) &&
58
+ color=t
59
+
60
+ while test "$#" -ne 0
61
+ do
62
+ case "$1" in
63
+ -d|--d|--de|--deb|--debu|--debug)
64
+ debug=t; shift ;;
65
+ -i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
66
+ immediate=t; shift ;;
67
+ -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
68
+ TODOTXT_TEST_LONG=t; export TODOTXT_TEST_LONG; shift ;;
69
+ -h|--h|--he|--hel|--help)
70
+ help=t; shift ;;
71
+ -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
72
+ verbose=t; shift ;;
73
+ -q|--q|--qu|--qui|--quie|--quiet)
74
+ quiet=t; shift ;;
75
+ --no-color)
76
+ color=; shift ;;
77
+ --no-python)
78
+ # noop now...
79
+ shift ;;
80
+ --tee)
81
+ shift ;; # was handled already
82
+ *)
83
+ break ;;
84
+ esac
85
+ done
86
+
87
+ if test -n "$color"; then
88
+ say_color () {
89
+ (
90
+ TERM=$ORIGINAL_TERM
91
+ export TERM
92
+ case "$1" in
93
+ error) tput bold; tput setaf 1;; # bold red
94
+ skip) tput bold; tput setaf 2;; # bold green
95
+ pass) tput setaf 2;; # green
96
+ info) tput setaf 3;; # brown
97
+ *) test -n "$quiet" && return;;
98
+ esac
99
+ shift
100
+ printf "* %s" "$*"
101
+ tput sgr0
102
+ echo
103
+ )
104
+ }
105
+ else
106
+ say_color() {
107
+ test -z "$1" && test -n "$quiet" && return
108
+ shift
109
+ echo "* $*"
110
+ }
111
+ fi
112
+
113
+ error () {
114
+ say_color error "error: $*"
115
+ trap - EXIT
116
+ exit 1
117
+ }
118
+
119
+ say () {
120
+ say_color info "$*"
121
+ }
122
+
123
+ test "${test_description}" != "" ||
124
+ error "Test script did not set test_description."
125
+
126
+ if test "$help" = "t"
127
+ then
128
+ echo "$test_description"
129
+ exit 0
130
+ fi
131
+
132
+ exec 5>&1
133
+ if test "$verbose" = "t"
134
+ then
135
+ exec 4>&2 3>&1
136
+ else
137
+ exec 4>/dev/null 3>/dev/null
138
+ fi
139
+
140
+ test_failure=0
141
+ test_count=0
142
+ test_fixed=0
143
+ test_broken=0
144
+ test_success=0
145
+
146
+ die () {
147
+ echo >&5 "FATAL: Unexpected exit with code $?"
148
+ exit 1
149
+ }
150
+
151
+ trap 'die' EXIT
152
+
153
+ # The semantics of the editor variables are that of invoking
154
+ # sh -c "$EDITOR \"$@\"" files ...
155
+ #
156
+ # If our trash directory contains shell metacharacters, they will be
157
+ # interpreted if we just set $EDITOR directly, so do a little dance with
158
+ # environment variables to work around this.
159
+ #
160
+ # In particular, quoting isn't enough, as the path may contain the same quote
161
+ # that we're using.
162
+ test_set_editor () {
163
+ FAKE_EDITOR="$1"
164
+ export FAKE_EDITOR
165
+ VISUAL='"$FAKE_EDITOR"'
166
+ export VISUAL
167
+ }
168
+
169
+ # You are not expected to call test_ok_ and test_failure_ directly, use
170
+ # the text_expect_* functions instead.
171
+
172
+ test_ok_ () {
173
+ test_success=$(($test_success + 1))
174
+ say_color "" " ok $test_count: $@"
175
+ }
176
+
177
+ test_failure_ () {
178
+ test_failure=$(($test_failure + 1))
179
+ say_color error "FAIL $test_count: $1"
180
+ shift
181
+ echo "$@" | sed -e 's/^/ /'
182
+ test "$immediate" = "" || { trap - EXIT; exit 1; }
183
+ }
184
+
185
+ test_known_broken_ok_ () {
186
+ test_fixed=$(($test_fixed+1))
187
+ say_color "" " FIXED $test_count: $@"
188
+ }
189
+
190
+ test_known_broken_failure_ () {
191
+ test_broken=$(($test_broken+1))
192
+ say_color skip " still broken $test_count: $@"
193
+ }
194
+
195
+ test_debug () {
196
+ test "$debug" = "" || eval "$1"
197
+ }
198
+
199
+ test_run_ () {
200
+ eval >&3 2>&4 "$1"
201
+ eval_ret="$?"
202
+ return 0
203
+ }
204
+
205
+ test_skip () {
206
+ test_count=$(($test_count+1))
207
+ to_skip=
208
+ for skp in $SKIP_TESTS
209
+ do
210
+ case $this_test.$test_count in
211
+ $skp)
212
+ to_skip=t
213
+ esac
214
+ done
215
+ case "$to_skip" in
216
+ t)
217
+ say_color skip >&3 "skipping test: $@"
218
+ say_color skip "skip $test_count: $1"
219
+ : true
220
+ ;;
221
+ *)
222
+ false
223
+ ;;
224
+ esac
225
+ }
226
+
227
+ test_expect_failure () {
228
+ test "$#" = 2 ||
229
+ error "bug in the test script: not 2 parameters to test-expect-failure"
230
+ if ! test_skip "$@"
231
+ then
232
+ say >&3 "checking known breakage: $2"
233
+ test_run_ "$2"
234
+ if [ "$?" = 0 -a "$eval_ret" = 0 ]
235
+ then
236
+ test_known_broken_ok_ "$1"
237
+ else
238
+ test_known_broken_failure_ "$1"
239
+ fi
240
+ fi
241
+ echo >&3 ""
242
+ }
243
+
244
+ test_expect_success () {
245
+ test "$#" = 2 ||
246
+ error "bug in the test script: not 2 parameters to test-expect-success"
247
+ if ! test_skip "$@"
248
+ then
249
+ say >&3 "expecting success: $2"
250
+ test_run_ "$2"
251
+ if [ "$?" = 0 -a "$eval_ret" = 0 ]
252
+ then
253
+ test_ok_ "$1"
254
+ else
255
+ test_failure_ "$@"
256
+ fi
257
+ fi
258
+ echo >&3 ""
259
+ }
260
+
261
+ test_expect_code () {
262
+ test "$#" = 3 ||
263
+ error "bug in the test script: not 3 parameters to test-expect-code"
264
+ if ! test_skip "$@"
265
+ then
266
+ say >&3 "expecting exit code $1: $3"
267
+ test_run_ "$3"
268
+ if [ "$?" = 0 -a "$eval_ret" = "$1" ]
269
+ then
270
+ test_ok_ "$2"
271
+ else
272
+ test_failure_ "$@"
273
+ fi
274
+ fi
275
+ echo >&3 ""
276
+ }
277
+
278
+ # test_external runs external test scripts that provide continuous
279
+ # test output about their progress, and succeeds/fails on
280
+ # zero/non-zero exit code. It outputs the test output on stdout even
281
+ # in non-verbose mode, and announces the external script with "* run
282
+ # <n>: ..." before running it. When providing relative paths, keep in
283
+ # mind that all scripts run in "trash directory".
284
+ # Usage: test_external description command arguments...
285
+ # Example: test_external 'Perl API' perl ../path/to/test.pl
286
+ test_external () {
287
+ test "$#" -eq 3 ||
288
+ error >&5 "bug in the test script: not 3 parameters to test_external"
289
+ descr="$1"
290
+ shift
291
+ if ! test_skip "$descr" "$@"
292
+ then
293
+ # Announce the script to reduce confusion about the
294
+ # test output that follows.
295
+ say_color "" " run $test_count: $descr ($*)"
296
+ # Run command; redirect its stderr to &4 as in
297
+ # test_run_, but keep its stdout on our stdout even in
298
+ # non-verbose mode.
299
+ "$@" 2>&4
300
+ if [ "$?" = 0 ]
301
+ then
302
+ test_ok_ "$descr"
303
+ else
304
+ test_failure_ "$descr" "$@"
305
+ fi
306
+ fi
307
+ }
308
+
309
+ # Like test_external, but in addition tests that the command generated
310
+ # no output on stderr.
311
+ test_external_without_stderr () {
312
+ # The temporary file has no (and must have no) security
313
+ # implications.
314
+ tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
315
+ stderr="$tmp/todotxt-external-stderr.$$.tmp"
316
+ test_external "$@" 4> "$stderr"
317
+ [ -f "$stderr" ] || error "Internal error: $stderr disappeared."
318
+ descr="no stderr: $1"
319
+ shift
320
+ say >&3 "expecting no stderr from previous command"
321
+ if [ ! -s "$stderr" ]; then
322
+ rm "$stderr"
323
+ test_ok_ "$descr"
324
+ else
325
+ if [ "$verbose" = t ]; then
326
+ output=`echo; echo Stderr is:; cat "$stderr"`
327
+ else
328
+ output=
329
+ fi
330
+ # rm first in case test_failure exits.
331
+ rm "$stderr"
332
+ test_failure_ "$descr" "$@" "$output"
333
+ fi
334
+ }
335
+
336
+ # This is not among top-level (test_expect_success | test_expect_failure)
337
+ # but is a prefix that can be used in the test script, like:
338
+ #
339
+ # test_expect_success 'complain and die' '
340
+ # do something &&
341
+ # do something else &&
342
+ # test_must_fail git checkout ../outerspace
343
+ # '
344
+ #
345
+ # Writing this as "! git checkout ../outerspace" is wrong, because
346
+ # the failure could be due to a segv. We want a controlled failure.
347
+
348
+ test_must_fail () {
349
+ "$@"
350
+ test $? -gt 0 -a $? -le 129 -o $? -gt 192
351
+ }
352
+
353
+ # test_cmp is a helper function to compare actual and expected output.
354
+ # You can use it like:
355
+ #
356
+ # test_expect_success 'foo works' '
357
+ # echo expected >expected &&
358
+ # foo >actual &&
359
+ # test_cmp expected actual
360
+ # '
361
+ #
362
+ # This could be written as either "cmp" or "diff -u", but:
363
+ # - cmp's output is not nearly as easy to read as diff -u
364
+ # - not all diff versions understand "-u"
365
+
366
+ test_cmp() {
367
+ diff -u "$@"
368
+ }
369
+
370
+ test_done () {
371
+ trap - EXIT
372
+ test_results_dir="$TEST_DIRECTORY/test-results"
373
+ mkdir -p "$test_results_dir"
374
+ test_results_path="$test_results_dir/${0%.sh}-$$"
375
+
376
+ echo "total $test_count" >> $test_results_path
377
+ echo "success $test_success" >> $test_results_path
378
+ echo "fixed $test_fixed" >> $test_results_path
379
+ echo "broken $test_broken" >> $test_results_path
380
+ echo "failed $test_failure" >> $test_results_path
381
+ echo "" >> $test_results_path
382
+
383
+ if test "$test_fixed" != 0
384
+ then
385
+ say_color pass "fixed $test_fixed known breakage(s)"
386
+ fi
387
+ if test "$test_broken" != 0
388
+ then
389
+ say_color error "still have $test_broken known breakage(s)"
390
+ msg="remaining $(($test_count-$test_broken)) test(s)"
391
+ else
392
+ msg="$test_count test(s)"
393
+ fi
394
+ case "$test_failure" in
395
+ 0)
396
+ say_color pass "passed all $msg"
397
+
398
+ # Clean up this test.
399
+ test -d "$remove_trash" &&
400
+ cd "$(dirname "$remove_trash")" &&
401
+ rm -rf "$(basename "$remove_trash")"
402
+
403
+ exit 0 ;;
404
+
405
+ *)
406
+ say_color error "failed $test_failure among $msg"
407
+ exit 1 ;;
408
+
409
+ esac
410
+ }
411
+
412
+ # Use -P to resolve symlinks in our working directory so that the pwd
413
+ # in subprocesses equals our $PWD (for pathname comparisons).
414
+ cd -P .
415
+
416
+ # Record our location for reference.
417
+ TEST_DIRECTORY=$(pwd)
418
+
419
+ # Test repository
420
+ #test="trash directory.$(basename "$0" .sh)" # RK CHANGED
421
+ test="trashdirectory.$(basename "$0" .sh)"
422
+ test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
423
+ rm -fr "$test" || {
424
+ trap - EXIT
425
+ echo >&5 "FATAL: Cannot prepare test area"
426
+ exit 1
427
+ }
428
+
429
+ # Most tests can use the created repository, but some may need to create more.
430
+ # Usage: test_init_todo <directory>
431
+ test_init_todo () {
432
+ test "$#" = 1 ||
433
+ error "bug in the test script: not 1 parameter to test_init_todo"
434
+ owd=`pwd`
435
+ root="$1"
436
+ mkdir -p "$root"
437
+ cd "$root" || error "Cannot setup todo dir in $root"
438
+ # Initialize the configuration file. Carefully quoted.
439
+ #sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' $TEST_DIRECTORY/../todo.cfg > todo.cfg
440
+
441
+ # Install latest todo.sh
442
+ mkdir bin
443
+ # TODO: XXX
444
+ #ln -s "$TEST_DIRECTORY/../todoapp.sh" bin/todoapp.sh
445
+ # ln -s ~/bin/todorb bin/todorb
446
+ ln -s ../../../lib/subcommand.rb bin/subcommand.rb
447
+
448
+ # Initialize a hack date script
449
+ TODO_TEST_REAL_DATE=$(which date)
450
+ TODO_TEST_TIME=1234500000
451
+ export PATH TODO_TEST_REAL_DATE TODO_TEST_TIME
452
+
453
+ # Trying to detect the version of "date" on current system
454
+ DATE_STYLE=unknown
455
+ # on GNU systems (versions may vary):
456
+ #date --version
457
+ #date (GNU coreutils) 6.10
458
+ #...
459
+ if date --version 2>&1 | grep -q "GNU"; then
460
+ DATE_STYLE=GNU
461
+ # on Mac OS X 10.5:
462
+ #date --version
463
+ #date: illegal option -- -
464
+ #usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
465
+ #[-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
466
+ elif date --version 2>&1 | grep -q -e "-jnu"; then
467
+ DATE_STYLE=Mac10.5
468
+ # on Mac OS X 10.4:
469
+ #date --version
470
+ #date: illegal option -- -
471
+ #usage: date [-nu] [-r seconds] [+format]
472
+ # date [[[[[cc]yy]mm]dd]hh]mm[.ss]
473
+ elif date --version 2>&1 | grep -q -e "-nu"; then
474
+ DATE_STYLE=Mac10.4
475
+ fi
476
+
477
+ case $DATE_STYLE in
478
+ GNU)
479
+ cat > bin/date <<-EOF
480
+ #!/bin/sh
481
+ exec "$TODO_TEST_REAL_DATE" -d @\$TODO_TEST_TIME \$@
482
+ EOF
483
+ chmod 755 bin/date
484
+ ;;
485
+ Mac10.5)
486
+ cat > bin/date <<-EOF
487
+ #!/bin/sh
488
+ exec "$TODO_TEST_REAL_DATE" -j -f %s \$TODO_TEST_TIME \$@
489
+ EOF
490
+ chmod 755 bin/date
491
+ ;;
492
+ Mac10.4)
493
+ cat > bin/date <<-EOF
494
+ #!/bin/sh
495
+ exec "$TODO_TEST_REAL_DATE" -r \$TODO_TEST_TIME \$@
496
+ EOF
497
+ chmod 755 bin/date
498
+ ;;
499
+ *)
500
+ echo "WARNING: Current date executable not recognized"
501
+ echo "So today date will be used, expect false negative tests..."
502
+ ;;
503
+ esac
504
+
505
+ # Ensure a correct PATH for testing.
506
+ PATH=$owd/$root/bin:$PATH
507
+ export PATH
508
+
509
+ cd "$owd"
510
+ }
511
+
512
+ # Usage: test_tick [increment]
513
+ test_tick () {
514
+ TODO_TEST_TIME=$(($TODO_TEST_TIME + ${1:-86400}))
515
+ }
516
+
517
+ # Generate and run a series of tests based on a transcript.
518
+ # Usage: test_todo_session "description" <<EOF
519
+ # >>> command
520
+ # output1
521
+ # output2
522
+ # >>> command
523
+ # === exit status
524
+ # output3
525
+ # output4
526
+ # EOF
527
+ test_todo_session () {
528
+ test "$#" = 1 ||
529
+ error "bug in the test script: extra args to test_todo_session"
530
+ subnum=1
531
+ cmd=""
532
+ status=0
533
+ > expect
534
+ #while read line
535
+ # earlier the program would stop expect on a blank line which is unacceptable
536
+ # i pass an explicit end, since my output does have blank lines
537
+ while IFS='' read line
538
+ do
539
+ case $line in
540
+ ">>> end")
541
+ if [ ! -z "$cmd" ]; then
542
+ if [ $status = 0 ]; then
543
+ test_expect_success "$1 $subnum" "$cmd > output && test_cmp expect output"
544
+ else
545
+ #test_expect_success "$1 $subnum" "$cmd > output || test $? = $status && test_cmp expect output"
546
+ test_expect_success "$1 $subnum" "$cmd > output 2>&1 || test $? = $status && test_cmp expect output"
547
+ fi
548
+
549
+ subnum=$(($subnum + 1))
550
+ cmd=""
551
+ status=0
552
+ > expect
553
+ fi
554
+ ;;
555
+ ">>> "*)
556
+ test -z "$cmd" || error "bug in the test script: missing blank line separator in test_todo_session"
557
+ cmd=${line#>>> }
558
+ ;;
559
+ "=== "*)
560
+ status=${line#=== }
561
+ ;;
562
+ *)
563
+ # WARNING please NOTE XXX that a blank line in output terminates what goes into expect !!! See above
564
+ echo "$line" >> expect
565
+ ;;
566
+ esac
567
+ done
568
+ if [ ! -z "$cmd" ]; then
569
+ if [ $status = 0 ]; then
570
+ test_expect_success "$1 $subnum" "$cmd > output && test_cmp expect output"
571
+ else
572
+ test_expect_success "$1 $subnum" "$cmd > output || test $? = $status && test_cmp expect output"
573
+ fi
574
+ fi
575
+ }
576
+
577
+ test_shell () {
578
+ trap - EXIT
579
+ export PS1='$(ret_val=$?; [ "$ret_val" != "0" ] && echo -e "=== $ret_val\n\n>>> "||echo "\n>>> ")'
580
+ cat <<EOF
581
+ Do your tests session here and
582
+ don't forget to replace the hardcoded path with \$HOME in the transcript:
583
+ $HOME/todo.txt => \$HOME/todo.txt
584
+ EOF
585
+ bash --noprofile --norc
586
+ exit 0
587
+ }
588
+
589
+ test_init_todo "$test"
590
+ # Use -P to resolve symlinks in our working directory so that the pwd
591
+ # in subprocesses equals our $PWD (for pathname comparisons).
592
+ cd -P "$test" || exit 1
593
+
594
+ # Since todo.sh refers to the home directory often,
595
+ # make sure we don't accidentally grab the tester's config
596
+ # but use something specified by the framework.
597
+ HOME=$(pwd)
598
+ export HOME
599
+
600
+ this_test=${0##*/}
601
+ this_test=${this_test%%-*}
602
+ for skp in $SKIP_TESTS
603
+ do
604
+ to_skip=
605
+ for skp in $SKIP_TESTS
606
+ do
607
+ case "$this_test" in
608
+ $skp)
609
+ to_skip=t
610
+ esac
611
+ done
612
+ case "$to_skip" in
613
+ t)
614
+ say_color skip >&3 "skipping test $this_test altogether"
615
+ say_color skip "skip all tests in $this_test"
616
+ test_done
617
+ esac
618
+ done