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