#!/bin/sh ############################################################################## # __ # # ________ ___ / / ___ Scala Tools Launch Script # # / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL # # __\ \/ /__/ __ |/ /__/ __ | # # /____/\___/_/ |_/____/_/ | | # # |/ # ############################################################################## # $Id$ ############################################################################## # Error functions # Prints a warning message on stderr. warning() { echo "$0: warning:" "$@" 1>&2; } # Prints an error message on stderr. error() { echo "$0:" "$@" 1>&2; } # Prints an error message on stderr and exits with a non-zero status. abort() { error "$@"; exit 1; } ############################################################################## # Printing functions # Initializes the printf functions printf_initialization() { case "$1" in many ) printf_font_outline="printf \\033[1;39m"; printf_font_success="printf \\033[1;32m"; printf_font_failure="printf \\033[1;31m"; printf_font_warning="printf \\033[1;33m"; printf_font_default="printf \\033[0;39m"; ;; some ) printf_font_outline="printf \\033[1m"; printf_font_success="printf \\033[0m"; printf_font_failure="printf \\033[1m"; printf_font_warning="printf \\033[1m"; printf_font_default="printf \\033[0m"; ;; none ) printf_font_outline=""; printf_font_success=""; printf_font_failure=""; printf_font_warning=""; printf_font_default=""; ;; * ) abort "unknown color mode \`$1'"; ;; esac; } # Prints formated text in outline font. printf_outline() { $printf_font_outline; printf "$@"; $printf_font_default; } # Prints formated text in success font. printf_success() { $printf_font_success; printf "$@"; $printf_font_default; } # Prints formated text in failure font. printf_failure() { $printf_font_failure; printf "$@"; $printf_font_default; } # Prints formated text in warning font. printf_warning() { $printf_font_warning; printf "$@"; $printf_font_default; } ############################################################################## # File name and path list conversion functions # Prints the OS-specific form of the specified Unix form file name. get_os_filename() { [ $# = 1 ] || abort "internal error"; case "$UNAME" in CYGWIN* ) cygpath --windows "$1";; * ) echo "$@";; esac; } # Prints the Unix form of the specified OS-specific form file name. get_unix_filename() { [ $# = 1 ] || abort "internal error"; case "$UNAME" in CYGWIN* ) cygpath --unix "$1";; * ) echo "$@";; esac; } # Prints the OS-specific form of the specified Unix form path list. get_os_pathlist() { [ $# = 1 ] || abort "internal error"; case "$UNAME" in CYGWIN* ) cygpath --window --path "$1";; * ) echo "$@";; esac; } # Prints the Unix form of the specified OS-specific form path list. get_unix_pathlist() { [ $# = 1 ] || abort "internal error"; case "$UNAME" in CYGWIN* ) cygpath --unix --path "$1";; * ) echo "$@";; esac; } # Collects all jar files in the given path get_ext_classpath() { [ $# = 1 ] || abort "internal error"; # Constructing the extension classpath cp="" for ext in `ls $1/*.jar` ; do if [ -z "$cp" ] ; then cp="$ext" else cp="$cp:$ext" fi done echo $cp } ############################################################################## # Implementation of scalatest # Prints the scalatest usage. test_print_usage() { [ $# = 0 ] || abort "internal error"; echo "Usage: $0 [OPTION]..." } # Prints the scalatest help. test_print_help() { [ $# = 0 ] || abort "internal error"; test_print_usage; echo ""; echo "--auto use filenames to select the test to run"; echo "--dis next files test the class file disassembler"; echo "--run next files test the interpreter and all backends"; echo "--jvm next files test the JVM backend"; echo "--pos next files test a compilation success"; echo "--neg next files test a compilation failure"; echo "--res next files test the resident compiler"; echo "--msil next files test the .NET backend"; echo "--script next files test Scala embedded in scripts"; echo "--ant next files test the Ant tasks"; echo "--quick use the 'quick' build instead of distribution"; echo '--installed use the installed programs on $PATH' echo "--no-run run no test, use results of last run"; echo "--show-log show output of failed tests"; echo "--show-diff show differences between actual and expected output"; echo "--use-fsc use the Fast Scala compiler"; echo "--failed test only files that failed last time"; echo "--errors= specify the number of expected errors"; echo "--flags= specify flags to pass on to the executable"; echo "--color=USAGE control the color usage (USAGE=none|some|many)"; echo "--objdir= specify where to place generated files"; echo "--help, -? display this help and exit"; echo "--version output version information and exit"; } # Prints the scalatest version. test_print_version() { [ $# = 0 ] || abort "internal error"; echo "$SCRIPT "'$Revision$'; } # Prints the name of the specified test file. test_print_testing() { [ $# = 1 ] || abort "internal error"; printf_outline "testing: "; case "$1" in "$TESTROOT"* ) printf "%-60s " "[...]`expr "$1" : "$TESTROOT\(.*\)"`"; return 0; ;; esac; printf "%-60s " "$1"; } # Prints a test success notification. test_print_success() { [ $# = 0 ] || abort "internal error"; printf "["; printf_success " OK "; printf "]\\n"; } # Prints a test failure notification. test_print_failure() { [ $# = 0 ] || abort "internal error"; printf "["; printf_failure "FAILED"; printf "]\\n"; } # Tests a compilation success. test_run_pos() { rm -rf "$dstbase".obj && mkdir -p "$dstbase".obj && $SCALAC -d "$os_dstbase".obj "$@" "$os_srcbase".scala && rm -rf "$dstbase".obj; } # Tests a compilation failure. test_run_neg() { rm -rf "$dstbase".obj && mkdir -p "$dstbase".obj && ( cd "$srcdir" && $SCALAC -d "$os_dstbase".obj "$@" "$testname".scala; ); if [ "$?" = 0 ]; then status=1; else status=0; fi; rm -rf "$dstbase".obj; return $status; } # Tests resident compiler. test_run_res() { rm -rf "$dstbase".obj && mkdir -p "$dstbase".obj && (cd "$srcdir" && cat "$testname".res | $SCALAC -d "$os_dstbase".obj -resident -sourcepath . "$@"; ); rm -rf "$dstbase".obj; } # Tests the JVM backend. test_run_jvm() { rm -rf "$dstbase".obj && mkdir -p "$dstbase".obj && $SCALAC -d "$os_dstbase".obj -cp "$JVM_EXT_CLASSPATH" "$@" "$os_srcbase".scala && scala_lib=`get_os_filename "$SCALA_LIB"` && classpath=`get_os_pathlist "$os_dstbase".obj:$CLASSPATH` && $SCALA -Dscalatest.output=$os_dstbase.obj -Dscalatest.lib=$scala_lib -classpath $classpath:$JVM_EXT_CLASSPATH Test "jvm" && rm -rf "$dstbase".obj; } # Test the disassemblers. test_run_dis() { argsfile="$srcbase".args; if [ ! -f "$argsfile" ]; then argsfile=/dev/null; fi; rm -rf "$dstbase".obj && mkdir -p "$dstbase".obj && $SCALAC -d "$os_dstbase".obj "$@" "$os_srcbase".scala && $SCALAP -classpath "$os_dstbase".obj `cat "$argsfile"` && rm -rf "$dstbase".obj; } # Tests the .NET backend. test_run_msil() { assemblies=`get_os_pathlist "/home/linuxsoft/apps/msil"`; rm -f "$dstbase".il && rm -f "$dstbase".EXE && $SCALAC -nowarn -target:msil -o "$os_dstbase" -r $assemblies "$@" \ "$os_srcbase".scala && case "$UNAME" in CYGWIN* ) ilasm /qui /nol /out="$os_dstbase".EXE "$os_dstbase".il \ > /dev/null && # peverify /il "$os_dstbase".EXE > /dev/null && "$dstbase".EXE "msil";; * ) ilasm /output:"$os_dstbase".EXE "$os_dstbase".il \ > /dev/null && mono "$dstbase".EXE "msil";; esac && rm -f "$dstbase".EXE && rm -f "$dstbase".il; } # Tests a script with Scala code embedded in it test_run_script() { argsfile="$srcbase.args" if [ ! -r "$argsfile" ] then argsfile=/dev/null fi chmod +x "$srcbase.scala" 2> /dev/null PATH="$BIN_DIR:$PATH" "$srcbase.scala" `cat $argsfile` } # Tests the Scala Ant task test_run_ant() { if [ "$BIN_DIR" = "" ]; then BINARY=installed elif [ "$BIN_DIR" = "$QUICK" ]; then BINARY=quick else BINARY=latest fi; testname=`basename "$srcbase"`; buildfile=`get_os_filename "$srcdir/$testname-build.xml"`; rm -rf "$dstbase".obj && $ANT -f "$buildfile" -Dbinary="$BINARY" -Dbuild.dir="$os_dstbase".obj && rm -rf "$dstbase".obj; } # Checks the specified test. test_check_test() { [ $# = 1 ] || abort "internal error"; testfile="$1"; shift 1; # compute test name testname=`basename "$testfile" ."$TEST_EXT"`; # compute source and destination directories (absolute paths) srcdir=`dirname "$testfile"`; srcdir=`cd "$srcdir"; pwd`; dstdir="$OBJDIR""$srcdir"; # compute source and destination base names srcbase="$srcdir"/"$testname"; dstbase="$dstdir"/"$testname"-$kind; os_srcbase=`get_os_filename "$srcbase"`; os_dstbase=`get_os_filename "$dstbase"`; # compute flags file flagsfile="$srcbase".flags; if [ ! -f "$flagsfile" ]; then flagsfile=/dev/null; fi; # compute check file checkfile="$srcbase"-$kind.check; if [ ! -f "$checkfile" ]; then checkfile="$srcbase".check; fi; if [ ! -f "$checkfile" ]; then checkfile=/dev/null; fi; # compute log file logfile="$dstbase".log; # if we are testing only failed tests, skip successful tests if [ "$FAILED" = "true" -a ! -f "$logfile" ]; then return 0; fi; # if that's the first file of the section print section header if [ -n "$header" ]; then printf_outline "$header\\n"; unset header; fi; # print tested file test_print_testing "$testfile"; # run test if [ "$NORUN" = "true" ]; then [ ! -f "$logfile" ]; else rm -f "$logfile"; { [ -d "$dstdir" ] || mkdir -p "$dstdir"; } && ( test_run_$kind `cat "$flagsfile"` $FLAGS 1> "$logfile" 2>&1; ) && $DIFF "$logfile" "$checkfile" 1> /dev/null 2>&1 && rm -f "$logfile"; fi; # print result if [ "$?" = 0 ]; then SUCCESS_COUNT=`echo "$SUCCESS_COUNT+1" | bc`; test_print_success; else FAILURE_COUNT=`echo "$FAILURE_COUNT+1" | bc`; test_print_failure; if [ ! -f "$logfile" ]; then logfile=/dev/null; fi; if [ "$SHOWLOG" = "true" ]; then cat "$logfile"; fi; if [ "$SHOWDIFF" = "true" ]; then $DIFF "$logfile" "$checkfile"; fi; fi; } # Checks the specified file test_check_file() { [ $# = 1 ] || abort "internal error"; file="$1"; shift 1; for testfile in "" `find "$file" -name "*.obj" -prune -o -name "*.$TEST_EXT" -a -type f -print`; do [ -z "$testfile" ] && continue; test_check_test "$testfile"; done; } # Checks all files of the specified kind. test_check_kind() { [ $# -ge 2 ] || abort "internal error"; header="$1"; shift 1; kind="$1"; shift 1; if [ "$kind" = "res" ]; then TEST_EXT="res"; else TEST_EXT="scala"; fi; for file in "" "$@"; do [ -z "$file" ] && continue; test_check_file "$file"; done if [ -z "$header" ]; then echo ""; fi; } # Checks everything. test_check_all() { [ $# = 0 ] || abort "internal error"; test_check_kind "Testing disassembler" \ "dis" $FILES_DIS; test_check_kind "Testing JVM backend" \ "jvm" $FILES_RUN $FILES_JVM; test_check_kind "Testing compiler (on files whose compilation should succeed)" \ "pos" $FILES_POS; test_check_kind "Testing compiler (on files whose compilation should fail)" \ "neg" $FILES_NEG; test_check_kind "Testing .NET backend" \ "msil" $FILES_MSIL; test_check_kind "Testing Scala embedded in script files" \ "script" $FILES_SCRIPT; test_check_kind "Testing Scala Ant tasks" \ "ant" $FILES_ANT; test_check_kind "Testing resident compiler" \ "res" $FILES_RES; } # Adds a new file to the appropriate file list(s). test_add_file() { [ $# = 1 ] || abort "internal error"; case "$1" in *.scala ) if [ ! \( -d "$1" -o -f "$1" \) ]; then abort "don't know what to do with '$1'"; fi;; * ) if [ ! -d "$1" ]; then abort "don't know what to do with '$1'"; fi;; esac; TEST_ALL="false"; case "$TEST_TYPE" in auto ) ;; dis ) FILES_DIS="$FILES_DIS $1"; return;; run ) FILES_RUN="$FILES_RUN $1"; return;; jvm ) FILES_JVM="$FILES_JVM $1"; return;; pos ) FILES_POS="$FILES_POS $1"; return;; neg ) FILES_NEG="$FILES_NEG $1"; return;; res ) FILES_RES="$FILES_RES $1"; return;; msil ) FILES_MSIL="$FILES_MSIL $1"; return;; script ) FILES_SCRIPT="$FILES_SCRIPT $1"; return;; ant ) FILES_ANT="$FILES_ANT $1"; return;; * ) abort "unknown test type \`$TEST_TYPE'";; esac; case "$1" in dis | */dis | */dis/* | dis/* ) FILES_DIS="$FILES_DIS $1";; run | */run | */run/* | run/* ) FILES_RUN="$FILES_RUN $1";; jvm5 | */jvm5 | */jvm5* | jvm5/* ) if [ "$JAVA5" = "true" ]; then FILES_JVM="$FILES_JVM $1" fi;; jvm | */jvm | */jvm/* | jvm/* ) FILES_JVM="$FILES_JVM $1";; pos | */pos | */pos/* | pos/* ) FILES_POS="$FILES_POS $1";; neg | */neg | */neg/* | neg/* ) FILES_NEG="$FILES_NEG $1";; res | */res | */res/* | res/* ) FILES_RES="$FILES_RES $1";; msil | */msil | */msil/* | msil/* ) FILES_MSIL="$FILES_MSIL $1";; script | */script | */script/* | script/* ) FILES_SCRIPT="$FILES_SCRIPT $1";; * ) abort "don't known what to do with \`$1'";; esac; } test_get_location() { [ $# = 1 ] || abort "internal error"; source="$1"; shift 1; script=`basename "$source"`; while [ -h "$source" ]; do script=`basename "$source"`; lookup=`ls -ld "$source"`; target=`expr "$lookup" : '.*-> \(.*\)$'`; if expr "${target:-.}/" : '/.*/$' > /dev/null; then source=${target:-.}; else source=`dirname "$source"`/${target:-.}; fi; done; location=`dirname "$source"`; location=`cd "$location"; pwd`; echo $location; } ############################################################################## # Definition of UNAME, SOURCE, SCRIPT and PREFIX unset SCRIPT; UNAME=`uname`; SOURCE=$0; SCRIPT=`basename "$SOURCE"`; while [ -h "$SOURCE" ]; do SCRIPT=`basename "$SOURCE"`; LOOKUP=`ls -ld "$SOURCE"`; TARGET=`expr "$LOOKUP" : '.*-> \(.*\)$'`; if expr "${TARGET:-.}/" : '/.*/$' > /dev/null; then SOURCE=${TARGET:-.}; else SOURCE=`dirname "$SOURCE"`/${TARGET:-.}; fi; done; PREFIX=`dirname "$SOURCE"`/..; PREFIX=`cd "$PREFIX"; pwd`; ############################################################################## # Invocation of $SCRIPT NORUN="false"; SHOWLOG="false"; SHOWDIFF="false"; USEFSC="false"; FAILED="false"; ERRORS=0; SUCCESS_COUNT=0; FAILURE_COUNT=0; if [ -d "$PREFIX/test" ]; then TESTROOT="$PREFIX/test"; elif [ -d "$PREFIX/misc/scala-test" ]; then TESTROOT="$PREFIX/misc/scala-test"; else abort "Test directory not found"; fi; SRCDIR="$TESTROOT/files"; OBJDIR=""""; TEST_ALL="true"; TEST_TYPE="auto"; FILES_RUN=""; FILES_JVM=""; FILES_POS=""; FILES_RES=""; FILES_NEG=""; FILES_MSIL=""; FILES_SCRIPT=""; FILES_DIS=""; FILES_ANT=""; QUICK="$PREFIX/build/quick/bin" QUICK_LIB="$PREFIX/build/quick/lib/library" JVM_EXT_CLASSPATH=`get_ext_classpath $TESTROOT/files/jvm/lib` if [ -d "$PREFIX/dists" ]; then LATEST="$PREFIX/dists/latest/bin"; LATEST_LIB="$PREFIX/dists/latest/lib/scala-library.jar"; elif [ -d "$PREFIX/build" ]; then LATEST="$QUICK"; LATEST_LIB=$QUICK_LIB elif [ -d "$PREFIX/bin" ]; then LATEST="$PREFIX/bin"; LATEST_LIB="$PREFIX/lib/scala-library.jar" else abort "Scala binaries could not be found"; fi; BIN_DIR="$LATEST/" # BIN_DIR should have a trailing / when needed, so that # it can also be set to the empty string SCALA_LIB="$LATEST_LIB" case `${JAVACMD:=java} \-version 2>&1 | head -1` in *1.5*) JAVA5="true";; *) JAVA5="false";; esac; DIFF="diff"; case `uname` in CYGWIN* ) DIFF="diff --text --strip-trailing-cr"; ;; esac; while [ $# -gt 0 ]; do case "$1" in --auto ) TEST_TYPE="auto"; shift 1;; --dis ) TEST_TYPE="dis"; shift 1;; --run ) TEST_TYPE="run"; shift 1;; --jvm ) TEST_TYPE="jvm"; shift 1;; --pos ) TEST_TYPE="pos"; shift 1;; --neg ) TEST_TYPE="neg"; shift 1;; --res ) TEST_TYPE="res"; shift 1;; --msil ) TEST_TYPE="msil"; shift 1;; --script ) TEST_TYPE="script"; shift 1;; --ant ) TEST_TYPE="ant"; shift 1;; --quick ) BIN_DIR="$QUICK/"; SCALA_LIB=$QUICK_LIB; shift 1;; --installed ) BIN_DIR=""; shift 1;; --no-run ) NORUN="true"; shift 1;; --show-log ) SHOWLOG="true"; shift 1;; --show-diff ) SHOWDIFF="true"; shift 1;; --use-fsc ) USEFSC="true"; shift 1;; --failed ) FAILED="true"; shift 1;; --pending ) SRCDIR="$TESTROOT/pending"; shift 1;; --errors= ) abort "illegal empty argument for option --errors";; --errors=* ) ERRORS=`expr "$1" : "--errors=\([0-9]*\)$"`;shift 1;; --flags= ) abort "illegal empty argument for option --flags";; --flags=* ) FLAGS=`expr "$1" : "--flags=\(.*\)"`; shift 1;; --color= ) abort "illegal empty argument for option --color";; --color=* ) COLOR=`expr "$1" : "--color=\(.*\)"`; shift 1;; --objdir=* ) OBJDIR=`expr "$1" : "--objdir=\(.*\)"`; shift 1;; --help| -? ) test_print_help; exit 0;; --version ) test_print_version; exit 0;; -* ) abort "unknown option $1";; * ) test_add_file "$1"; shift 1;; esac; done; if [ "$JAVA5" = "true" ]; then FLAGS="$FLAGS -target:jvm-1.5" fi; if [ -z "$ERRORS" ]; then abort "illegal non-numerical argument for option --errors"; fi; if [ -z "$COLOR" -a -n "$EMACS" ]; then COLOR="none"; fi; printf_initialization "${COLOR:-many}"; if [ "$TEST_ALL" = "true" ]; then case "$TEST_TYPE" in dis ) FILES_DIS="$FILES_DIS $SRCDIR/dis";; esac; case "$TEST_TYPE" in run ) FILES_RUN="$FILES_RUN $SRCDIR/run";; esac; case "$TEST_TYPE" in auto | jvm ) FILES_JVM="$FILES_JVM $SRCDIR/run $SRCDIR/jvm" if [ "$JAVA5" = "true" ]; then FILES_JVM="$FILES_JVM $SRCDIR/jvm5"; fi;; esac; case "$TEST_TYPE" in auto | pos ) FILES_POS="$FILES_POS $SRCDIR/pos";; esac; case "$TEST_TYPE" in auto | neg ) FILES_NEG="$FILES_NEG $SRCDIR/neg";; esac; case "$TEST_TYPE" in auto | res ) FILES_RES="$FILES_RES $SRCDIR/res";; esac; case "$TEST_TYPE" in msil ) FILES_MSIL="$FILES_MSIL $SRCDIR/run";; esac; case "$TEST_TYPE" in auto | script ) FILES_SCRIPT="$FILES_SCRIPT $SRCDIR/script";; esac; case "$TEST_TYPE" in ant ) FILES_ANT="$FILES_ANT $SRCDIR/ant";; esac; fi; SCALA="${BIN_DIR}scala"; if [ "$USEFSC" = "true" ]; then SCALAC="${BIN_DIR}fsc -deprecation -encoding iso-8859-1"; else SCALAC="${BIN_DIR}scalac -deprecation -encoding iso-8859-1"; fi; SCALAP="scalap"; ANT="ant"; if [ -n "$OBJDIR" ]; then if [ -d "$OBJDIR" ] || mkdir -p "$OBJDIR"; then OBJDIR=`cd "$OBJDIR"; pwd`; else abort "could not create directory '$OBJDIR'"; fi fi printf_outline "Source directory is : $SRCDIR\\n"; bin_dir=$BIN_DIR if [ -z "$bin_dir" ]; then scalac=`which $SCALAC`; bin_dir=`test_get_location $scalac`; fi; printf_outline "Scala binaries in : $bin_dir\\n"; scala_version=`${SCALAC} -version 2>&1` printf_outline "Scala version is : $scala_version\\n"; jvm_version=`${JAVACMD:=java} -version 2>&1 | head -3 | tail -1` printf_outline "Java runtime is : $jvm_version\\n\\n"; test_check_all; TOTAL_COUNT=`echo "$FAILURE_COUNT+$SUCCESS_COUNT" | bc`; if [ $FAILURE_COUNT -eq 0 ]; then printf_success "All of $TOTAL_COUNT tests were successful\\n"; else printf_failure "$FAILURE_COUNT of $TOTAL_COUNT tests failed\\n"; fi; if [ $FAILURE_COUNT -eq "$ERRORS" ]; then exit 0; else exit 1; fi; ##############################################################################