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 24PROGDIR=`dirname $0` 25PROGDIR=`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# 30ROOTDIR=`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. 35LONG_TESTS="prebuild-stlport test-stlport test-gnustl" 36 37# 38# Parse options 39# 40VERBOSE=no 41ABI=default 42PLATFORM="" 43NDK_ROOT= 44JOBS=$BUILD_NUM_CPUS 45find_program ADB_CMD adb 46TESTABLES="samples build device awk" 47FULL_TESTS=no 48RUN_TESTS= 49NDK_PACKAGE= 50WINE= 51 52while [ -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=*) # Deprecated, but keep it just in case. 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 new test name 114 RUN_TESTS=$RUN_TESTS" $opt" 115 ;; 116 esac 117 shift 118done 119 120if [ "$OPTION_HELP" = "yes" ] ; then 121 echo "Usage: $PROGNAME [options] [testname1 [testname2...]]" 122 echo "" 123 echo "Run NDK automated tests. Without any parameter, this will try to" 124 echo "run all standard tests, except those are tagged broken. You can" 125 echo "also select/enforce specific tests by listing their name on the" 126 echo "command-line." 127 echo "" 128 echo "Valid options:" 129 echo "" 130 echo " --help|-h|-? Print this help" 131 echo " --verbose Enable verbose mode (can be used several times)" 132 echo " --ndk=<path> Path to NDK to test [$ROOTDIR]" 133 echo " --package=<path> Path to NDK package to test" 134 echo " -j<N> --jobs=<N> Launch parallel builds [$JOBS]" 135 echo " --abi=<name> Only run tests for the specific ABI [$ABI]" 136 echo " --platform=<name> Force API level for testing; platform=<android-x>" 137 echo " --adb=<file> Specify adb executable for device tests" 138 echo " --only-samples Only rebuild samples" 139 echo " --only-build Only rebuild build tests" 140 echo " --only-device Only rebuild & run device tests" 141 echo " --only-awk Only run awk tests." 142 echo " --full Run all device tests, even very long ones." 143 echo " --wine Build all tests with wine on Linux" 144 echo "" 145 echo "NOTE: You cannot use --ndk and --package at the same time." 146 echo "" 147 exit 0 148fi 149 150# Run a command in ADB. 151# 152# This is needed because "adb shell" does not return the proper status 153# of the launched command, so we need to add it to the output, and grab 154# it after that. 155# 156adb_cmd () 157{ 158 local RET ADB_CMD_LOG 159 # mktemp under Mac OS X requires the -t option 160 ADB_CMD_LOG=$(mktemp -t XXXXXXXX) 161 if [ $VERBOSE = "yes" ] ; then 162 echo "$ADB_CMD shell $@" 163 $ADB_CMD shell $@ ";" echo \$? | tee $ADB_CMD_LOG 164 else 165 $ADB_CMD shell $@ ";" echo \$? > $ADB_CMD_LOG 166 fi 167 # Get last line in log, should be OK or KO 168 # +Get rid of \r at the end of lines 169 RET=`sed -e 's![[:cntrl:]]!!g' $ADB_CMD_LOG | tail -n1` 170 rm -f $ADB_CMD_LOG 171 return $RET 172} 173 174# Make a directory path on device 175# 176# The 'mkdir' command on the Android device does not 177# support the '-p' option. This function will test 178# for the existence of the parent directory and recursively 179# call itself until it files a parent which exists; then 180# create the requested directory. 181adb_cmd_mkdir () 182{ 183 local FULLDIR BASEDIR 184 FULLDIR=$1 185 BASEDIR=`dirname $FULLDIR` 186 187 #run $ADB_CMD shell "ls $BASEDIR 1>/dev/null 2>&1" 188 adb_cmd "ls $BASEDIR 1>/dev/null 2>&1" 189 if [ $? != 0 ] ; then 190 if [ $BASEDIR = "/" ] ; then 191 dump "ERROR: Could not find the root (/) directory on the device!" 192 exit 1 193 else 194 adb_cmd_mkdir $BASEDIR 195 adb_cmd_mkdir $FULLDIR 196 fi 197 else 198 #run $ADB_CMD shell "mkdir $FULLDIR" 199 # If the directory doesn't exist, make it 200 adb_cmd "ls $FULLDIR 1>/dev/null 2>&1 || mkdir $FULLDIR" 201 if [ $? != 0 ] ; then 202 dump "ERROR: Could not mkdir '$FULLDIR' on the device!" 203 exit 1 204 fi 205 fi 206} 207 208# Returns 0 if a variable containing one or more items separated 209# by spaces contains a given value. 210# $1: variable name (e.g. FOO) 211# $2: value to test 212var_list_contains () 213{ 214 echo `var_value $1` | tr ' ' '\n' | grep -q -F -x -e "$2" 215} 216 217# 218# List of stuff to actually tests 219# 220is_testable () { 221 var_list_contains TESTABLES "$1" 222} 223 224# is_buildable returns 0 if a test should be built/run for this invocation 225# $1: test path 226if [ -n "$RUN_TESTS" ] ; then 227 is_buildable () { 228 [ -f $1/build.sh -o -f $1/jni/Android.mk ] && 229 var_list_contains RUN_TESTS "`basename $1`" 230 } 231elif [ "$FULL_TESTS" = "yes" ] ; then 232 is_buildable () { 233 [ -f $1/build.sh -o -f $1/jni/Android.mk ] 234 } 235else # !FULL_TESTS 236 is_buildable () { 237 [ -f $1/build.sh -o -f $1/jni/Android.mk ] || return 1 238 ! var_list_contains LONG_TESTS "`basename $1`" || return 1 239 } 240fi # !FULL_TESTS 241 242 243TEST_DIR="/tmp/ndk-$USER/tests" 244mkdir -p $TEST_DIR 245setup_default_log_file "$TEST_DIR/build-tests.log" 246 247if [ -n "$NDK_PACKAGE" ] ; then 248 if [ -n "$NDK_ROOT" ] ; then 249 dump "ERROR: You can't use --ndk and --package at the same time!" 250 exit 1 251 fi 252 NDK_ROOT=/tmp/ndk-tests/install 253 mkdir -p "$NDK_ROOT" && rm -rf "$NDK_ROOT/*" 254 dump "Unpacking NDK package to $NDK_ROOT" 255 unpack_archive "$NDK_PACKAGE" "$NDK_ROOT" 256 NDK_ROOT=`ls -d $NDK_ROOT/*` 257fi 258 259# 260# Check the NDK install path. 261# 262if [ -n "$NDK_ROOT" ] ; then 263 if [ ! -d "$NDK_ROOT" ] ; then 264 dump "ERROR: Your --ndk option does not point to a directory: $NDK_ROOT" 265 dump "Please use a valid path for this option." 266 exit 1 267 fi 268 if [ ! -f "$NDK_ROOT/ndk-build" -o ! -f "$NDK_ROOT/build/core/ndk-common.sh" ] ; then 269 dump "ERROR: Your --ndk option does not point to a valid NDK install: $NDK_ROOT" 270 dump "Please use a valid NDK install path for this option." 271 exit 3 272 fi 273 NDK="$NDK_ROOT" 274else 275 NDK="$ROOTDIR" 276fi 277 278# 279# Create log file 280# 281 282BUILD_DIR=$TEST_DIR/build 283mkdir -p "$BUILD_DIR" && rm -rf "$BUILD_DIR/*" 284 285### 286### RUN AWK TESTS 287### 288 289# Run a simple awk script 290# $1: awk script to run 291# $2: input file 292# $3: expected output file 293# $4+: optional additional command-line arguments for the awk command 294run_awk_test () 295{ 296 local SCRIPT="$1" 297 local SCRIPT_NAME="`basename $SCRIPT`" 298 local INPUT="$2" 299 local INPUT_NAME="`basename $INPUT`" 300 local EXPECTED="$3" 301 local EXPECTED_NAME="`basename $EXPECTED`" 302 shift; shift; shift; 303 local OUTPUT="$BUILD_DIR/$EXPECTED_NAME" 304 if [ "$VERBOSE2" = "yes" ]; then 305 echo "### COMMAND: awk -f \"$SCRIPT\" $@ < \"$INPUT\" > \"$OUTPUT\"" 306 fi 307 awk -f "$SCRIPT" $@ < "$INPUT" > "$OUTPUT" 308 fail_panic "Can't run awk script: $SCRIPT" 309 if [ "$VERBOSE2" = "yes" ]; then 310 echo "OUTPUT FROM SCRIPT:" 311 cat "$OUTPUT" 312 echo "EXPECTED VALUES:" 313 cat "$EXPECTED" 314 fi 315 cmp -s "$OUTPUT" "$EXPECTED" 316 if [ $? = 0 ] ; then 317 echo "Awk script: $SCRIPT_NAME: passed $INPUT_NAME" 318 if [ "$VERBOSE2" = "yes" ]; then 319 cat "$OUTPUT" 320 fi 321 else 322 if [ "$VERBOSE" = "yes" ]; then 323 run diff -burN "$EXPECTED" "$OUTPUT" 324 fi 325 echo "Awk script: $SCRIPT_NAME: $INPUT_NAME FAILED!!" 326 rm -f "$OUTPUT" 327 exit 1 328 fi 329} 330 331run_awk_test_dir () 332{ 333 local SCRIPT_NAME="`basename \"$DIR\"`" 334 local SCRIPT="$ROOTDIR/build/awk/$SCRIPT_NAME.awk" 335 local INPUT 336 local OUTPUT 337 if [ ! -f "$SCRIPT" ]; then 338 echo "Awk script: $SCRIPT_NAME: Missing script: $SCRIPT" 339 continue 340 fi 341 for INPUT in `ls "$PROGDIR"/awk/$SCRIPT_NAME/*.in`; do 342 OUTPUT=`echo $INPUT | sed 's/\.in$/.out/g'` 343 if [ ! -f "$OUTPUT" ]; then 344 echo "Awk script: $SCRIPT_NAME: Missing awk output file: $OUTPUT" 345 continue 346 fi 347 run_awk_test "$SCRIPT" "$INPUT" "$OUTPUT" 348 done 349} 350 351if is_testable awk; then 352 AWKDIR="$ROOTDIR/build/awk" 353 for DIR in `ls -d "$PROGDIR"/awk/*`; do 354 run_awk_test_dir "$DIR" 355 done 356fi 357 358### 359### REBUILD ALL SAMPLES FIRST 360### 361 362NDK_BUILD_FLAGS="-B" 363case $ABI in 364 default) # Let the APP_ABI in jni/Application.mk decide what to build 365 ;; 366 armeabi|armeabi-v7a|x86|mips) 367 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI" 368 ;; 369 *) 370 echo "ERROR: Unsupported abi value: $ABI" 371 exit 1 372 ;; 373esac 374 375# Force all tests to run at one API level 376if [ "$PLATFORM" != "" ]; then 377 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_PLATFORM=$PLATFORM" 378fi 379 380# Use --verbose twice to see build commands for the tests 381if [ "$VERBOSE2" = "yes" ] ; then 382 NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS V=1" 383fi 384 385run_ndk_build () 386{ 387 if [ "$WINE" ]; then 388 run wine cmd /c Z:$NDK/ndk-build.cmd -j$JOBS "$@" 389 else 390 run $NDK/ndk-build -j$JOBS "$@" 391 fi 392} 393 394get_build_var () 395{ 396 if [ -z "$GNUMAKE" ] ; then 397 GNUMAKE=make 398 fi 399 $GNUMAKE --no-print-dir -f $NDK/build/core/build-local.mk -C $DIR DUMP_$1 | tail -1 400} 401 402build_project () 403{ 404 local NAME=`basename $1` 405 local CHECK_ABI=$2 406 local DIR="$BUILD_DIR/$NAME" 407 if [ -f "$1/BROKEN_BUILD" -a -z "$RUN_TESTS" ] ; then 408 echo "Skipping `basename $1`: (build)" 409 return 0 410 fi 411 rm -rf "$DIR" && cp -r "$1" "$DIR" 412 if [ "$ABI" != "default" -a "$CHECK_ABI" = "yes" ] ; then 413 # check APP_ABI 414 local APP_ABIS=`get_build_var APP_ABI` 415 APP_ABIS=$APP_ABIS" " 416 if [ "$APP_ABIS" != "${APP_ABIS%%all*}" ] ; then 417 # replace the first "all" with all available ABIs 418 ALL_ABIS=`get_build_var NDK_ALL_ABIS` 419 APP_ABIS_FRONT="${APP_ABIS%%all*}" 420 APP_ABIS_BACK="${APP_ABIS#*all}" 421 APP_ABIS="${APP_ABIS_FRONT}${ALL_ABIS}${APP_ABIS_BACK}" 422 fi 423 if [ "$APP_ABIS" = "${APP_ABIS%$ABI *}" ] ; then 424 echo "Skipping `basename $1`: incompatible ABI, needs $APP_ABIS" 425 return 0 426 fi 427 fi 428 # build it 429 (run cd "$DIR" && run_ndk_build $NDK_BUILD_FLAGS) 430 RET=$? 431 if [ -f "$1/BUILD_SHOULD_FAIL" ]; then 432 if [ $RET = 0 ]; then 433 echo "!!! FAILURE: BUILD SHOULD HAVE FAILED [$1]" 434 exit 1 435 fi 436 log "!!! SUCCESS: BUILD FAILED AS EXPECTED [$(basename $1)]" 437 RET=0 438 fi 439 if [ $RET != 0 ] ; then 440 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!" 441 exit 1 442 fi 443} 444 445# 446# Determine list of samples directories. 447# 448if is_testable samples; then 449 if [ -f "$NDK/RELEASE.TXT" ] ; then 450 # This is a release package, all samples should be under $NDK/samples 451 SAMPLES_DIRS="$NDK/samples" 452 if [ ! -d "$SAMPLES_DIRS" ] ; then 453 dump "ERROR: Missing samples directory: $SAMPLES_DIRS" 454 dump "Your NDK release installation is broken!" 455 exit 1 456 fi 457 log "Using release NDK samples from: $SAMPLES_DIRS" 458 else 459 # This is a development work directory, we will take the samples 460 # directly from development/ndk. 461 DEVNDK_DIR=`dirname $NDK`/development/ndk 462 if [ ! -d "$DEVNDK_DIR" ] ; then 463 dump "ERROR: Could not find development NDK directory: $DEVNDK_DIR" 464 dump "Please clone platform/development.git from android.googlesource.com" 465 exit 1 466 fi 467 SAMPLES_DIRS="$DEVNDK_DIR/samples" 468 for DIR in `ls -d $DEVNDK_DIR/platforms/android-*/samples`; do 469 SAMPLES_DIRS="$SAMPLES_DIRS $DIR" 470 done 471 dump "Using development NDK samples from $DEVNDK_DIR" 472 if [ "$VERBOSE" = "yes" ] ; then 473 echo "$SAMPLES_DIRS" | tr ' ' '\n' 474 fi 475 fi 476 477 # 478 # Copy the samples to a temporary build directory 479 480 build_sample () 481 { 482 echo "Building NDK sample: `basename $1`" 483 build_project $1 "no" 484 } 485 486 for DIR in $SAMPLES_DIRS; do 487 for SUBDIR in `ls -d $DIR/*`; do 488 if is_buildable $SUBDIR; then 489 build_sample $SUBDIR 490 fi 491 done 492 done 493fi 494 495### 496### BUILD PROJECTS UNDER tests/build/ 497### 498 499if is_testable build; then 500 build_build_test () 501 { 502 echo "Building NDK build test: `basename $1`" 503 if [ -f $1/build.sh ]; then 504 export NDK 505 run $1/build.sh $NDK_BUILD_FLAGS 506 if [ $? != 0 ]; then 507 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!" 508 exit 1 509 fi 510 else 511 build_project $1 "yes" 512 fi 513 } 514 515 for DIR in `ls -d $ROOTDIR/tests/build/*`; do 516 if is_buildable $DIR; then 517 build_build_test $DIR 518 fi 519 done 520fi 521 522### 523### BUILD PROJECTS UNDER tests/device/ 524### XXX: TODO: RUN THEM ON A DEVICE/EMULATOR WITH ADB 525### 526 527CPU_ABIS= 528if is_testable device; then 529 build_device_test () 530 { 531 # Do not build test if BROKEN_BUILD is defined, except if we 532 # Have listed the test explicitely. 533 if [ -f "$1/BROKEN_BUILD" -a -z "$RUN_TESTS" ] ; then 534 echo "Skipping broken device test build: `basename $1`" 535 return 0 536 fi 537 echo "Building NDK device test: `basename $1` in $1" 538 build_project $1 "yes" 539 } 540 541 run_device_test () 542 { 543 local SRCDIR 544 local DSTDIR="$2/ndk-tests" 545 local SRCFILE 546 local DSTFILE 547 local PROGRAMS= 548 local PROGRAM 549 # Do not run the test if BROKEN_RUN is defined 550 if [ -f "$1/BROKEN_RUN" -o -f "$1/BROKEN_BUILD" ] ; then 551 if [ -z "$RUN_TESTS" ]; then 552 dump "Skipping NDK device test run: `basename $1`" 553 return 0 554 fi 555 fi 556 for CPU_ABI in $CPU_ABIS; do 557 SRCDIR="$BUILD_DIR/`basename $1`/libs/$CPU_ABI" 558 if [ -d "$SRCDIR" ]; then 559 break; 560 fi 561 done 562 if [ ! -d "$SRCDIR" ]; then 563 dump "Skipping NDK device test run (no $CPU_ABIS binaries): `basename $1`" 564 return 0 565 fi 566 # First, copy all files to the device, except for gdbserver 567 # or gdb.setup. 568 adb_cmd_mkdir $DSTDIR 569 for SRCFILE in `ls $SRCDIR`; do 570 DSTFILE=`basename $SRCFILE` 571 if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then 572 continue 573 fi 574 SRCFILE="$SRCDIR/$SRCFILE" 575 if [ $HOST_OS = cygwin ]; then 576 SRCFILE=`cygpath -m $SRCFILE` 577 fi 578 DSTFILE="$DSTDIR/$DSTFILE" 579 run $ADB_CMD push "$SRCFILE" "$DSTFILE" && 580 run $ADB_CMD shell chmod 0755 $DSTFILE 581 if [ $? != 0 ] ; then 582 dump "ERROR: Could not install $SRCFILE to device!" 583 exit 1 584 fi 585 # If its name doesn't end with .so, add it to PROGRAMS 586 echo "$DSTFILE" | grep -q -e '\.so$' 587 if [ $? != 0 ] ; then 588 PROGRAMS="$PROGRAMS $DSTFILE" 589 fi 590 done 591 for PROGRAM in $PROGRAMS; do 592 dump "Running device test: `basename $PROGRAM`" 593 adb_cmd LD_LIBRARY_PATH="$DSTDIR" $PROGRAM 594 if [ $? != 0 ] ; then 595 dump " ---> TEST FAILED!!" 596 fi 597 done 598 # Cleanup 599 adb_cmd rm -r $DSTDIR 600 } 601 602 for DIR in `ls -d $ROOTDIR/tests/device/*`; do 603 if is_buildable $DIR; then 604 build_device_test $DIR 605 fi 606 done 607 608 # Do we have adb and any device connected here? 609 # If not, we can't run our tests. 610 # 611 SKIP_TESTS=no 612 if [ -z "$ADB_CMD" ] ; then 613 dump "WARNING: No 'adb' in your path!" 614 SKIP_TESTS=yes 615 else 616 ADB_DEVICES=`$ADB_CMD devices | sed '/^$/d'` 617 log2 "ADB devices: $ADB_DEVICES" 618 ADB_DEVCOUNT=`echo "$ADB_DEVICES" | wc -l` 619 ADB_DEVCOUNT=`expr $ADB_DEVCOUNT - 1` 620 log2 "ADB Device count: $ADB_DEVCOUNT" 621 if [ "$ADB_DEVCOUNT" = "0" ]; then 622 dump "WARNING: No device connected to adb!" 623 SKIP_TESTS=yes 624 elif [ "$ADB_DEVCOUNT" != 1 -a -z "$ANDROID_SERIAL" ] ; then 625 dump "WARNING: More than one device connected to adb. Please define ANDROID_SERIAL!" 626 SKIP_TESTS=yes 627 fi 628 echo "$ADB_DEVICES" | grep -q -e "offline" 629 if [ $? = 0 ] ; then 630 dump "WARNING: Device is offline, can't run device tests!" 631 SKIP_TESTS=yes 632 fi 633 if [ "$ABI" != "default" ] ; then 634 CPU_ABIS=$ABI 635 else 636 # get device CPU_ABI and CPU_ABI2, each may contain list of abi, comma-delimited. 637 CPU_ABI1=`$ADB_CMD shell getprop ro.product.cpu.abi | tr -dc '[:print:]'` 638 CPU_ABI2=`$ADB_CMD shell getprop ro.product.cpu.abi2 | tr -dc '[:print:]'` 639 CPU_ABIS="$CPU_ABI1,$CPU_ABI2" 640 CPU_ABIS=$(echo $CPU_ABIS | tr ',' ' ') 641 fi 642 fi 643 644 if [ "$SKIP_TESTS" = "yes" ] ; then 645 dump "SKIPPING RUNNING TESTS ON DEVICE!" 646 else 647 for DIR in `ls -d $ROOTDIR/tests/device/*`; do 648 log "Running device test: $DIR" 649 if is_buildable $DIR; then 650 run_device_test $DIR /data/local/tmp 651 fi 652 done 653 fi 654fi 655 656dump "Cleaning up..." 657rm -rf $BUILD_DIR 658dump "Done." 659