run-tests.sh 15.3 KB
Newer Older
Daniel Barlow's avatar
Daniel Barlow committed
1 2
#!/bin/sh

3
# run-tests {lisp invocation} {scripts-regex}
4 5 6 7
# - read lisp forms one at a time from standard input
# - quit with exit status 0 on getting eof
# - quit with exit status >0 if an unhandled error occurs

8 9 10 11 12 13
usage () {
    echo "$0 [lisp invocation] [scripts-regex]"
    echo " - read lisp forms one at a time from matching scripts"
    echo " - quit with exit status 0 on getting eof"
    echo " - quit with exit status >0 if an unhandled error occurs"
    echo " you need to supply the .script in the second argument"
14
    echo " lisps include abcl, allegro, allegromodern, ccl (clozure),"
15
    echo "  clisp, cmucl, ecl, gcl, gclcvs, sbcl, scl and xcl."
16 17
    echo "OPTIONS:"
    echo "    -d -- debug mode"
18 19
    echo "    -h -- show this message."
    echo "    -u -- upgrade tests."
20 21
    echo "    -c -- clean load test"
    echo "    -l -- load systems tests"
22
    echo "    -t -- test interactively"
23
    echo "    -H -- extract all asdf versions to upgrade from"
24 25
}

26
unset DEBUG_ASDF_TEST upgrade clean_load load_systems test_interactively extract_all
27
SHELL=/bin/sh
28
export SHELL DEBUG_ASDF_TEST GCL_ANSI ASDF_OUTPUT_TRANSLATIONS
Robert P. Goldman's avatar
 
Robert P. Goldman committed
29

30
while getopts "cdtHulhu" OPTION
Robert P. Goldman's avatar
 
Robert P. Goldman committed
31
do
32
    case $OPTION in
Robert P. Goldman's avatar
 
Robert P. Goldman committed
33
        d)
34
            DEBUG_ASDF_TEST=t
Robert P. Goldman's avatar
 
Robert P. Goldman committed
35 36
            ;;
        u)
37
            upgrade=t
Robert P. Goldman's avatar
 
Robert P. Goldman committed
38
            ;;
39 40 41
        c)
            clean_load=t
            ;;
42 43 44
        l)
            load_systems=t
            ;;
45 46 47
        t)
            test_interactively=t
            ;;
48 49 50
        H)
            extract_all=t
            ;;
Robert P. Goldman's avatar
 
Robert P. Goldman committed
51 52 53 54 55 56 57
        h)
            usage
            exit 1
            ;;
    esac
done
shift $(($OPTIND - 1))
58

59
if [ x"$1" = "xhelp" ]; then
Robert P. Goldman's avatar
 
Robert P. Goldman committed
60 61
    usage
    exit 1
62
fi
63
lisp=${1:-sbcl} ; shift
64

65

66 67 68 69 70 71 72 73 74 75 76 77 78
ECHO () { printf '%s\n' "$*" ;}
ECHOn () { printf '%s' "$*" ;}
DBG () { ECHO "$*" >& 2 ;}
simple_term_p () {
  case "$1" in *[!a-zA-Z0-9-+_,.:=%/]*) return 1 ;; *) return 0 ;; esac
}
kwote0 () { ECHOn "$1" | sed -e "s/\([\\\\\"\$\`]\)/\\\\\\1/g" ;}
kwote1 () { if simple_term_p "$1" ; then ECHOn "$1"
  else ECHOn "\"$(kwote0 "$1")\"" ; fi ;}
kwote () { ( set +x
  k="" ; for i ; do ECHOn "$k" ; kwote1 "$i" ; k=" " ; done ; echo
) }
DO () { kwote "$@" ; "$@" ; }
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
79

80
do_tests () {
81 82 83 84 85
  if [ -z "$*" ]; then
       scripts="*.script"
  else
       scripts="$*"
  fi
86
  env | grep -i asdf
87
  rm -f ~/.cache/common-lisp/"`pwd`"/* || true
88 89 90
  ## We go through great lengths to avoid " in the command line,
  ## the quoting of which some Windows implementations get wrong.
  ## While we're at it, we also avoid spaces and backslashes.
91
  ( cd .. && DO $bcmd $eval '(or #.(load(string`|test/script-support.lisp|))#.(asdf-test::compile-asdf-script))' )
92 93
  if [ $? -ne 0 ] ; then
    echo "Compilation FAILED" >&2
94 95 96
    echo "you can retry compilation with:" >&2
    echo ./test/run-tests.sh $lisp >&2
    echo "or more interactively (and maybe with rlwrap or in emacs), start with:" >&2
97
    echo "$icmd" >&2
98 99
    echo "then copy/paste:" >&2
    echo '(load "test/script-support.lisp") (asdf-test::compile-asdf-script)' >&2
100 101
  else
    echo "Compiled OK" >&2
102 103 104 105
    test_count=0
    test_pass=0
    test_fail=0
    failed_list=""
106 107
    for i in $scripts ;
    do
108 109
      echo "Testing: $i" >&2
      test_count=`expr "$test_count" + 1`
110
      rm -f ~/.cache/common-lisp/"`pwd`"/* || true
111
      if DO $bcmd $eval "'(#.(load(string'|script-support.lisp|))#.(asdf-test::load-asdf)#.(asdf-test::frob-packages)#.(asdf-test::with-test()(load(string'|$i|))))" ; then
112
        echo "Using $command, $i passed" >&2
113 114
	test_pass=`expr "$test_pass" + 1`
      else
115
        echo "Using $command, $i failed" >&2
116 117
	test_fail=`expr "$test_fail" + 1`
	failed_list="$failed_list $i"
118 119 120
        echo "you can retry compilation with:" >&2
        echo ./test/run-tests.sh $lisp $i >&2
        echo "or more interactively (and maybe with rlwrap or in emacs), start with:" >&2
121
        echo "(cd test ; $icmd )" >&2
122
        echo "then copy/paste:" >&2
123
        echo "'(#.(load \"script-support.lisp\") #.(asdf-test::da) #.(load-asdf) #.(frob-packages) #.(load \"$i\"))" >&2
124
      fi
125 126
      echo >&2
      echo >&2
127 128
    done
    echo >&2
Gary King's avatar
Gary King committed
129
    echo "-#---------------------------------------" >&2
130
    echo "Using $command" >&2
131 132 133 134
    echo "Ran $test_count tests: " >&2
    echo "  $test_pass passing and $test_fail failing" >&2
    if [ $test_fail -eq 0 ] ; then
	echo "all tests apparently successful" >&2
135
        echo success > ../build/results/status
136 137 138
    else
	echo "failing test(s): $failed_list" >&2
    fi
Gary King's avatar
Gary King committed
139
    echo "-#---------------------------------------" >&2
140
    echo >&2
141
  fi
142 143
}

144 145 146 147 148
case $(uname) in
    CYGWIN*) os=windows ;;
    *) os=unix ;;
esac

149
# terminate on error
150 151
set -e

152
command= flags= nodebug= eval= bcmd= icmd=
153
case "$lisp" in
154 155
  abcl)
    command="${ABCL:-abcl}"
156
    flags="--noinit --nosystem --noinform"
157 158
    eval="--eval"
    ;;
159
  allegro)
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
160
    command="${ALLEGRO:-alisp}"
161
    flags="-q"
162
    nodebug="-batch"
163
    if [ "$os" = windows ] ; then bcmd="$command +c $flags" ; fi
164
    eval="-e" ;;
165
  allegromodern)
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
166
    command="${ALLEGROMODERN:-mlisp}"
167
    if [ "$os" = windows ] ; then bcmd="$command +c $flags" ; fi
168 169 170
    flags="-q"
    nodebug="-batch"
    eval="-e" ;;
171
  ccl)
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
172
    command="${CCL:-ccl}"
173 174 175
    flags="--no-init --quiet"
    nodebug="--batch"
    eval="--eval" ;;
176 177
  clisp)
    command="${CLISP:-clisp}"
178
    flags="-norc --silent -ansi -I "
179 180
    nodebug="-on-error exit"
    eval="-x" ;;
181
  cmucl)
182 183 184
    # cmucl likes to have its executable called lisp, but so does scl
    # Please use a symlink or an exec ... "$@" trampoline script.
    command="${CMUCL:-cmucl}"
185 186 187
    flags="-noinit"
    nodebug="-batch"
    eval="-eval" ;;
188
  ecl)
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
189
    command="${ECL:-ecl}"
190 191
    flags="-norc -load sys:cmp"
    eval="-eval" ;;
192
  ecl_bytecodes)
193 194
    command="${ECL:-ecl}"
    flags="-norc -eval (ext::install-bytecodes-compiler)"
195
    eval="-eval" ;;
196
  gcl)
197
    GCL_ANSI=t
198 199 200
    command="${GCL:-gcl}"
    flags="-batch"
    eval="-eval" ;;
201
  gclcvs)
202
    GCL_ANSI=t
203
    command="${GCLCVS:-gclcvs}"
204 205
    flags="-batch"
    eval="-eval" ;;
206
  lispworks)
Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
207
    command="${LISPWORKS:-lispworks}"
208 209 210 211
    # If you have a licensed copy of lispworks,
    # you can obtain the "lispworks" binary with, e.g.
    # echo '(hcl:save-image "/lispworks" :environment nil)' > /tmp/build.lisp ;
    # ./lispworks-6-0-0-x86-linux -siteinit - -init - -build /tmp/build.lisp
212 213
    flags="-siteinit - -init -"
    eval="-eval" ;;
214 215 216 217
  mkcl)
    command="${MKCL:-mkcl}"
    flags="-norc"
    eval="-eval" ;;
218 219
  sbcl)
    command="${SBCL:-sbcl}"
220
    flags="--noinform --userinit /dev/null --sysinit /dev/null" # --eval (require'asdf)
221
    nodebug="--disable-debugger"
222
    eval="--eval" ;;
223 224 225 226 227
  scl)
    command="${SCL:-scl}"
    flags="-noinit"
    nodebug="-batch"
    eval="-eval" ;;
228 229
  xcl)
    command="${XCL:-xcl}"
230
    flags="--no-userinit --no-siteinit --noinform"
231
    eval="--eval" ;;
232 233 234 235
  *)
    echo "Unsupported lisp: $1" >&2
    echo "Please add support to run-tests.sh" >&2
    exit 42 ;;
236
esac
237

238
if ! type "$command" > /dev/null ; then
239
    echo "lisp implementation not found: $command" >&2
240 241 242
    exit 43
fi

243
ASDFDIR="$(cd $(dirname $0)/.. ; /bin/pwd)"
244
: ${bcmd:=$command $flags} ${icmd:=$command $flags} # batch and interactive
245
if [ -z "${DEBUG_ASDF_TEST}" ] ; then
246
  bcmd="$bcmd $nodebug"
247 248
fi

Francois-Rene Rideau's avatar
1.647:  
Francois-Rene Rideau committed
249

250
create_config () {
251 252
    cd ${ASDFDIR}
    mkdir -p build/results/ build/test-source-registry-conf.d build/test-asdf-output-translations-conf.d
253
}
254
upgrade_tags () {
255 256
    if [ -n "$ASDF_UPGRADE_TEST_TAGS" ] ; then
        echo $ASDF_UPGRADE_TEST_TAGS ; return
257
    fi
258 259 260 261 262 263 264
    # REQUIRE is a magic tag meaning whatever your implementation provides, if anything
    #
    # 1.85 (2004-05-16) is the last release by Daniel Barlow (not 1.37, which is the README revision!)
    # 1.97 (2006-05-14) is the last release before Gary King takes over
    # 1.369 (2009-10-27) is the last release by Gary King
    #
    # 2.000 to 2.019 and 2.20 to 2.26 and beyond are Faré's "stable" ASDF 2 releases
265
    # 2.26.61 is the last single-file, single-package ASDF.
266 267 268 269 270 271 272 273 274 275 276 277
    # 2.27 and beyond are Faré's "stable" ASDF 3 pre-releases
    #
    # 2.000 (2010-05-31) was the first ASDF 2 release
    # 2.008 (2010-09-10) was a somewhat stable ASDF 2 release
    # 2.011 (2010-11-28) was used by CLISP 2.49, Debian squeeze, Ubuntu 10.04 LTS
    # 2.014.6 (2011-04-06) was used by Quicklisp in 2011
    # 2.019 (2011-11-27) was stable
    # 2.20 (2012-01-18) was in CCL 1.8, Ubuntu 12.04 LTS
    # 2.22 (2012-06-12) was used by debian wheezy
    # 2.26 (2012-10-30) was used by Quicklisp
    # 2.27 (2013-02-01) is the first ASDF 3 pre-release
    # 2.32 (2013-03-05) is the first really stable ASDF 3 pre-release
278
    # 3.0.1 (2013-05-16) is the first stable ASDF 3 release
279
    echo REQUIRE 1.85 1.97 1.369
280 281 282
    # git tag -l '2.0??'
    # git tag -l '2.??'
    echo 2.000 2.008 2.011 2.014.6 2.019 2.20 2.22 2.26
283 284
    echo 2.27 2.32
    git tag -l '3.0.[1-9]'
285
}
286
upgrade_methods () {
287 288
    if [ -n "$ASDF_UPGRADE_TEST_METHODS" ] ; then
        echo $ASDF_UPGRADE_TEST_METHODS ; return
289 290
    fi
    cat <<EOF
291
'load-asdf-lisp'load-asdf-lisp-clean
292 293 294 295
'load-asdf-lisp'load-asdf-system
'load-asdf-lisp'compile-load-asdf
'load-asdf-lisp'load-asdf-fasl
()'load-asdf-fasl
296
'load-asdf-lisp-and-test-uiop'load-asdf-fasl
297 298
EOF
}
299
extract_tagged_asdf () {
300 301
    cd ${ASDFDIR}
    mkdir -p build/
302 303
    tag=$1
    if [ REQUIRE = "$tag" ] ; then return 0 ; fi
304 305
    file=build/asdf-${tag}.lisp ;
    if [ ! -f $file ] ; then
306
        case $tag in
307
            1.*|2.0*|2.2[0-6]|2.26.61)
308
                git show ${tag}:asdf.lisp > $file ;;
309
            2.2[7-9]*|2.[3-9]*|3.*)
310
                mkdir -p build/old/build
311
                git archive ${tag} | (cd build/old/ ; tar xf -)
312
                make -C build/old
313
                mv build/old/build/asdf.lisp build/asdf-${tag}.lisp
314 315
                rm -rf build/old ;;
             *)
316 317 318 319 320 321
                echo "Don't know how to extract asdf.lisp for version $tag"
                exit 55
                ;;
        esac
    fi
}
322 323 324 325 326
extract_all_tagged_asdf () {
    for i in `upgrade_tags` ; do
      extract_tagged_asdf $i
    done
}
327 328
valid_upgrade_test_p () {
    case "${1}:${2}:${3}" in
329 330 331
        # It's damn slow. Also, for some reason, we punt on anything earlier than 2.25,
        # and only need to test it once, below for 2.24.
        abcl:1.*|abcl:2.00[0-9]:*|abcl:201[0-9]:*|abcl:2.2[0-3]:*) : ;;
332 333
        # Skip allegro modern on 1.x -- fails for rpgoldman on his mac (!)
        allegromodern:1.*) : ;;
334 335
        # ccl fasl numbering broke loading of old asdf 2.0
        ccl:2.0[01]*) : ;;
336 337
        # my old ubuntu clisp 2.44.1 is wired in
        # with an antique ASDF 1.374 from CLC that can't be downgraded.
338 339
        # 2.00[0-7] use UID, which fails on that CLISP and was removed afterwards.
        # Note that for the longest time, CLISP has included 2.011 in its distribution.
340 341
        # Since we punt on the upgrade, let's only do the test once, for 2.26.
        clisp:2.00[0-7]:*|clisp:1.*|clisp:2.0[01]*|clisp:2.2[0-5]:*) : ;;
342
        # Skip, CMUCL has problems before 2.014.7 due to source-registry upgrade.
343 344 345 346 347 348 349 350 351
        # Weird unidentified problems before 2.018, so we punt equally for everything before,
        # and only need to test it once: above, for 2.017.
        cmucl:1.*|cmucl:2.00*|cmucl:2.01[0-6]:*) : ;;
        # Skip many ECL tests, for various ASDF issues
        ecl*:1.*|ecl*:2.0[01]*|ecl*:2.20:*) : ;;
        # GCL 2.6 is only supported with ASDF 2.27, so skip earlier versions
        gcl:1.*|gcl:2.0*|gcl:2.2[0-6]*) : ;;
        # MKCL is only supported starting with 2.24, so skip earlier versions
        mkcl:1.*|mkcl:2.0[01]*|mkcl:2.2[0-3]:*) : ;;
352 353
        # XCL support starts with ASDF 2.014.2
        # — It also dies during upgrade trying to show the backtrace.
354
        xcl:1.*|xcl:2.00*|xcl:2.01[0-4]:*|xcl:*) : ;;
355 356 357
        *) return 0 ;;
   esac
   return 1
358
}
359
run_upgrade_tests () {
360
    cd ${ASDFDIR}
361
    mkdir -p build/results/
362
    rm -f build/*.*f* uiop/*.*f* test/*.*f* ## Remove stale FASLs from ASDF 1.x, especially when different implementations have same name
363
    ASDF_OUTPUT_TRANSLATIONS="(:output-translations (\"${ASDFDIR}\" (\"${ASDFDIR}/build/fasls/\" :implementation \"asdf/\")) (t (\"${ASDFDIR}/build/fasls/\" :implementation \"root/\")) :ignore-inherited-configuration)"
364 365
    su=test/script-support.lisp
    for tag in `upgrade_tags` ; do
366 367 368 369
        for method in `upgrade_methods` ; do
            if valid_upgrade_test_p $lisp $tag $method ; then
                echo "Testing ASDF upgrade from ${tag} using method $method"
                extract_tagged_asdf $tag
370
                $bcmd $eval \
371
                "'(#.(load(string'|$su|))#.#.\`(in-package,:asdf-test)#.(test-upgrade$method\`|$tag|))" ||
372 373
                { echo "upgrade FAILED for $lisp from $tag using method $method" ;
                  echo "you can retry just that test with:" ;
374
                  echo ASDF_UPGRADE_TEST_TAGS=\"$tag\" ASDF_UPGRADE_TEST_METHODS=\"$method\" ./test/run-tests.sh -u $lisp ;
375
                  echo "or more interactively (and maybe with rlwrap or in emacs), start with:"
376
                  echo "$icmd"
377
                  echo "then copy/paste:"
378
                  echo "(load \"$su\") (asdf-test::da) (test-upgrade $method \"$tag\")"
379
                  exit 1 ;}
380
    fi ; done ; done 2>&1 | tee build/results/${lisp}-upgrade.text
381 382 383
}
run_tests () {
  create_config
384
  cd ./test/
385 386
  echo failure > ../build/results/status
    thedate=`date "+%Y-%m-%d"`
387
    do_tests "$@" 2>&1 | \
388 389 390
	tee "../build/results/${lisp}.text" "../build/results/${lisp}-${thedate}.save"
    read a < ../build/results/status
  clean_up
391 392 393 394 395 396 397
  if [ success = "$a" ] ; then ## exit code
      return 0
  else
     echo "To view full results and failures, try the following command:" >&2
     echo "     less -p ABORTED build/results/${lisp}.text" >&2
     return 1
  fi
398
}
399
clean_up () {
400
    rm -rf ../build/test-source-registry-conf.d ../build/test-asdf-output-translations-conf.d
401
}
402
test_clean_load () {
403
    case $lisp in
404
        gcl|cmucl) return 0 ;; # These are hopeless
405
    esac
406 407
    cd ${ASDFDIR}
    mkdir -p build/results/
408 409
    nop=build/results/${lisp}-nop.text
    load=build/results/${lisp}-load.text
410
    $bcmd $eval \
411
      '(or`#.(load(string`|test/script-support.lisp|)`:verbose():print())#.(asdf-test::exit-lisp`0))' \
412
        > $nop 2>&1
413
    $bcmd $eval \
414
      '(or`#.(load(string`|test/script-support.lisp|)`:verbose`():print`())#.(asdf-test::verbose())#.(load(string`|build/asdf.lisp|):verbose())#.(asdf/image:quit`0))' \
415 416 417 418 419 420 421
        > $load 2>&1
    if diff $nop $load ; then
      echo "GOOD: Loading ASDF on $lisp produces no message" >&2 ; return 0
    else
      echo "BAD: Loading ASDF on $lisp produces messages" >&2 ; return 1
    fi
}
422 423 424 425
test_load_systems () {
    case $lisp in
        gcl) return 0 ;; # This one is hopeless
    esac
426 427
    cd ${ASDFDIR}
    mkdir -p build/results/
428
    echo "Loading all these systems: $*"
429
    $bcmd $eval \
430
      "(or #.(load(string'|test/script-support.lisp|))#.(asdf-test::with-test()(asdf-test::test-load-systems $*)))" \
431 432
        2>&1 | tee build/results/${lisp}-systems.text
}
433
test_interactively () {
434 435
    cd ${ASDFDIR}
    mkdir -p build/results/
436
    rlwrap $icmd $eval "(or'#.(load(string'|test/script-support.lisp|))#.(asdf-test::interactive-test'($*)))"
437
}
438

439
if [ -z "$command" ] ; then
Gary King's avatar
Gary King committed
440
    echo "Error: cannot find or do not know how to run Lisp named $lisp"
441 442
elif [ -n "$test_interactively" ] ; then
    test_interactively "$@"
443 444
elif [ -n "$clean_load" ] ; then
    test_clean_load
445
elif [ -n "$load_systems" ] ; then
446
    test_load_systems "$@"
447 448
elif [ -n "$upgrade" ] ; then
    run_upgrade_tests
449 450
elif [ -n "$extract_all" ] ; then
    extract_all_tagged_asdf
451
else
452
    run_tests "$@"
453
fi ; exit # NB: "; exit" makes it robust wrt the script being modified while running.