1 #!/bin/sh 2 # 3 # Copyright (C) 2010 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 # This shell script is used to run all NDK build tests in a row. 18 # "Build tests" are tests that check the building features of the NDK 19 # but do not run anything on target devices/emulators. 20 # 21 22 # You need to define the NDK 23 24 PROGDIR=`dirname $0` 25 PROGDIR=`cd $PROGDIR && pwd` 26 27 # Assume that we are under tests/ 28 # and that the samples will be under samples/ and platforms/android-N/samples/ 29 # 30 ROOTDIR=`cd $PROGDIR/.. && pwd` 31 . $ROOTDIR/build/core/ndk-common.sh 32 33 # The list of tests that are too long to be part of a normal run of 34 # run-tests.sh. Most of these do not run properly at the moment. 35 LONG_TESTS="prebuild-stlport test-stlport test-gnustl" 36 37 # 38 # Parse options 39 # 40 VERBOSE=no 41 ABI=armeabi 42 PLATFORM="" 43 NDK_ROOT= 44 JOBS=$BUILD_NUM_CPUS 45 find_program ADB_CMD adb 46 TESTABLES="samples build device awk" 47 FULL_TESTS=no 48 RUN_TESTS= 49 NDK_PACKAGE= 50 WINE= 51 52 while [ -n "$1" ]; do 53 opt="$1" 54 optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` 55 case "$opt" in 56 --help|-h|-\?) 57 OPTION_HELP=yes 58 ;; 59 --verbose) 60 if [ "$VERBOSE" = "yes" ] ; then 61 VERBOSE2=yes 62 else 63 VERBOSE=yes 64 fi 65 ;; 66 --abi=*) 67 ABI="$optarg" 68 ;; 69 --platform=*) 70 PLATFORM="$optarg" 71 ;; 72 --ndk=*) 73 NDK_ROOT="$optarg" 74 ;; 75 --full) 76 FULL_TESTS=yes; 77 ;; 78 --test=*) 79 RUN_TESTS="$RUN_TESTS $optarg" 80 ;; 81 --package=*) 82 NDK_PACKAGE="$optarg" 83 ;; 84 -j*) 85 JOBS=`expr "$opt" : '-j\(.*\)'` 86 shift 87 ;; 88 --jobs=*) 89 JOBS="$optarg" 90 ;; 91 --adb=*) 92 ADB_CMD="$optarg" 93 ;; 94 --only-samples) 95 TESTABLES=samples 96 ;; 97 --only-build) 98 TESTABLES=build 99 ;; 100 --only-device) 101 TESTABLES=device 102 ;; 103 --only-awk) 104 TESTABLES=awk 105 ;; 106 --wine) 107 WINE=yes 108 ;; 109 -*) # unknown options 110 echo "ERROR: Unknown option '$opt', use --help for list of valid ones." 111 exit 1 112 ;; 113 *) # Simply record parameter 114 if [ -z "$PARAMETERS" ] ; then 115 PARAMETERS="$opt" 116 else 117 PARAMETERS="$PARAMETERS $opt" 118 fi 119 ;; 120 esac 121 shift 122 done 123 124 if [ "$OPTION_HELP" = "yes" ] ; then 125 echo "Usage: $PROGNAME [options]" 126 echo "" 127 echo "Run all NDK automated tests at once." 128 echo "" 129 echo "Valid options:" 130 echo "" 131 echo " --help|-h|-? Print this help" 132 echo " --verbose Enable verbose mode" 133 echo " --test=<name> Run selected test (all if not used)" 134 echo " --ndk=<path> Path to NDK to test [$ROOTDIR]" 135 echo " --package=<path> Path to NDK package to test" 136 echo " -j<N> --jobs=<N> Launch parallel builds [$JOBS]" 137 echo " --abi=<name> Only run tests for the specific ABI [$ABI]" 138 echo " --platform=<name> Force API level for testing; platform=<android-x>" 139 echo " --adb=<file> Specify adb executable for device tests" 140 echo " --only-samples Only rebuild samples" 141 echo " --only-build Only rebuild build tests" 142 echo " --only-device Only rebuild & run device tests" 143 echo " --only-awk Only run awk tests." 144 echo " --full Run all device tests, even very long ones." 145 echo " --wine Build all tests with wine on Linux" 146 echo "" 147 echo "NOTE: You cannot use --ndk and --package at the same time." 148 echo "" 149 echo "You can use --test=<name> several times to run several tests" 150 echo "during the same invokation." 151 exit 0 152 fi 153 154 # Run a command in ADB. 155 # 156 # This is needed because "adb shell" does not return the proper status 157 # of the launched command, so we need to 158 # 159 adb_cmd () 160 { 161 local RET ADB_CMD_LOG 162 # mktemp under Mac OS X requires the -t option 163 ADB_CMD_LOG=$(mktemp -t XXXXXXXX) 164 if [ $VERBOSE = "yes" ] ; then 165 echo "$ADB_CMD shell $@" 166 $ADB_CMD shell $@ ";" echo \$? | tee $ADB_CMD_LOG 167 else 168 $ADB_CMD shell $@ ";" echo \$? > $ADB_CMD_LOG 169 fi 170 # Get last line in log, should be OK or KO 171 # +Get rid of \r at the end of lines 172 RET=`sed -e 's![[:cntrl:]]!!g' $ADB_CMD_LOG | tail -n1` 173 rm -f $ADB_CMD_LOG 174 return $RET 175 } 176 177 # Make a directory path on device 178 # 179 # The 'mkdir' command on the Android device does not 180 # support the '-p' option. This function will test 181 # for the existence of the parent directory and recursively 182 # call itself until it files a parent which exists; then 183 # create the requested directory. 184 adb_cmd_mkdir () 185 { 186 local FULLDIR BASEDIR 187 FULLDIR=$1 188 BASEDIR=`dirname $FULLDIR` 189 190 #run $ADB_CMD shell "ls $BASEDIR 1>/dev/null 2>&1" 191 adb_cmd "ls $BASEDIR 1>/dev/null 2>&1" 192 if [ $? != 0 ] ; then 193 if [ $BASEDIR = "/" ] ; then 194 dump "ERROR: Could not find the root (/) directory on the device!" 195 exit 1 196 else 197 adb_cmd_mkdir $BASEDIR 198 adb_cmd_mkdir $FULLDIR 199 fi 200 else 201 #run $ADB_CMD shell "mkdir $FULLDIR" 202 # If the directory doesn't exist, make it 203 adb_cmd "ls $FULLDIR 1>/dev/null 2>&1 || mkdir $FULLDIR" 204 if [ $? != 0 ] ; then 205 dump "ERROR: Could not mkdir '$FULLDIR' on the device!" 206 exit 1 207 fi 208 fi 209 } 210 211 # Returns 0 if a variable containing one or more items separated 212 # by spaces contains a given value. 213 # $1: variable name (e.g. FOO) 214 # $2: value to test 215 var_list_contains () 216 { 217 echo `var_value $1` | tr ' ' '\n' | grep -q -F -x -e "$2" 218 } 219 220 # 221 # List of stuff to actually tests 222 # 223 is_testable () { 224 var_list_contains TESTABLES "$1" 225 } 226 227 # is_buildable returns 0 if a test should be built/run for this invocation 228 # $1: test path 229 if [ -n "$RUN_TESTS" ] ; then 230 is_buildable () { 231 test -f $1/jni/Android.mk && 232 var_list_contains RUN_TESTS "`basename $1`" 233 } 234 elif [ "$FULL_TESTS" = "yes" ] ; then 235 is_buildable () { 236 test -f $1/jni/Android.mk 237 } 238 else # !FULL_TESTS 239 is_buildable () { 240 test -f $1/jni/Android.mk || return 1 241 ! var_list_contains LONG_TESTS "`basename $1`" || return 1 242 } 243 fi # !FULL_TESTS 244 245 246 TEST_DIR="/tmp/ndk-$USER/tests" 247 mkdir -p $TEST_DIR 248 setup_default_log_file "$TEST_DIR/build-tests.log" 249 250 if [ -n "$NDK_PACKAGE" ] ; then 251 if [ -n "$NDK_ROOT" ] ; then 252 dump "ERROR: You can't use --ndk and --package at the same time!" 253 exit 1 254 fi 255 NDK_ROOT=/tmp/ndk-tests/install 256 mkdir -p "$NDK_ROOT" && rm -rf "$NDK_ROOT/*" 257 dump "Unpacking NDK package to $NDK_ROOT" 258 unpack_archive "$NDK_PACKAGE" "$NDK_ROOT" 259 NDK_ROOT=`ls -d $NDK_ROOT/*` 260 fi 261 262 # 263 # Check the NDK install path. 264 # 265 if [ -n "$NDK_ROOT" ] ; then 266 if [ ! -d "$NDK_ROOT" ] ; then 267 dump "ERROR: Your --ndk option does not point to a directory: $NDK_ROOT" 268 dump "Please use a valid path for this option." 269 exit 1 270 fi 271 if [ ! -f "$NDK_ROOT/ndk-build" -o ! -f "$NDK_ROOT/build/core/ndk-common.sh" ] ; then 272 dump "ERROR: Your --ndk option does not point to a valid NDK install: $NDK_ROOT" 273 dump "Please use a valid NDK install path for this option." 274 exit 3 275 fi 276 NDK="$NDK_ROOT" 277 else 278 NDK="$ROOTDIR" 279 fi 280 281 # 282 # Create log file 283 # 284 285 BUILD_DIR=$TEST_DIR/build 286 mkdir -p "$BUILD_DIR" && rm -rf "$BUILD_DIR/*" 287 288 ### 289 ### RUN AWK TESTS 290 ### 291 292 # Run a simple awk script 293 # $1: awk script to run 294 # $2: input file 295 # $3: expected output file 296 # $4+: optional additional command-line arguments for the awk command 297 run_awk_test () 298 { 299 local SCRIPT="$1" 300 local SCRIPT_NAME="`basename $SCRIPT`" 301 local INPUT="$2" 302 local INPUT_NAME="`basename $INPUT`" 303 local EXPECTED="$3" 304 local EXPECTED_NAME="`basename $EXPECTED`" 305 shift; shift; shift; 306 local OUTPUT="$BUILD_DIR/$EXPECTED_NAME" 307 if [ "$VERBOSE2" = "yes" ]; then 308 echo "### COMMAND: awk -f \"$SCRIPT\" $@ < \"$INPUT\" > \"$OUTPUT\"" 309 fi 310 awk -f "$SCRIPT" $@ < "$INPUT" > "$OUTPUT" 311 fail_panic "Can't run awk script: $SCRIPT" 312 if [ "$VERBOSE2" = "yes" ]; then 313 echo "OUTPUT FROM SCRIPT:" 314 cat "$OUTPUT" 315 echo "EXPECTED VALUES:" 316 cat "$EXPECTED" 317 fi 318 cmp -s "$OUTPUT" "$EXPECTED" 319 if [ $? = 0 ] ; then 320 echo "Awk script: $SCRIPT_NAME: passed $INPUT_NAME" 321 if [ "$VERBOSE2" = "yes" ]; then 322 cat "$OUTPUT" 323 fi 324 else 325 if [ "$VERBOSE" = "yes" ]; then 326 run diff -burN "$EXPECTED" "$OUTPUT" 327 fi 328 echo "Awk script: $SCRIPT_NAME: $INPUT_NAME FAILED!!" 329 rm -f "$OUTPUT" 330 exit 1 331 fi 332 } 333 334 run_awk_test_dir () 335 { 336 local SCRIPT_NAME="`basename \"$DIR\"`" 337 local SCRIPT="$ROOTDIR/build/awk/$SCRIPT_NAME.awk" 338 local INPUT 339 local OUTPUT 340 if [ ! -f "$SCRIPT" ]; then 341 echo "Awk script: $SCRIPT_NAME: Missing script: $SCRIPT" 342 continue 343 fi 344 for INPUT in `ls "$PROGDIR"/awk/$SCRIPT_NAME/*.in`; do 345 OUTPUT=`echo $INPUT | sed 's/\.in$/.out/g'` 346 if [ ! -f "$OUTPUT" ]; then 347 echo "Awk script: $SCRIPT_NAME: Missing awk output file: $OUTPUT" 348 continue 349 fi 350 run_awk_test "$SCRIPT" "$INPUT" "$OUTPUT" 351 done 352 } 353 354 if is_testable awk; then 355 AWKDIR="$ROOTDIR/build/awk" 356 for DIR in `ls -d "$PROGDIR"/awk/*`; do 357 run_awk_test_dir "$DIR" 358 done 359 fi 360 361 ### 362 ### REBUILD ALL SAMPLES FIRST 363 ### 364 365 # Special case, if ABI is 'armeabi' or 'armeabi-v7a' 366 # we want to build both armeabi and armeabi-v7a machine code 367 # even if we will only run the armeabi test programs on the 368 # device. This is done by not forcing the definition of APP_ABI 369 NDK_BUILD_FLAGS="-B" 370 case $ABI in 371 armeabi|armeabi-v7a) 372 ;; 373 x86) 374 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI" 375 ;; 376 *) 377 echo "ERROR: Unsupported abi value: $ABI" 378 exit 1 379 ;; 380 esac 381 382 # Force all tests to run at one API level 383 if [ "$PLATFORM" != "" ]; then 384 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_PLATFORM=$PLATFORM" 385 fi 386 387 # Use --verbose twice to see build commands for the tests 388 if [ "$VERBOSE2" = "yes" ] ; then 389 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS V=1" 390 fi 391 392 run_ndk_build () 393 { 394 if [ "$WINE" ]; then 395 run wine cmd /c Z:$NDK/ndk-build.cmd -j$JOBS "$@" 396 else 397 run $NDK/ndk-build -j$JOBS "$@" 398 fi 399 } 400 401 build_project () 402 { 403 local NAME=`basename $1` 404 local DIR="$BUILD_DIR/$NAME" 405 if [ -f "$1/BROKEN_BUILD" ] ; then 406 echo "Skipping $1: (build)" 407 return 0 408 fi 409 rm -rf "$DIR" && cp -r "$1" "$DIR" 410 (cd "$DIR" && run_ndk_build $NDK_BUILD_FLAGS) 411 if [ $? != 0 ] ; then 412 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!" 413 exit 1 414 fi 415 } 416 417 # 418 # Determine list of samples directories. 419 # 420 if is_testable samples; then 421 if [ -f "$NDK/RELEASE.TXT" ] ; then 422 # This is a release package, all samples should be under $NDK/samples 423 SAMPLES_DIRS="$NDK/samples" 424 if [ ! -d "$SAMPLES_DIRS" ] ; then 425 dump "ERROR: Missing samples directory: $SAMPLES_DIRS" 426 dump "Your NDK release installation is broken!" 427 exit 1 428 fi 429 log "Using release NDK samples from: $SAMPLES_DIRS" 430 else 431 # This is a development work directory, we will take the samples 432 # directly from development/ndk. 433 DEVNDK_DIR=`dirname $NDK`/development/ndk 434 if [ ! -d "$DEVNDK_DIR" ] ; then 435 dump "ERROR: Could not find development NDK directory: $DEVNDK_DIR" 436 dump "Please clone platform/development.git from android.googlesource.com" 437 exit 1 438 fi 439 SAMPLES_DIRS="$DEVNDK_DIR/samples" 440 for DIR in `ls -d $DEVNDK_DIR/platforms/android-*/samples`; do 441 SAMPLES_DIRS="$SAMPLES_DIRS $DIR" 442 done 443 dump "Using development NDK samples from $DEVNDK_DIR" 444 if [ "$VERBOSE" = "yes" ] ; then 445 echo "$SAMPLES_DIRS" | tr ' ' '\n' 446 fi 447 fi 448 449 # 450 # Copy the samples to a temporary build directory 451 452 build_sample () 453 { 454 echo "Building NDK sample: `basename $1`" 455 build_project $1 456 } 457 458 for DIR in $SAMPLES_DIRS; do 459 for SUBDIR in `ls -d $DIR/*`; do 460 if is_buildable $SUBDIR; then 461 build_sample $SUBDIR 462 fi 463 done 464 done 465 fi 466 467 ### 468 ### BUILD PROJECTS UNDER tests/build/ 469 ### 470 471 if is_testable build; then 472 build_build_test () 473 { 474 echo "Building NDK build test: `basename $1`" 475 if [ -f $1/build.sh ]; then 476 export NDK 477 run $1/build.sh "$NDK_BUILD_FLAGS" 478 if [ $? != 0 ]; then 479 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!" 480 exit 1 481 fi 482 else 483 build_project $1 484 fi 485 } 486 487 for DIR in `ls -d $ROOTDIR/tests/build/*`; do 488 if is_buildable $DIR; then 489 build_build_test $DIR 490 fi 491 done 492 fi 493 494 ### 495 ### BUILD PROJECTS UNDER tests/device/ 496 ### XXX: TODO: RUN THEM ON A DEVICE/EMULATOR WITH ADB 497 ### 498 499 if is_testable device; then 500 build_device_test () 501 { 502 # Do not build test if BROKEN_BUILD is defined 503 if [ -f "$1/BROKEN_BUILD" ] ; then 504 echo "Skipping broken device test build: `basename $1`" 505 return 0 506 fi 507 echo "Building NDK device test: `basename $1` in $1" 508 build_project $1 509 } 510 511 run_device_test () 512 { 513 local SRCDIR="$BUILD_DIR/`basename $1`/libs/$ABI" 514 local DSTDIR="$2/ndk-tests" 515 local SRCFILE 516 local DSTFILE 517 local PROGRAMS= 518 local PROGRAM 519 # Do not run the test if BROKEN_RUN is defined 520 if [ -f "$1/BROKEN_RUN" -o -f "$1/BROKEN_BUILD" ] ; then 521 dump "Skipping NDK device test run: `basename $1`" 522 return 0 523 fi 524 if [ ! -d "$SRCDIR" ]; then 525 dump "Skipping NDK device test run (no $ABI binaries): `basename $1`" 526 return 0 527 fi 528 # First, copy all files to /data/local, except for gdbserver 529 # or gdb.setup. 530 adb_cmd_mkdir $DSTDIR 531 for SRCFILE in `ls $SRCDIR`; do 532 DSTFILE=`basename $SRCFILE` 533 if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then 534 continue 535 fi 536 DSTFILE="$DSTDIR/$DSTFILE" 537 run $ADB_CMD push "$SRCDIR/$SRCFILE" "$DSTFILE" && 538 run $ADB_CMD shell chmod 0755 $DSTFILE 539 if [ $? != 0 ] ; then 540 dump "ERROR: Could not install $SRCFILE to device!" 541 exit 1 542 fi 543 # If its name doesn't end with .so, add it to PROGRAMS 544 echo "$DSTFILE" | grep -q -e '\.so$' 545 if [ $? != 0 ] ; then 546 PROGRAMS="$PROGRAMS $DSTFILE" 547 fi 548 done 549 for PROGRAM in $PROGRAMS; do 550 dump "Running device test: `basename $PROGRAM`" 551 adb_cmd LD_LIBRARY_PATH="$DSTDIR" $PROGRAM 552 if [ $? != 0 ] ; then 553 dump " ---> TEST FAILED!!" 554 fi 555 done 556 # Cleanup 557 adb_cmd rm -r $DSTDIR 558 } 559 560 for DIR in `ls -d $ROOTDIR/tests/device/*`; do 561 if is_buildable $DIR; then 562 build_device_test $DIR 563 fi 564 done 565 566 # Do we have adb and any device connected here? 567 # If not, we can't run our tests. 568 # 569 SKIP_TESTS=no 570 if [ -z "$ADB_CMD" ] ; then 571 dump "WARNING: No 'adb' in your path!" 572 SKIP_TESTS=yes 573 else 574 ADB_DEVICES=`$ADB_CMD devices` 575 log2 "ADB devices: $ADB_DEVICES" 576 ADB_DEVCOUNT=`echo "$ADB_DEVICES" | wc -l` 577 ADB_DEVCOUNT=`expr $ADB_DEVCOUNT - 1` 578 log2 "ADB Device count: $ADB_DEVCOUNT" 579 if [ "$ADB_DEVCOUNT" = "0" ]; then 580 dump "WARNING: No device connected to adb!" 581 SKIP_TESTS=yes 582 elif [ "$ADB_DEVCOUNT" != 1 -a -z "$ANDROID_SERIAL" ] ; then 583 dump "WARNING: More than one device connected to adb. Please define ANDROID_SERIAL!" 584 SKIP_TESTS=yes 585 fi 586 echo "$ADB_DEVICES" | grep -q -e "offline" 587 if [ $? = 0 ] ; then 588 dump "WARNING: Device is offline, can't run device tests!" 589 SKIP_TESTS=yes 590 fi 591 fi 592 593 if [ "$SKIP_TESTS" = "yes" ] ; then 594 dump "SKIPPING RUNNING TESTS ON DEVICE!" 595 else 596 for DIR in `ls -d $ROOTDIR/tests/device/*`; do 597 log "Running device test: $DIR" 598 if is_buildable $DIR; then 599 run_device_test $DIR /data/local 600 fi 601 done 602 fi 603 fi 604 605 dump "Cleaning up..." 606 rm -rf $BUILD_DIR 607 dump "Done." 608