Home | History | Annotate | Download | only in test
      1 #!/bin/sh
      2 # //===--------------------------- testit ---------------------------------===//
      3 # //
      4 # //                     The LLVM Compiler Infrastructure
      5 # //
      6 # // This file is distributed under the University of Illinois Open Source
      7 # // License. See LICENSE.TXT for details.
      8 # //
      9 # //===--------------------------------------------------------------------===//
     10 
     11 currentpath=`pwd`
     12 origpath=$currentpath
     13 currentdir=`basename $currentpath`
     14 while [ $currentdir != "test" ]; do
     15 	if [ $currentdir = "/" ]
     16 	then
     17 		echo "current directory must be in or under \"test\"."
     18 		exit 1
     19 	fi
     20 	cd ..
     21 	currentpath=`pwd`
     22 	currentdir=`basename $currentpath`
     23 done
     24 
     25 cd ..
     26 LIBCXX_ROOT=`pwd`
     27 cd $origpath
     28 
     29 ANDROID_SUPPORT=$(cd "$LIBCXX_ROOT"/../../../android/support && pwd)
     30 
     31 VERBOSE=1
     32 
     33 run () {
     34   if [ "$VERBOSE" -gt 1 ]; then
     35     echo "COMMAND: $@"
     36   fi
     37   case $VERBOSE in
     38     0|1)
     39       # Hide command output and errors.
     40       "$@" >/dev/null 2>&1
     41       ;;
     42     2)
     43       # Only hide command output
     44       "$@" >/dev/null
     45       ;;
     46     *)
     47       # Show command output and errors.
     48       "$@"
     49       ;;
     50   esac
     51 }
     52 
     53 run2 () {
     54   if [ "$VERBOSE" -gt 2 ]; then
     55     echo "COMMAND: $@"
     56   fi
     57   case $VERBOSE in
     58     0|1)
     59       # Hide command output and errors.
     60       "$@" >/dev/null 2>&1
     61       ;;
     62     2)
     63       # Only hide command output
     64       "$@" >/dev/null
     65       ;;
     66     *)
     67       # Show command output and errors.
     68       "$@"
     69       ;;
     70   esac
     71 }
     72 
     73 # The list of valid target abis supported by this script.
     74 VALID_ABIS="armeabi armeabi-v7a x86 mips"
     75 
     76 DO_HELP=
     77 DO_STATIC=
     78 TARGET_ABI=
     79 TARGET_ARCH=
     80 CXX=
     81 for OPT; do
     82   case $OPT in
     83     --help|-?)
     84       DO_HELP=true
     85       ;;
     86     --abi=*)
     87       TARGET_ABI=${OPT##--abi=}
     88       ;;
     89     --static)
     90       DO_STATIC=true
     91       ;;
     92     --cxx=*)
     93       CXX=${OPT##--cxx=}
     94       ;;
     95     --verbose)
     96       VERBOSE=$(( $VERBOSE + 1 ))
     97       ;;
     98     -*)
     99       echo "Unknown option: $OPT. See --help."
    100       exit 1
    101       ;;
    102     *)
    103       echo "This script doesn't take parameters. See --help."
    104       exit 1
    105       ;;
    106   esac
    107 done
    108 
    109 if [ "$DO_HELP" ]; then
    110   echo \
    111 "Usage: $(basename $0) [options]
    112 
    113 This script is used to run the libc++ test suite for Android.
    114 You will need the following things:
    115 
    116   - The prebuild libc++ libraries in your NDK install.
    117   - A prebuilt Android toolchain in your path.
    118   - The 'adb' tool in your path.
    119   - An Android device connected to ADB.
    120 
    121 The toolchain and device must match your target ABI. For example, if
    122 you use --abi=armeabi-v7a, your device must run ARMv7-A Android binaries,
    123 and arm-linux-androideabi-g++ will be used to compile all tests, unless
    124 you use --cxx=<command> to override it.
    125 
    126 Valid options:
    127   --help|-?        Display this message.
    128   --abi=<name>     Specify target ABI. Use --abi=list for list.
    129   --static         Link against static libc++ library.
    130   --cxx=<program>  Override C++ compiler/linker.
    131   --verbose        Increase verbosity.
    132 "
    133   exit 0
    134 fi
    135 
    136 # Check target ABI.
    137 if [ "$TARGET_ABI" = "list" ]; then
    138   echo "List of valid target ABIs:"
    139   for ABI in $VALID_ABIS; do
    140     printf " %s" $ABI
    141   done
    142   printf "\n"
    143   exit 0
    144 fi
    145 
    146 if [ -z "$TARGET_ABI" ]; then
    147   echo "ERROR: Please specify a target ABI (--abi=<name>)."
    148   exit 1
    149 fi
    150 
    151 FOUND_ABI=
    152 for ABI in $VALID_ABIS; do
    153   if [ "$ABI" = "$TARGET_ABI" ]; then
    154     FOUND_ABI=true
    155     break
    156   fi
    157 done
    158 
    159 if [ -z "$FOUND_ABI" ]; then
    160   echo "ERROR: Invalid abi '$TARGET_ABI'. Must be one of: $VALID_ABIS"
    161   exit 1
    162 fi
    163 
    164 LIBCXX_LIBS=$(cd $LIBCXX_ROOT/.. && pwd)/libs/$TARGET_ABI
    165 for LIB in libc++_static.a libc++_shared.so; do
    166   if [ ! -f "$LIBCXX_LIBS/$LIB" ]; then
    167     echo "ERROR: Missing prebuilt library: $LIBCXX_LIBS/$LIB"
    168     echo "Please run: build/tools/build-cxx-stl.sh --stl=libc++"
    169     exit 1
    170   fi
    171 done
    172 
    173 # Check or detect C++ toolchain.
    174 TOOLCHAIN_CFLAGS=
    175 TOOLCHAIN_LDFLAGS=
    176 if [ -z "$TOOLCHAIN_PREFIX" ]; then
    177   # Compute 
    178   case $TARGET_ABI in
    179     armeabi)
    180       TOOLCHAIN_PREFIX=arm-linux-androideabi
    181       ;;
    182     armeabi-v7a)
    183       TOOLCHAIN_PREFIX=arm-linux-androideabi
    184       TOOLCHAIN_CFLAGS="-march=armv7-a -mfpu=vfpv3-d16"
    185       TOOLCHAIN_LDFLAGS="-march=armv7-a -Wl,--fix-cortex-a8"
    186       ;;
    187     x86)
    188       TOOLCHAIN_PREFIX=i686-linux-android
    189       ;;
    190     mips)
    191       TOOLCHAIN_PREFIX=mipsel-linux-android
    192       ;;
    193     *)
    194       echo "ERROR: Unknown ABI '$ABI'"
    195       exit 1
    196       ;;
    197   esac
    198   CXX=$TOOLCHAIN_PREFIX-g++
    199 fi
    200 
    201 REAL_CXX=$(which "$CXX" 2>/dev/null)
    202 if [ -z "$REAL_CXX" ]; then
    203   echo "ERROR: Missing C++ compiler: $CXX"
    204   exit 1
    205 fi
    206 CC=$CXX
    207 
    208 if [ -z "$OPTIONS" ]
    209 then
    210 	OPTIONS="-std=c++11"
    211 fi
    212 OPTIONS="$OPTIONS -I$LIBCXX_ROOT/test/support"
    213 
    214 if [ -z "$HEADER_INCLUDE" ]
    215 then
    216        HEADER_INCLUDE="-I$LIBCXX_ROOT/include -I$ANDROID_SUPPORT/include"
    217 fi
    218 
    219 if [ -z "$SOURCE_LIB" ]
    220 then
    221        SOURCE_LIB="-L$LIBCXX_LIBS"
    222 fi
    223 if [ -z "$ADB" ]
    224 then
    225        ADB=adb
    226 fi
    227 
    228 if [ "$DO_STATIC" ]; then
    229   # Statically link to ensure the executable can be run easily through ADB
    230   LIBS=-lc++_static
    231 else
    232   run2 $ADB push $LIBCXX_LIBS/libc++_shared.so /data/local/tmp 2>/dev/null
    233   if [ $? != 0 ]; then
    234     echo "ERROR: Can't push shared libc++ to target device!"
    235     exit 1
    236   fi
    237   LIBS=-lc++_shared
    238 fi
    239 
    240 case $TRIPLE in
    241   *-*-mingw* | *-*-cygwin* | *-*-win*)
    242     TEST_EXE=test.exe
    243     ;;
    244   *)
    245     TEST_EXE=a.out
    246     ;;
    247 esac
    248 
    249 TEST_EXE=/tmp/testit_android-$USER-$$-$TEST_EXE
    250 
    251 FAIL=0
    252 PASS=0
    253 UNIMPLEMENTED=0
    254 IMPLEMENTED_FAIL=0
    255 IMPLEMENTED_PASS=0
    256 
    257 # Run a shell command through ADB, return its status.
    258 adb_shell () {
    259   # We need a temporary file to store the output of our command
    260   local CMD_OUT RET OUTPUT
    261   CMD_OUT=$(mktemp /tmp/testit_android-cmdout-XXXXXX)
    262   # Run the command, while storing the standard output to CMD_OUT
    263   # and appending the exit code as the last line.
    264   if [ "$VERBOSE" -gt 2 ]; then
    265     echo "COMMAND: $ADB shell $@"
    266   fi
    267   $ADB shell "$@ ; echo \$?" | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1
    268   # Get last line in log, which contains the exit code from the command
    269   RET=$(sed -e '$!d' $CMD_OUT)
    270   # Get output, which corresponds to everything except the last line
    271   OUT=$(sed -e '$d' $CMD_OUT)
    272   rm -f $CMD_OUT
    273   if [ "$VERBOSE" -gt 2 ]; then
    274     printf "%s" "$OUT"
    275   fi
    276   return $RET
    277 }
    278 
    279 # Run a given executable through ADB.
    280 # $1: Executable path
    281 # $2+: arguments.
    282 adb_run () {
    283   local EXECUTABLE EXECUTABLE_BASENAME TARGET_PATH
    284   EXECUTABLE=$1
    285   EXECUTABLE_BASENAME=$(basename "$EXECUTABLE")
    286   shift
    287   TARGET_PATH=/data/local/tmp
    288   run2 $ADB push $EXECUTABLE $TARGET_PATH/$EXECUTABLE_BASENAME 2>/dev/null &&
    289   adb_shell "LD_LIBRARY_PATH=$TARGET_PATH; cd $TARGET_PATH; ./$EXECUTABLE_BASENAME"
    290 }
    291 
    292 afunc() {
    293 	fail=0
    294 	pass=0
    295 	if (ls *.fail.cpp > /dev/null 2>&1)
    296 	then
    297 		for FILE in $(ls *.fail.cpp); do
    298 			if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE > /dev/null 2>&1
    299 			then
    300 				rm $TEST_EXE
    301 				echo "$FILE should not compile"
    302 				fail=$(($fail+1))
    303 			else
    304 				pass=$(($pass+1))
    305 			fi
    306 		done
    307 	fi
    308 
    309 	if (ls *.pass.cpp > /dev/null 2>&1)
    310 	then
    311 		for FILE in $(ls *.pass.cpp); do
    312                       if [ "$VERBOSE" -gt 1 ]; then
    313                           echo "Running test: " $FILE
    314                       fi
    315 			if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE
    316 			then
    317 				if adb_run $TEST_EXE
    318 				then
    319 					rm $TEST_EXE
    320 					pass=$(($pass+1))
    321 				else
    322 					echo "`pwd`/$FILE failed at run time"
    323 					echo "Compile line was:" $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS
    324 					fail=$(($fail+1))
    325 					rm $TEST_EXE
    326 				fi
    327 			else
    328 				echo "`pwd`/$FILE failed to compile"
    329 				echo "Compile line was:" $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS
    330 				fail=$(($fail+1))
    331 			fi
    332 		done
    333 	fi
    334 
    335 	if [ $fail -gt 0 ]
    336 	then
    337 		echo "failed $fail tests in `pwd`"
    338 		IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL+1))
    339 	fi
    340 	if [ $pass -gt 0 ]
    341 	then
    342 		echo "passed $pass tests in `pwd`"
    343 		if [ $fail -eq 0 ]
    344 		then
    345 			IMPLEMENTED_PASS=$((IMPLEMENTED_PASS+1))
    346 		fi
    347 	fi
    348 	if [ $fail -eq 0 -a $pass -eq 0 ]
    349 	then
    350 		echo "not implemented:  `pwd`"
    351 		UNIMPLEMENTED=$(($UNIMPLEMENTED+1))
    352 	fi
    353 
    354 	FAIL=$(($FAIL+$fail))
    355 	PASS=$(($PASS+$pass))
    356 
    357 	for FILE in *
    358 	do
    359 		if [ -d "$FILE" ];
    360 		then
    361 			cd $FILE
    362 			afunc
    363 			cd ..
    364 		fi
    365 	done
    366 }
    367 
    368 afunc
    369 
    370 echo "****************************************************"
    371 echo "Results for `pwd`:"
    372 echo "using `$CC --version`"
    373 echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB"
    374 echo "----------------------------------------------------"
    375 echo "sections without tests   : $UNIMPLEMENTED"
    376 echo "sections with failures   : $IMPLEMENTED_FAIL"
    377 echo "sections without failures: $IMPLEMENTED_PASS"
    378 echo "                       +   ----"
    379 echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))"
    380 echo "----------------------------------------------------"
    381 echo "number of tests failed   : $FAIL"
    382 echo "number of tests passed   : $PASS"
    383 echo "                       +   ----"
    384 echo "total number of tests    : $(($FAIL+$PASS))"
    385 echo "****************************************************"
    386 
    387 exit $FAIL
    388