#!/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