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 11currentpath=`pwd` 12origpath=$currentpath 13currentdir=`basename $currentpath` 14while [ $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` 23done 24 25cd .. 26LIBCXX_ROOT=`pwd` 27cd $origpath 28 29VERBOSE=1 30 31run () { 32 if [ "$VERBOSE" -gt 1 ]; then 33 echo "COMMAND: $@" 34 fi 35 case $VERBOSE in 36 0|1) 37 # Hide command output and errors. 38 "$@" >/dev/null 2>&1 39 ;; 40 2) 41 # Only hide command output 42 "$@" >/dev/null 43 ;; 44 *) 45 # Show command output and errors. 46 "$@" 47 ;; 48 esac 49} 50 51run2 () { 52 if [ "$VERBOSE" -gt 2 ]; then 53 echo "COMMAND: $@" 54 fi 55 case $VERBOSE in 56 0|1) 57 # Hide command output and errors. 58 "$@" >/dev/null 2>&1 59 ;; 60 2) 61 # Only hide command output 62 "$@" >/dev/null 63 ;; 64 *) 65 # Show command output and errors. 66 "$@" 67 ;; 68 esac 69} 70 71# The list of valid target abis supported by this script. 72VALID_ABIS="armeabi armeabi-v7a x86 mips" 73 74HOST_OS=`uname -s` 75if [ "$HOST_OS" = "Darwin" ]; then 76 # darwin doesn't have readelf. hard-code a known one 77 READELF=../../../../../toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86/bin/arm-linux-androideabi-readelf 78else 79 READELF=readelf 80fi 81 82DO_HELP= 83DO_STATIC= 84TARGET_ABI= 85TARGET_ARCH= 86if [ -z "$TARGET_TEST_SUBDIR" ]; then 87 TARGET_TEST_SUBDIR="libcxx" 88fi 89TARGET_PATH=/data/local/tmp/$TARGET_TEST_SUBDIR 90CXX= 91WITH_COMPILER_RT= 92LIBCXX_NEEDS_COMPILER_RT= 93for OPT; do 94 case $OPT in 95 --help|-?) 96 DO_HELP=true 97 ;; 98 --abi=*) 99 TARGET_ABI=${OPT##--abi=} 100 ;; 101 --static) 102 DO_STATIC=true 103 ;; 104 --shared) 105 DO_STATIC= 106 ;; 107 --cxx=*) 108 CXX=${OPT##--cxx=} 109 ;; 110 --verbose) 111 VERBOSE=$(( $VERBOSE + 1 )) 112 ;; 113 --with-compiler-rt) 114 WITH_COMPILER_RT=yes 115 ;; 116 -*) 117 echo "Unknown option: $OPT. See --help." 118 exit 1 119 ;; 120 *) 121 echo "This script doesn't take parameters. See --help." 122 exit 1 123 ;; 124 esac 125done 126 127if [ "$DO_HELP" ]; then 128 echo \ 129"Usage: $(basename $0) [options] 130 131This script is used to run the libc++ test suite for Android. 132You will need the following things: 133 134 - The prebuild libc++ libraries in your NDK install. 135 - A prebuilt Android toolchain in your path. 136 - The 'adb' tool in your path. 137 - An Android device connected to ADB. 138 139The toolchain and device must match your target ABI. For example, if 140you use --abi=armeabi-v7a, your device must run ARMv7-A Android binaries, 141and arm-linux-androideabi-g++ will be used to compile all tests, unless 142you use --cxx=<command> to override it. 143 144Valid options: 145 --help|-? Display this message. 146 --abi=<name> Specify target ABI. Use --abi=list for list. 147 --static Link against static libc++ library. 148 --cxx=<program> Override C++ compiler/linker. 149 --verbose Increase verbosity. 150" 151 exit 0 152fi 153 154# Check target ABI. 155if [ "$TARGET_ABI" = "list" ]; then 156 echo "List of valid target ABIs:" 157 for ABI in $VALID_ABIS; do 158 printf " %s" $ABI 159 done 160 printf "\n" 161 exit 0 162fi 163 164if [ -z "$TARGET_ABI" ]; then 165 echo "ERROR: Please specify a target ABI (--abi=<name>)." 166 exit 1 167fi 168 169FOUND_ABI= 170for ABI in $VALID_ABIS; do 171 if [ "$ABI" = "$TARGET_ABI" ]; then 172 FOUND_ABI=true 173 break 174 fi 175done 176 177if [ -z "$FOUND_ABI" ]; then 178 echo "ERROR: Invalid abi '$TARGET_ABI'. Must be one of: $VALID_ABIS" 179 exit 1 180fi 181 182LIBCXX_LIBS=$(cd $LIBCXX_ROOT/.. && pwd)/libs/$TARGET_ABI 183for LIB in libc++_static.a libc++_shared.so; do 184 if [ ! -f "$LIBCXX_LIBS/$LIB" ]; then 185 echo "ERROR: Missing prebuilt library: $LIBCXX_LIBS/$LIB" 186 echo "Please run: build/tools/build-cxx-stl.sh --stl=libc++" 187 exit 1 188 fi 189done 190 191LIBCOMPILER_RT_LIBS=$(cd "$LIBCXX_ROOT"/../../../android/compiler-rt && pwd)/libs/$TARGET_ABI 192$READELF -d "$LIBCXX_LIBS/libc++_shared.so" | grep NEEDED | grep -q compiler_rt 193if [ $? = 0 ]; then 194 LIBCXX_NEEDS_COMPILER_RT=yes 195fi 196 197if [ "$WITH_COMPILER_RT" = "yes" -o "$LIBCXX_NEEDS_COMPILER_RT" = "yes" ]; then 198 for LIB in libcompiler_rt_static.a libcompiler_rt_shared.so; do 199 if [ ! -f "$LIBCOMPILER_RT_LIBS/$LIB" ]; then 200 echo "ERROR: Missing prebuilt library: $LIBCOMPILER_RT_LIBS/$LIB" 201 echo "Please run: build/tools/build-compiler-rt.sh --ndk-dir=$NDK \ 202--src-dir=/tmp/ndk-$USER/src/llvm-3.3/compiler-rt --llvm-version=3.3" 203 exit 1 204 fi 205 done 206fi 207 208# Check or detect C++ toolchain. 209TOOLCHAIN_CFLAGS= 210TOOLCHAIN_LDFLAGS= 211if [ -z "$TOOLCHAIN_PREFIX" ]; then 212 # Compute 213 case $TARGET_ABI in 214 armeabi) 215 TOOLCHAIN_PREFIX=arm-linux-androideabi 216 TOOLCHAIN_CFLAGS="-mthumb" 217 TOOLCHAIN_LDFLAGS="-mthumb" 218 ;; 219 armeabi-v7a) 220 TOOLCHAIN_PREFIX=arm-linux-androideabi 221 TOOLCHAIN_CFLAGS="-march=armv7-a -mthumb -mfpu=vfpv3-d16" 222 TOOLCHAIN_LDFLAGS="-march=armv7-a -mthumb -Wl,--fix-cortex-a8" 223 ;; 224 armeabi-v7a-hard) 225 TOOLCHAIN_PREFIX=arm-linux-androideabi 226 TOOLCHAIN_CFLAGS="-march=armv7-a -mthumb -mfpu=vfpv3-d16 -mhard-float -D_NDK_MATH_NO_SOFTFP=1" 227 TOOLCHAIN_LDFLAGS="-march=armv7-a -mthumb -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard" 228 ;; 229 x86) 230 TOOLCHAIN_PREFIX=i686-linux-android 231 ;; 232 mips) 233 TOOLCHAIN_PREFIX=mipsel-linux-android 234 ;; 235 *) 236 echo "ERROR: Unknown ABI '$ABI'" 237 exit 1 238 ;; 239 esac 240 if [ -z "$CXX" ]; then 241 CXX=$TOOLCHAIN_PREFIX-g++ 242 fi 243fi 244 245REAL_CXX=$(which "$CXX" 2>/dev/null) 246if [ -z "$REAL_CXX" ]; then 247 echo "ERROR: Missing C++ compiler: $CXX" 248 exit 1 249fi 250CC=$CXX 251 252if [ -z "$OPTIONS" ] 253then 254 # Note that some tests use assert() to check condition but -O2 defines assert() to nothing, 255 # unless we specify -UNDEBUG to bring assert() back. 256 OPTIONS="--std=c++11 -O2 -g -funwind-tables -UNDEBUG" 257 if [ "$CXX" != "${CXX%clang++*}" ] ; then 258 OPTIONS="$OPTIONS" # clang3.5 doesn't accept the following: -mllvm -arm-enable-ehabi-descriptors -mllvm -arm-enable-ehabi" 259 else 260 # Some libc++ implementation (eg. list) break TBAA! 261 OPTIONS="$OPTIONS -fno-strict-aliasing" 262 fi 263fi 264 265OPTIONS="$OPTIONS $TOOLCHAIN_CFLAGS $TOOLCHAIN_LDFLAGS" 266OPTIONS="$OPTIONS -I$LIBCXX_ROOT/test/support" 267# llvm-libc++/libcxx/test/lit.cfg line #278 defineds the following for testing only on Linux 268OPTIONS="$OPTIONS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS" 269 270if [ -z "$ADB" ] 271then 272 ADB=adb 273fi 274 275# Run a shell command through ADB, return its status. 276# Variable ERR contains output if $RET is non-zero 277adb_shell () { 278 # We need a temporary file to store the output of our command 279 local CMD_OUT RET 280 ERR= 281 CMD_OUT=$(mktemp /tmp/testit_android-cmdout-XXXXXX) 282 # Run the command, while storing the standard output to CMD_OUT 283 # and appending the exit code as the last line. 284 if [ "$VERBOSE" -gt 2 ]; then 285 echo "COMMAND: $ADB shell $@" 286 fi 287 $ADB shell "$@ ; echo \$?" | sed -e 's![[:cntrl:]]!!g' > $CMD_OUT 2>&1 288 # Get last line in log, which contains the exit code from the command 289 RET=$(sed -e '$!d' $CMD_OUT) 290 # Get output, which corresponds to everything except the last line 291 OUT=$(sed -e '$d' $CMD_OUT) 292 if [ "$RET" != "0" ]; then 293 ERR=$OUT 294 fi 295 if [ "$VERBOSE" -gt 2 ]; then 296 printf "%s" "$OUT" 297 fi 298 rm -f $CMD_OUT 299 return $RET 300} 301 302# Push a given file through ADB. 303# $1: File path 304adb_push () { 305 local FILE=$1 306 local FILE_BASENAME=$(basename "$FILE") 307 run2 $ADB push $FILE $TARGET_PATH/$FILE_BASENAME 2>/dev/null 308} 309 310# Run a given executable through ADB. 311# $1: Executable path 312adb_run () { 313 local EXECUTABLE=$1 314 local EXECUTABLE_BASENAME=$(basename "$EXECUTABLE") 315 run2 $ADB push $EXECUTABLE $TARGET_PATH/$EXECUTABLE_BASENAME 2>/dev/null 316 if [ "$?" != 0 ]; then 317 return 1; 318 fi 319 # Retry up to 10 times if fail is due to "Text file busy" 320 for i in 1 2 3 4 5 6 7 8 9 10; do 321 adb_shell "LD_LIBRARY_PATH=$TARGET_PATH; cd $TARGET_PATH; ./$EXECUTABLE_BASENAME" 322 if [ "$?" = "0" ]; then 323 return 0 324 fi 325 if ! $(echo $ERR | grep -iq "Text file busy"); then 326 if [ "$i" != "1" ]; then 327 # Dump error message to help diagnostics 328 echo "ERR=$ERR" 329 fi 330 break; 331 fi 332 echo "Text file busy. Re-try $i" 333 sleep 1 334 run2 $ADB push $EXECUTABLE $TARGET_PATH/$EXECUTABLE_BASENAME 2>/dev/null 335 sleep 2 # try again 336 done 337 return 1 338} 339 340adb_shell "rm -rf $TARGET_PATH" 341adb_shell "mkdir -p $TARGET_PATH" 342 343if [ "$DO_STATIC" ]; then 344 # Statically link to ensure the executable can be run easily through ADB 345 # Note that in standalone toolchain libc++_static is renamed to libstdc++, and 346 # compiler adds -lstdc++ implicitly 347 if [ "$WITH_COMPILER_RT" = "yes" ]; then 348 LIBS="-nodefaultlibs -lstdc++ -latomic -ldl -lm -lc -lcompiler_rt_static" 349 else 350 LIBS="-latomic" 351 fi 352else 353 run2 $ADB push $LIBCXX_LIBS/libc++_shared.so $TARGET_PATH 2>/dev/null 354 if [ $? != 0 ]; then 355 echo "ERROR: Can't push shared libc++ to target device!" 356 exit 1 357 fi 358 359 if [ "$WITH_COMPILER_RT" = "yes" -o "$LIBCXX_NEEDS_COMPILER_RT" = "yes" ]; then 360 run2 $ADB push $LIBCOMPILER_RT_LIBS/libcompiler_rt_shared.so $TARGET_PATH 2>/dev/null 361 if [ $? != 0 ]; then 362 echo "ERROR: Can't push shared libcompiler_rt to target device!" 363 exit 1 364 fi 365 fi 366 367 if [ "$WITH_COMPILER_RT" = "yes" ]; then 368 LIBS="-nodefaultlibs -lc++_shared -latomic -ldl -lm -lc -lcompiler_rt_shared" 369 else 370 LIBS="-lc++_shared -latomic" 371 fi 372fi 373 374case $TRIPLE in 375 *-*-mingw* | *-*-cygwin* | *-*-win*) 376 TEST_EXE=test.exe 377 ;; 378 *) 379 TEST_EXE=a.out 380 ;; 381esac 382 383TEST_EXE=/tmp/testit_android-$USER-$$-$TEST_EXE 384 385FAIL=0 386PASS=0 387UNIMPLEMENTED=0 388IMPLEMENTED_FAIL=0 389IMPLEMENTED_PASS=0 390 391# Run tests in current directory, recursively 392# 393# Note that file path containing EQ are symlink to the existing tests whose path contain '=', 394# to workaround an issue in ndk-build which doesn't handle LOCAL_SRC_FILES with '='. 395# See tests/device/test-libc++-static-full/jni/Android.mk We need to filter out path containing 396# EQ such that we don't run same tests twice 397# 398# An alternative is to do "find . -type f", but this doesn't work in NDK windows package 399# where zip turns symlink into physical file it points to. 400# 401# We also sort the test to make the test report comparable to previous test 402# 403 404afunc() { 405 fail=0 406 pass=0 407 if (ls *.fail.cpp > /dev/null 2>&1) 408 then 409 for FILE in $(ls *.fail.cpp | tr ' ' '\n' | grep -v EQ | sort); do 410 if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE > /dev/null 2>&1 411 then 412 rm $TEST_EXE 413 echo "$FILE should not compile" 414 fail=$(($fail+1)) 415 else 416 pass=$(($pass+1)) 417 fi 418 done 419 fi 420 421 if (ls *.pass.cpp > /dev/null 2>&1) 422 then 423 if (ls *.dat > /dev/null 2>&1) 424 then 425 adb_shell "rm -f $TARGET_PATH/*.dat" 426 for FILE in $(ls *.dat | tr ' ' '\n' | grep -v EQ | sort); do 427 if [ "$VERBOSE" -gt 1 ]; then 428 echo "Pushing data: " $FILE 429 fi 430 adb_push $FILE 431 if [ $? != 0 ]; then 432 echo "Failed to push file $FILE" 433 fi 434 done 435 fi 436 for FILE in $(ls *.pass.cpp | tr ' ' '\n' | grep -v EQ | sort); do 437 if [ "$VERBOSE" -gt 1 ]; then 438 echo "Running test: " $FILE 439 fi 440 COMMAND="( cd $(pwd) && $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS )" 441 if run $CC $OPTIONS $HEADER_INCLUDE $SOURCE_LIB $FILE $LIBS -o $TEST_EXE 442 then 443 if adb_run $TEST_EXE 444 then 445 rm $TEST_EXE 446 pass=$(($pass+1)) 447 else 448 echo "`pwd`/$FILE failed at run time" 449 echo "Compile line was: $COMMAND # run-time" 450 fail=$(($fail+1)) 451 rm $TEST_EXE 452 fi 453 else 454 echo "`pwd`/$FILE failed to compile" 455 echo "Compile line was: $COMMAND # compile-time" 456 fail=$(($fail+1)) 457 fi 458 done 459 fi 460 461 if [ $fail -gt 0 ] 462 then 463 echo "failed $fail tests in `pwd`" 464 IMPLEMENTED_FAIL=$(($IMPLEMENTED_FAIL+1)) 465 fi 466 if [ $pass -gt 0 ] 467 then 468 echo "passed $pass tests in `pwd`" 469 if [ $fail -eq 0 ] 470 then 471 IMPLEMENTED_PASS=$((IMPLEMENTED_PASS+1)) 472 fi 473 fi 474 if [ $fail -eq 0 -a $pass -eq 0 ] 475 then 476 echo "not implemented: `pwd`" 477 UNIMPLEMENTED=$(($UNIMPLEMENTED+1)) 478 fi 479 480 FAIL=$(($FAIL+$fail)) 481 PASS=$(($PASS+$pass)) 482 483 for FILE in $(ls | tr ' ' '\n' | grep -v EQ | sort) 484 do 485 if [ -d "$FILE" ]; 486 then 487 cd $FILE 488 afunc 489 cd .. 490 fi 491 done 492} 493 494afunc 495 496echo "****************************************************" 497echo "Results for `pwd`:" 498echo "using `$CC --version`" 499echo "with $OPTIONS $HEADER_INCLUDE $SOURCE_LIB" 500echo "----------------------------------------------------" 501echo "sections without tests : $UNIMPLEMENTED" 502echo "sections with failures : $IMPLEMENTED_FAIL" 503echo "sections without failures: $IMPLEMENTED_PASS" 504echo " + ----" 505echo "total number of sections : $(($UNIMPLEMENTED+$IMPLEMENTED_FAIL+$IMPLEMENTED_PASS))" 506echo "----------------------------------------------------" 507echo "number of tests failed : $FAIL" 508echo "number of tests passed : $PASS" 509echo " + ----" 510echo "total number of tests : $(($FAIL+$PASS))" 511echo "****************************************************" 512 513exit $FAIL 514