| #!/bin/sh |
| # //===--------------------------- testit ---------------------------------===// |
| # // |
| # // The LLVM Compiler Infrastructure |
| # // |
| # // This file is distributed under the University of Illinois Open Source |
| # // License. See LICENSE.TXT for details. |
| # // |
| # //===--------------------------------------------------------------------===// |
| |
| currentpath=`pwd` |
| origpath=$currentpath |
| currentdir=`basename $currentpath` |
| while [ $currentdir != "test" ]; do |
| if [ $currentdir = "/" ] |
| then |
| echo "current directory must be in or under \"test\"." |
| exit 1 |
| fi |
| cd .. |
| currentpath=`pwd` |
| currentdir=`basename $currentpath` |
| done |
| |
| cd .. |
| LIBCXX_ROOT=`pwd` |
| cd $origpath |
| |
| ANDROID_SUPPORT=$(cd "$LIBCXX_ROOT"/../../../android/support && pwd) |
| |
| VERBOSE=1 |
| |
| run () { |
| if [ "$VERBOSE" -gt 1 ]; then |
| echo "COMMAND: $@" |
| fi |
| case $VERBOSE in |
| 0|1) |
| # Hide command output and errors. |
| "$@" >/dev/null 2>&1 |
| ;; |
| 2) |
| # Only hide command output |
| "$@" >/dev/null |
| ;; |
| *) |
| # Show command output and errors. |
| "$@" |
| ;; |
| esac |
| } |
| |
| run2 () { |
| if [ "$VERBOSE" -gt 2 ]; then |
| echo "COMMAND: $@" |
| fi |
| case $VERBOSE in |
| 0|1) |
| # Hide command output and errors. |
| "$@" >/dev/null 2>&1 |
| ;; |
| 2) |
| # Only hide command output |
| "$@" >/dev/null |
| ;; |
| *) |
| # Show command output and errors. |
| "$@" |
| ;; |
| esac |
| } |
| |
| # The list of valid target abis supported by this script. |
| VALID_ABIS="armeabi armeabi-v7a x86 mips" |
| |
| DO_HELP= |
| DO_STATIC= |
| TARGET_ABI= |
| TARGET_ARCH= |
| CXX= |
| for OPT; do |
| case $OPT in |
| --help|-?) |
| DO_HELP=true |
| ;; |
| --abi=*) |
| TARGET_ABI=${OPT##--abi=} |
| ;; |
| --static) |
| DO_STATIC=true |
| ;; |
| --cxx=*) |
| CXX=${OPT##--cxx=} |
| ;; |
| --verbose) |
| VERBOSE=$(( $VERBOSE + 1 )) |
| ;; |
| -*) |
| echo "Unknown option: $OPT. See --help." |
| exit 1 |
| ;; |
| *) |
| echo "This script doesn't take parameters. See --help." |
| exit 1 |
| ;; |
| esac |
| done |
| |
| if [ "$DO_HELP" ]; then |
| echo \ |
| "Usage: $(basename $0) [options] |
| |
| This script is used to run the libc++ test suite for Android. |
| You will need the following things: |
| |
| - The prebuild libc++ libraries in your NDK install. |
| - A prebuilt Android toolchain in your path. |
| - The 'adb' tool in your path. |
| - An Android device connected to ADB. |
| |
| The toolchain and device must match your target ABI. For example, if |
| you use --abi=armeabi-v7a, your device must run ARMv7-A Android binaries, |
| and arm-linux-androideabi-g++ will be used to compile all tests, unless |
| you use --cxx=<command> to override it. |
| |
| Valid options: |
| --help|-? Display this message. |
| --abi=<name> Specify target ABI. Use --abi=list for list. |
| --static Link against static libc++ library. |
| --cxx=<program> Override C++ compiler/linker. |
| --verbose Increase verbosity. |
| " |
| exit 0 |
| fi |
| |
| # Check target ABI. |
| if [ "$TARGET_ABI" = "list" ]; then |
| echo "List of valid target ABIs:" |
| for ABI in $VALID_ABIS; do |
| printf " %s" $ABI |
| done |
| printf "\n" |
| exit 0 |
| fi |
| |
| if [ -z "$TARGET_ABI" ]; then |
| echo "ERROR: Please specify a target ABI (--abi=<name>)." |
| exit 1 |
| fi |
| |
| FOUND_ABI= |
| for ABI in $VALID_ABIS; do |
| if [ "$ABI" = "$TARGET_ABI" ]; then |
| FOUND_ABI=true |
| break |
| fi |
| done |
| |
| if [ -z "$FOUND_ABI" ]; then |
| echo "ERROR: Invalid abi '$TARGET_ABI'. Must be one of: $VALID_ABIS" |
| exit 1 |
| fi |
| |
| LIBCXX_LIBS=$(cd $LIBCXX_ROOT/.. && pwd)/libs/$TARGET_ABI |
| for LIB in libc++_static.a libc++_shared.so; do |
| if [ ! -f "$LIBCXX_LIBS/$LIB" ]; then |
| echo "ERROR: Missing prebuilt library: $LIBCXX_LIBS/$LIB" |
| echo "Please run: build/tools/build-cxx-stl.sh --stl=libc++" |
| exit 1 |
| fi |
| done |
| |
| # Check or detect C++ toolchain. |
| TOOLCHAIN_CFLAGS= |
| TOOLCHAIN_LDFLAGS= |
| if [ -z "$TOOLCHAIN_PREFIX" ]; then |
| # Compute |
| case $TARGET_ABI in |
| armeabi) |
| TOOLCHAIN_PREFIX=arm-linux-androideabi |
| ;; |
| armeabi-v7a) |
| TOOLCHAIN_PREFIX=arm-linux-androideabi |
| TOOLCHAIN_CFLAGS="-march=armv7-a -mfpu=vfpv3-d16" |
| TOOLCHAIN_LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8" |
| ;; |
| x86) |
| TOOLCHAIN_PREFIX=i686-linux-android |
| ;; |
| mips) |
| TOOLCHAIN_PREFIX=mipsel-linux-android |
| ;; |
| *) |
| echo "ERROR: Unknown ABI '$ABI'" |
| exit 1 |
| ;; |
| esac |
| CXX=$TOOLCHAIN_PREFIX-g++ |
| fi |
| |
| REAL_CXX=$(which "$CXX" 2>/dev/null) |
| if [ -z "$REAL_CXX" ]; then |
| echo "ERROR: Missing C++ compiler: $CXX" |
| exit 1 |
| fi |
| CC=$CXX |
| |
| if [ -z "$OPTIONS" ] |
| then |
| OPTIONS="-std=c++11" |
| fi |
| OPTIONS="$OPTIONS -I$LIBCXX_ROOT/test/support" |
| |
| if [ -z "$HEADER_INCLUDE" ] |
| then |
| HEADER_INCLUDE="-I$LIBCXX_ROOT/include -I$ANDROID_SUPPORT/include" |
| fi |
| |
| if [ -z "$SOURCE_LIB" ] |
| then |
| SOURCE_LIB="-L$LIBCXX_LIBS" |
| fi |
| if [ -z "$ADB" ] |
| then |
| ADB=adb |
| fi |
| |
| if [ "$DO_STATIC" ]; then |
| # Statically link to ensure the executable can be run easily through ADB |
| LIBS=-lc++_static |
| else |
| run2 $ADB push $LIBCXX_LIBS/libc++_shared.so /data/local/tmp 2>/dev/null |
| if [ $? != 0 ]; then |
| echo "ERROR: Can't push shared libc++ to target device!" |
| exit 1 |
| fi |
| LIBS=-lc++_shared |
| fi |
| |
| case $TRIPLE in |
| *-*-mingw* | *-*-cygwin* | *-*-win*) |
| TEST_EXE=test.exe |
| ;; |
| *) |
| TEST_EXE=a.out |
| ;; |
| esac |
| |
| TEST_EXE=/tmp/testit_android-$USER-$$-$TEST_EXE |
| |
| FAIL=0 |
| PASS=0 |
| UNIMPLEMENTED=0 |
| IMPLEMENTED_FAIL=0 |
| IMPLEMENTED_PASS=0 |
| |
| # Run a shell command through ADB, return its status. |
| adb_shell () { |
| # We need a temporary file to store the output of our command |
| local CMD_OUT RET OUTPUT |
| CMD_OUT=$(mktemp /tmp/testit_android-cmdout-XXXXXX) |
| # Run the command, while storing the standard output to CMD_OUT |
| # and appending the exit code as the last line. |
| if [ "$VERBOSE" -gt 2 ]; then |
| echo "COMMAND: $ADB shell $@" |
| fi |
| $ADB shell "$@ ; echo \$?" | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1 |
| # Get last line in log, which contains the exit code from the command |
| RET=$(sed -e '$!d' $CMD_OUT) |
| # Get output, which corresponds to everything except the last line |
| OUT=$(sed -e '$d' $CMD_OUT) |
| rm -f $CMD_OUT |
| if [ "$VERBOSE" -gt 2 ]; then |
| printf "%s" "$OUT" |
| fi |
| return $RET |
| } |
| |
| # Run a given executable through ADB. |
| # $1: Executable path |
| # $2+: arguments. |
| adb_run () { |
| local EXECUTABLE EXECUTABLE_BASENAME TARGET_PATH |
| EXECUTABLE=$1 |
| EXECUTABLE_BASENAME=$(basename "$EXECUTABLE") |
| shift |
| TARGET_PATH=/data/local/tmp |
| run2 $ADB push $EXECUTABLE $TARGET_PATH/$EXECUTABLE_BASENAME 2>/dev/null && |
| adb_shell "LD_LIBRARY_PATH=$TARGET_PATH; cd $TARGET_PATH; ./$EXECUTABLE_BASENAME" |
| } |
| |
| afunc() { |
| fail=0 |
| pass=0 |
| if (ls *.fail.cpp > /dev/null 2>&1) |
| then |
| for FILE in $(ls *.fail.cpp); do |
| if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE > /dev/null 2>&1 |
| then |
| rm $TEST_EXE |
| echo "$FILE should not compile" |
| fail=$(($fail+1)) |
| else |
| pass=$(($pass+1)) |
| fi |
| done |
| fi |
| |
| if (ls *.pass.cpp > /dev/null 2>&1) |
| then |
| for FILE in $(ls *.pass.cpp); do |
| if [ "$VERBOSE" -gt 1 ]; then |
| echo "Running test: " $FILE |
| fi |
| if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE |
| then |
| if adb_run $TEST_EXE |
| then |
| rm $TEST_EXE |
| pass=$(($pass+1)) |
| else |
| echo "`pwd`/$FILE failed at run time" |
| echo "Compile line was:" $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS |
| fail=$(($fail+1)) |
| rm $TEST_EXE |
| fi |
| else |
| echo "`pwd`/$FILE failed to compile" |
| echo "Compile line was:" $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS |
| fail=$(($fail+1)) |
| fi |
| done |
| fi |
| |
| if [ $fail -gt 0 ] |
| then |
| echo "failed $fail tests in `pwd`" |
| IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL+1)) |
| fi |
| if [ $pass -gt 0 ] |
| then |
| echo "passed $pass tests in `pwd`" |
| if [ $fail -eq 0 ] |
| then |
| IMPLEMENTED_PASS=$((IMPLEMENTED_PASS+1)) |
| fi |
| fi |
| if [ $fail -eq 0 -a $pass -eq 0 ] |
| then |
| echo "not implemented: `pwd`" |
| UNIMPLEMENTED=$(($UNIMPLEMENTED+1)) |
| fi |
| |
| FAIL=$(($FAIL+$fail)) |
| PASS=$(($PASS+$pass)) |
| |
| for FILE in * |
| do |
| if [ -d "$FILE" ]; |
| then |
| cd $FILE |
| afunc |
| cd .. |
| fi |
| done |
| } |
| |
| afunc |
| |
| echo "****************************************************" |
| echo "Results for `pwd`:" |
| echo "using `$CC --version`" |
| echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB" |
| echo "----------------------------------------------------" |
| echo "sections without tests : $UNIMPLEMENTED" |
| echo "sections with failures : $IMPLEMENTED_FAIL" |
| echo "sections without failures: $IMPLEMENTED_PASS" |
| echo " + ----" |
| echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))" |
| echo "----------------------------------------------------" |
| echo "number of tests failed : $FAIL" |
| echo "number of tests passed : $PASS" |
| echo " + ----" |
| echo "total number of tests : $(($FAIL+$PASS))" |
| echo "****************************************************" |
| |
| exit $FAIL |