Home | History | Annotate | Download | only in tests
      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 NDK_BUILDTOOLS_PATH=$ROOTDIR/build/tools
     32 . $NDK_BUILDTOOLS_PATH/ndk-common.sh
     33 . $NDK_BUILDTOOLS_PATH/prebuilt-common.sh
     34 
     35 # Defining _NDK_TESTING_ALL_=yes to put armeabi-v7a-hard in its own libs/armeabi-v7a-hard
     36 # directoy and tested separately from armeabi-v7a.  Some tests are now compiled with both
     37 # APP_ABI=armeabi-v7a and APP_ABI=armeabi-v7a-hard. Without _NDK_TESTING_ALL_=yes, tests
     38 # may fail to install due to race condition on the same libs/armeabi-v7a
     39 if [ -z "$_NDK_TESTING_ALL_" ]; then
     40    _NDK_TESTING_ALL_=all
     41 fi
     42 export _NDK_TESTING_ALL_
     43 
     44 # The list of tests that are too long to be part of a normal run of
     45 # run-tests.sh. Most of these do not run properly at the moment.
     46 LONG_TESTS="prebuild-stlport test-stlport test-gnustl-full \
     47 test-stlport_shared-exception test-stlport_static-exception \
     48 test-gnustl_shared-exception-full test-gnustl_static-exception-full \
     49 test-googletest-full test-libc++-shared-full test-libc++-static-full"
     50 
     51 #
     52 # Parse options
     53 #
     54 VERBOSE=no
     55 ABI=default
     56 PLATFORM=""
     57 NDK_ROOT=
     58 JOBS=$BUILD_NUM_CPUS
     59 find_program ADB_CMD adb
     60 TESTABLES="samples build device awk"
     61 FULL_TESTS=no
     62 RUN_TESTS=
     63 RUN_TESTS_FILTERED=
     64 NDK_PACKAGE=
     65 WINE=
     66 CONTINUE_ON_BUILD_FAIL=
     67 if [ -z "$TEST_DIR" ]; then
     68     TEST_DIR="/tmp/ndk-$USER/tests"
     69 fi
     70 if [ -z "$TARGET_TEST_SUBDIR" ]; then
     71     TARGET_TEST_SUBDIR="ndk-tests"
     72 fi
     73 
     74 while [ -n "$1" ]; do
     75     opt="$1"
     76     optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
     77     case "$opt" in
     78         --help|-h|-\?)
     79             OPTION_HELP=yes
     80             ;;
     81         --verbose)
     82             if [ "$VERBOSE" = "yes" ] ; then
     83                 VERBOSE2=yes
     84             else
     85                 VERBOSE=yes
     86             fi
     87             ;;
     88         --abi=*)
     89             ABI="$optarg"
     90             ;;
     91         --platform=*)
     92             PLATFORM="$optarg"
     93 	    ;;
     94         --test-dir=*)
     95             TEST_DIR="$optarg"
     96             ;;
     97         --ndk=*)
     98             NDK_ROOT="$optarg"
     99             ;;
    100         --full)
    101             FULL_TESTS=yes;
    102             ;;
    103         --test=*)
    104             RUN_TESTS="$RUN_TESTS $optarg"
    105             ;;
    106         --test-filtered=*)
    107             # same as --test but apply BROKEN_RUN too. Useful for projects with tons of test some of them can't run
    108             RUN_TESTS="$RUN_TESTS $optarg"
    109             RUN_TESTS_FILTERED="yes"
    110             ;;
    111         --package=*)
    112             NDK_PACKAGE="$optarg"
    113             ;;
    114         -j*)
    115             JOBS=`expr "$opt" : '-j\(.*\)'`
    116             shift
    117             ;;
    118         --jobs=*)
    119             JOBS="$optarg"
    120             ;;
    121         --adb=*)
    122             ADB_CMD="$optarg"
    123             ;;
    124         --only-samples)
    125             TESTABLES=samples
    126             ;;
    127         --only-build)
    128             TESTABLES=build
    129             ;;
    130         --only-device)
    131             TESTABLES=device
    132             ;;
    133         --only-awk)
    134             TESTABLES=awk
    135             ;;
    136         --wine)
    137             WINE=yes
    138             ;;
    139         --continue-on-build-fail)
    140             CONTINUE_ON_BUILD_FAIL=yes
    141             ;;
    142         -*) # unknown options
    143             echo "ERROR: Unknown option '$opt', use --help for list of valid ones."
    144             exit 1
    145         ;;
    146         *)  # Simply record new test name
    147             RUN_TESTS=$RUN_TESTS" $opt"
    148             ;;
    149     esac
    150     shift
    151 done
    152 
    153 if [ "$OPTION_HELP" = "yes" ] ; then
    154     echo "Usage: $PROGNAME [options] [testname1 [testname2...]]"
    155     echo ""
    156     echo "Run NDK automated tests. Without any parameter, this will try to"
    157     echo "run all standard tests, except those are tagged broken. You can"
    158     echo "also select/enforce specific tests by listing their name on the"
    159     echo "command-line."
    160     echo ""
    161     echo "Valid options:"
    162     echo ""
    163     echo "    --help|-h|-?      Print this help"
    164     echo "    --verbose         Enable verbose mode (can be used several times)"
    165     echo "    --ndk=<path>      Path to NDK to test [$ROOTDIR]"
    166     echo "    --package=<path>  Path to NDK package to test"
    167     echo "    -j<N> --jobs=<N>  Launch parallel builds [$JOBS]"
    168     echo "    --abi=<name>      Only run tests for the specific ABI [$ABI]"
    169     echo "    --platform=<name> Force API level for testing; platform=<android-x>"
    170     echo "    --adb=<file>      Specify adb executable for device tests"
    171     echo "    --only-samples    Only rebuild samples"
    172     echo "    --only-build      Only rebuild build tests"
    173     echo "    --only-device     Only rebuild & run device tests"
    174     echo "    --only-awk        Only run awk tests."
    175     echo "    --full            Run all device tests, even very long ones."
    176     echo "    --wine            Build all tests with wine on Linux"
    177     echo ""
    178     echo "NOTE: You cannot use --ndk and --package at the same time."
    179     echo ""
    180     exit 0
    181 fi
    182 
    183 # Run a command in ADB.
    184 #
    185 # This is needed because "adb shell" does not return the proper status
    186 # of the launched command, so we need to add it to the output, and grab
    187 # it after that.
    188 # $1: Device name
    189 # $2: Variable name that will contain the result
    190 # $3+: Command options
    191 adb_var_shell_cmd ()
    192 {
    193     # We need a temporary file to store the output of our command
    194     local ADB_SHELL_CMD_LOG RET OUT
    195     local DEVICE=$1
    196     local VARNAME=$2
    197     shift; shift;
    198     ADB_SHELL_CMD_LOG=$(mktemp -t XXXXXXXX)
    199     # Run the command, while storing the standard output to ADB_SHELL_CMD_LOG
    200     # and appending the exit code as the last line.
    201     if [ $VERBOSE = "yes" ] ; then
    202         echo "$ADB_CMD -s \"$DEVICE\" shell \"$@\""
    203         $ADB_CMD -s "$DEVICE" shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' | tee $ADB_SHELL_CMD_LOG
    204     else
    205         $ADB_CMD -s "$DEVICE" shell "$@" ";" echo \$? | sed -e 's![[:cntrl:]]!!g' > $ADB_SHELL_CMD_LOG
    206     fi
    207     # Get last line in log, which contains the exit code from the command
    208     RET=`sed -e '$!d' $ADB_SHELL_CMD_LOG`
    209     # Get output, which corresponds to everything except the last line
    210     OUT=`sed -e '$d' $ADB_SHELL_CMD_LOG`
    211     rm -f $ADB_SHELL_CMD_LOG
    212     if [ "$VARNAME" != "" ]; then
    213         eval $VARNAME=\"\$OUT\"
    214     fi
    215     return $RET
    216 }
    217 
    218 # Make a directory path on device
    219 #
    220 # The 'mkdir' command on the Android device does not
    221 # support the '-p' option. This function will test
    222 # for the existence of the parent directory and recursively
    223 # call itself until it files a parent which exists; then
    224 # create the requested directory.
    225 adb_shell_mkdir ()
    226 {
    227     local FULLDIR BASEDIR
    228     local DEVICE=$1
    229     local FULLDIR=$2
    230     local BASEDIR=`dirname $FULLDIR`
    231 
    232     adb_var_shell_cmd "$DEVICE" "" "ls $BASEDIR 1>/dev/null 2>&1"
    233     if [ $? != 0 ] ; then
    234         if [ $BASEDIR = "/" ] ; then
    235             dump "ERROR: Could not find the root (/) directory on the device!"
    236             exit 1
    237         else
    238             adb_shell_mkdir "$DEVICE" $BASEDIR
    239             adb_shell_mkdir "$DEVICE" $FULLDIR
    240         fi
    241     else
    242         #If the directory doesn't exist, make it
    243         adb_var_shell_cmd "$DEVICE" "" "ls $FULLDIR 1>/dev/null 2>&1 || mkdir $FULLDIR"
    244         if [ $? != 0 ] ; then
    245             dump "ERROR: Could not mkdir '$FULLDIR' on the device!"
    246             exit 1
    247         fi
    248     fi
    249 }
    250 
    251 # Returns 0 if a variable containing one or more items separated
    252 # by spaces contains a given value.
    253 # $1: variable name (e.g. FOO)
    254 # $2: value to test
    255 var_list_contains ()
    256 {
    257     echo `var_value $1` | tr ' ' '\n' | grep -q -F -x -e "$2"
    258 }
    259 
    260 #
    261 # List of stuff to actually tests
    262 #
    263 is_testable () {
    264     var_list_contains TESTABLES "$1"
    265 }
    266 
    267 # is_buildable returns 0 if a test should be built/run for this invocation
    268 # $1: test path
    269 if [ -n "$RUN_TESTS" ] ; then
    270     is_buildable () {
    271         [ -f $1/build.sh -o -f $1/jni/Android.mk ] &&
    272         var_list_contains RUN_TESTS "`basename $1`"
    273     }
    274 elif [ "$FULL_TESTS" = "yes" ] ; then
    275     is_buildable () {
    276         [ -f $1/build.sh -o -f $1/jni/Android.mk ]
    277     }
    278 else # !FULL_TESTS
    279     is_buildable () {
    280         [ -f $1/build.sh -o -f $1/jni/Android.mk ] || return 1
    281         ! var_list_contains LONG_TESTS "`basename $1`" || return 1
    282     }
    283 fi # !FULL_TESTS
    284 
    285 
    286 mkdir -p $TEST_DIR
    287 setup_default_log_file "$TEST_DIR/build-tests.log"
    288 
    289 if [ -n "$NDK_PACKAGE" ] ; then
    290     if [ -n "$NDK_ROOT" ] ; then
    291         dump "ERROR: You can't use --ndk and --package at the same time!"
    292         exit 1
    293     fi
    294     NDK_ROOT=/tmp/ndk-tests/install
    295     mkdir -p  "$NDK_ROOT" && rm -rf "$NDK_ROOT/*"
    296     dump "Unpacking NDK package to $NDK_ROOT"
    297     unpack_archive "$NDK_PACKAGE" "$NDK_ROOT"
    298     NDK_ROOT=`ls -d $NDK_ROOT/*`
    299 fi
    300 
    301 #
    302 # Check the NDK install path.
    303 #
    304 if [ -n "$NDK_ROOT" ] ; then
    305     if [ ! -d "$NDK_ROOT" ] ; then
    306         dump "ERROR: Your --ndk option does not point to a directory: $NDK_ROOT"
    307         dump "Please use a valid path for this option."
    308         exit 1
    309     fi
    310     if [ ! -f "$NDK_ROOT/ndk-build" -o ! -f "$NDK_ROOT/build/tools/prebuilt-common.sh" ] ; then
    311         dump "ERROR: Your --ndk option does not point to a valid NDK install: $NDK_ROOT"
    312         dump "Please use a valid NDK install path for this option."
    313         exit 3
    314     fi
    315     NDK="$NDK_ROOT"
    316 else
    317     NDK="$ROOTDIR"
    318 fi
    319 
    320 #
    321 # Create log file
    322 #
    323 
    324 BUILD_DIR=$TEST_DIR/build
    325 mkdir -p "$BUILD_DIR" && rm -rf "$BUILD_DIR/*"
    326 
    327 #
    328 # Add -link-native-binary to allow linking native binaries
    329 #
    330 if [ "$NDK_ABI_FILTER" != "${NDK_ABI_FILTER%%bc*}" ] ; then
    331   APP_LDFLAGS="$APP_LDFLAGS -Wl,-link-native-binary"
    332 fi
    333 
    334 
    335 ###
    336 ### RUN AWK TESTS
    337 ###
    338 
    339 # Run a simple awk script
    340 # $1: awk script to run
    341 # $2: input file
    342 # $3: expected output file
    343 # $4+: optional additional command-line arguments for the awk command
    344 run_awk_test ()
    345 {
    346     local SCRIPT="$1"
    347     local SCRIPT_NAME="`basename $SCRIPT`"
    348     local INPUT="$2"
    349     local INPUT_NAME="`basename $INPUT`"
    350     local EXPECTED="$3"
    351     local EXPECTED_NAME="`basename $EXPECTED`"
    352     shift; shift; shift;
    353     local OUTPUT="$BUILD_DIR/$EXPECTED_NAME"
    354     if [ "$VERBOSE2" = "yes" ]; then
    355         echo "### COMMAND: awk -f \"$SCRIPT\" $@ < \"$INPUT\" > \"$OUTPUT\""
    356     fi
    357     awk -f "$SCRIPT" $@ < "$INPUT" > "$OUTPUT"
    358     fail_panic "Can't run awk script: $SCRIPT"
    359     if [ "$VERBOSE2" = "yes" ]; then
    360         echo "OUTPUT FROM SCRIPT:"
    361         cat "$OUTPUT"
    362         echo "EXPECTED VALUES:"
    363         cat "$EXPECTED"
    364     fi
    365     cmp -s "$OUTPUT" "$EXPECTED"
    366     if [ $? = 0 ] ; then
    367         echo "Awk script: $SCRIPT_NAME: passed $INPUT_NAME"
    368         if [ "$VERBOSE2" = "yes" ]; then
    369             cat "$OUTPUT"
    370         fi
    371     else
    372         if [ "$VERBOSE" = "yes" ]; then
    373             run diff -burN "$EXPECTED" "$OUTPUT"
    374         fi
    375         echo "Awk script: $SCRIPT_NAME: $INPUT_NAME FAILED!!"
    376         rm -f "$OUTPUT"
    377         exit 1
    378     fi
    379 }
    380 
    381 run_awk_test_dir ()
    382 {
    383     local SCRIPT_NAME="`basename \"$DIR\"`"
    384     local SCRIPT="$ROOTDIR/build/awk/$SCRIPT_NAME.awk"
    385     local INPUT
    386     local OUTPUT
    387     if [ ! -f "$SCRIPT" ]; then
    388         echo "Awk script: $SCRIPT_NAME: Missing script: $SCRIPT"
    389         continue
    390     fi
    391     for INPUT in `ls "$PROGDIR"/awk/$SCRIPT_NAME/*.in`; do
    392         OUTPUT=`echo $INPUT | sed 's/\.in$/.out/g'`
    393         if [ ! -f "$OUTPUT" ]; then
    394             echo "Awk script: $SCRIPT_NAME: Missing awk output file: $OUTPUT"
    395             continue
    396         fi
    397         run_awk_test "$SCRIPT" "$INPUT" "$OUTPUT"
    398     done
    399 }
    400 
    401 if is_testable awk; then
    402     AWKDIR="$ROOTDIR/build/awk"
    403     for DIR in `ls -d "$PROGDIR"/awk/*`; do
    404         run_awk_test_dir "$DIR"
    405     done
    406 fi
    407 
    408 ###
    409 ###  REBUILD ALL SAMPLES FIRST
    410 ###
    411 
    412 NDK_BUILD_FLAGS="-B"
    413 if [ "$WINE" ]; then
    414     case "$NDK_HOST_32BIT" in
    415         1|true)
    416             WINE=wine12
    417             ;;
    418         *)
    419             WINE=wine17
    420             NDK_BUILD_FLAGS=""  # make.exe -B hangs in wine > 1.2.x
    421             if [ "$NDK_TOOLCHAIN_VERSION" != "4.4.3" ] ; then
    422                 APP_LDFLAGS="$APP_LDFLAGS -fuse-ld=mcld" # 64-bit ld.gold can't run in any wine!
    423             fi
    424             ;;
    425     esac
    426     find_program WINE_PROG $WINE
    427     fail_panic "Can't locate $WINE"
    428 fi
    429 
    430 # $1: output bitcode path
    431 gen_empty_bitcode() {
    432     TEMP_FILE=`mktemp`
    433     mv $TEMP_FILE ${TEMP_FILE}.c
    434     run $NDK/$(get_llvm_toolchain_binprefix $DEFAULT_LLVM_VERSION)/clang -shared -target le32-none-ndk -emit-llvm -o $1 ${TEMP_FILE}.c
    435     rm -f ${TEMP_FILE}.c
    436 }
    437 
    438 # $1: output archive path
    439 gen_empty_archive() {
    440     run ar crs $1
    441 }
    442 
    443 case $ABI in
    444     default)  # Let the APP_ABI in jni/Application.mk decide what to build
    445         ;;
    446     armeabi|armeabi-v7a|arm64-v8a|x86|x86_64|mips|mips64|armeabi-v7a-hard)
    447         NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI"
    448         ;;
    449     *)
    450         if [ -n "$(filter_out "$PREBUILT_ABIS" "$ABI")" ] && [ -n "$(find_ndk_unknown_archs)" ]; then
    451             ABI=$(find_ndk_unknown_archs)
    452             NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI"
    453 
    454             # Create those temporarily files to make testing happy
    455             GCC_TOOLCHAIN_VERSION=`cat $NDK/toolchains/llvm-$DEFAULT_LLVM_VERSION/setup.mk | grep '^TOOLCHAIN_VERSION' | awk '{print $3'}`
    456             run mkdir -p $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
    457             run mkdir -p $NDK/$GABIXX_SUBDIR/libs/$ABI
    458             run mkdir -p $NDK/$LIBPORTABLE_SUBDIR/libs/$ABI
    459             run gen_empty_archive $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libsupc++.a
    460             run gen_empty_archive $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libgnustl_static.a
    461             run gen_empty_bitcode $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libgnustl_shared.bc
    462             run gen_empty_archive $NDK/$GABIXX_SUBDIR/libs/$ABI/libgabi++_static.a
    463             run gen_empty_bitcode $NDK/$GABIXX_SUBDIR/libs/$ABI/libgabi++_shared.bc
    464             run cp -a $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$(get_default_abi_for_arch arm)/include $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
    465         else
    466             echo "ERROR: Unsupported abi value: $ABI"
    467             exit 1
    468         fi
    469         ;;
    470 esac
    471 
    472 # Force all tests to run at one API level
    473 if [ "$PLATFORM" != "" ]; then
    474     NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_PLATFORM=$PLATFORM"
    475 fi
    476 
    477 # Use --verbose twice to see build commands for the tests
    478 if [ "$VERBOSE2" = "yes" ] ; then
    479     NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS V=1"
    480 fi
    481 
    482 run_ndk_build ()
    483 {
    484     if [ "$WINE" ]; then
    485         if [ "$WINE" = "wine12" ]; then
    486             run $WINE cmd /c Z:$NDK/ndk-build.cmd -j$JOBS "$@" APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
    487         else
    488             # do "clean" instead of -B
    489             run $WINE cmd /c Z:$NDK/ndk-build.cmd clean
    490             # make.exe can't do parallel build in wine > 1.2.x
    491             run $WINE cmd /c Z:$NDK/ndk-build.cmd "$@" -j1 APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
    492         fi
    493     else
    494         run $NDK/ndk-build -j$JOBS "$@" APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
    495     fi
    496 }
    497 
    498 # get build var
    499 # $1: project directory
    500 # $2: var
    501 get_build_var ()
    502 {
    503     local PROJECT=$1
    504     local VAR=$2
    505 
    506     if [ -z "$GNUMAKE" ] ; then
    507         GNUMAKE=make
    508     fi
    509     $GNUMAKE --no-print-dir -f $NDK/build/core/build-local.mk -C $PROJECT DUMP_$VAR | tail -1
    510 }
    511 
    512 
    513 # check if the project is broken and shouldn't be built
    514 # $1: project directory
    515 # $2: optional error message
    516 is_broken_build ()
    517 {
    518     local PROJECT="$1"
    519     local ERRMSG="$2"
    520 
    521     if [ -z "$RUN_TESTS" ] ; then
    522         if [ -f "$PROJECT/BROKEN_BUILD" ] ; then
    523             if [ ! -s "$PROJECT/BROKEN_BUILD" ] ; then
    524                 # skip all
    525                 if [ -z "$ERRMSG" ] ; then
    526                     echo "Skipping `basename $PROJECT`: (build)"
    527                 else
    528                     echo "Skipping $ERRMSG: `basename $PROJECT`"
    529                 fi
    530                 return 0
    531             else
    532                 # only skip listed in file
    533                 TARGET_TOOLCHAIN=`get_build_var $PROJECT TARGET_TOOLCHAIN`
    534                 TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
    535                 grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$PROJECT/BROKEN_BUILD"
    536                 if [ $? = 0 ] ; then
    537                     if [ -z "$ERRMSG" ] ; then
    538                         echo "Skipping `basename $PROJECT`: (no build for $TARGET_TOOLCHAIN_VERSION)"
    539                     else
    540                         echo "Skipping $ERRMSG: `basename $PROJECT` (no build for $TARGET_TOOLCHAIN_VERSION)"
    541                     fi
    542                     return 0
    543                 fi
    544                 # skip incompatible forced platform
    545                 if [ "$PLATFORM" != "" ] ; then
    546                     grep -q -e "$PLATFORM" "$PROJECT/BROKEN_BUILD" || grep -q -e "android-forced" "$PROJECT/BROKEN_BUILD"
    547                     if [ $? = 0 ] ; then
    548                         if [ -z "$ERRMSG" ] ; then
    549                             echo "Skipping `basename $PROJECT`: (no build for $PLATFORM)"
    550                         else
    551                             echo "Skipping $ERRMSG: `basename $PROJECT` (no build for $PLATFORM)"
    552                         fi
    553                         return 0
    554                     fi
    555                 fi
    556             fi
    557         fi
    558     fi
    559     return 1
    560 }
    561 
    562 # check if $ABI is incompatible and shouldn't be built
    563 # $1: project directory
    564 is_incompatible_abi ()
    565 {
    566     local PROJECT="$1"
    567     # Basically accept all for unknown arch, even some cases may not be suitable for this way
    568     if [ "$ABI" != "default" -a "$ABI" != "$(find_ndk_unknown_archs)" ] ; then
    569         # check APP_ABI
    570         local APP_ABIS=`get_build_var $PROJECT APP_ABI`
    571         APP_ABIS=$APP_ABIS" "
    572         if [ "$APP_ABIS" != "${APP_ABIS%%all*}" ] ; then
    573         # replace the first "all" with all available ABIs
    574           ALL_ABIS=`get_build_var $PROJECT NDK_ALL_ABIS`
    575           APP_ABIS_FRONT="${APP_ABIS%%all*}"
    576           APP_ABIS_BACK="${APP_ABIS#*all}"
    577           APP_ABIS="${APP_ABIS_FRONT}${ALL_ABIS}${APP_ABIS_BACK}"
    578         fi
    579         if [ "$APP_ABIS" = "${APP_ABIS%$ABI *}" ] ; then
    580             echo "Skipping `basename $PROJECT`: incompatible ABI, needs $APP_ABIS"
    581             return 0
    582         fi
    583     fi
    584     return 1
    585 }
    586 
    587 compile_on_the_fly()
    588 {
    589     local DSTDIR="$1"
    590     local COMPILER_PKGNAME="compiler.abcc"
    591     if [ -z "`$ADB_CMD -s "$DEVICE" shell pm path $COMPILER_PKGNAME`" ]; then
    592         dump "ERROR: No abcc found for unknown arch testing"
    593         return 1
    594     fi
    595     run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
    596     run $ADB_CMD -s "$DEVICE" shell am startservice --user 0 -a ${COMPILER_PKGNAME}.BITCODE_COMPILE_TEST -n $COMPILER_PKGNAME/.AbccService -e working_dir $DSTDIR
    597 
    598     old_pid="`$ADB_CMD -s "$DEVICE" shell top -n 1 | grep $COMPILER_PKGNAME | awk '{print $1}'`"
    599     threshold=`echo $((60*10))` # Wait at most 10 minutes for large testcases
    600     sleep_seconds=0
    601     while [ 2 -eq 2 ]; do
    602       if [ $sleep_seconds -gt $threshold ]; then
    603         pid="`$ADB_CMD -s "$DEVICE" shell top -n 1 | grep $COMPILER_PKGNAME | awk '{print $1}'`"
    604         if [ "$pid" = "$old_pid" ]; then
    605           # Too much time
    606           break
    607         fi
    608         old_pid="$pid"
    609         sleep_seconds=0
    610       fi
    611       if [ -n "`$ADB_CMD -s "$DEVICE" shell ls $DSTDIR | grep compile_result`" ]; then
    612         # Compile done
    613         break
    614       fi
    615       sleep 3
    616       sleep_seconds="`echo $sleep_seconds + 3 | bc`"
    617     done
    618     ret="`$ADB_CMD -s "$DEVICE" shell cat $DSTDIR/compile_result`"
    619     ret=`echo $ret | tr -d "\r\n"`
    620     if [ $sleep_seconds -gt $threshold ] || [ "$ret" != "0" ]; then
    621       dump "ERROR: Could not compile bitcodes for $TEST_NAME on device"
    622       if [ $sleep_seconds -gt $threshold ]; then
    623         dump "- Reason: Compile time too long"
    624       elif [ -n "`$ADB_CMD -s "$DEVICE" shell ls $DSTDIR | grep compile_error`" ]; then
    625         dump "- Reason: `$ADB_CMD -s "$DEVICE" shell cat $DSTDIR/compile_error`"
    626       fi
    627       run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
    628       return 1
    629     fi
    630     run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
    631     return 0
    632 }
    633 
    634 
    635 build_project ()
    636 {
    637     local NAME=`basename $1`
    638     local CHECK_ABI=$2
    639     local DIR="$BUILD_DIR/$NAME"
    640 
    641     if is_broken_build $1; then
    642         return 0;
    643     fi
    644     if [ "$CHECK_ABI" = "yes" ] ; then
    645         if is_incompatible_abi $1 ; then
    646             return 0
    647         fi
    648     fi
    649     rm -rf "$DIR" && cp -r "$1" "$DIR"
    650     # build it
    651     (run cd "$DIR" && run_ndk_build $NDK_BUILD_FLAGS)
    652     RET=$?
    653     if [ -f "$1/BUILD_SHOULD_FAIL" ]; then
    654         if [ $RET = 0 ]; then
    655             echo "!!! FAILURE: BUILD SHOULD HAVE FAILED [$1]"
    656             if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
    657                 exit 1
    658             fi
    659         fi
    660         log "!!! SUCCESS: BUILD FAILED AS EXPECTED [$(basename $1)]"
    661         RET=0
    662     fi
    663     if [ $RET != 0 ] ; then
    664         echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
    665         if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
    666             exit 1
    667         fi
    668     fi
    669 }
    670 
    671 #
    672 # Determine list of samples directories.
    673 #
    674 if is_testable samples; then
    675     if [ -f "$NDK/RELEASE.TXT" ] ; then
    676         # This is a release package, all samples should be under $NDK/samples
    677         SAMPLES_DIRS="$NDK/samples"
    678         if [ ! -d "$SAMPLES_DIRS" ] ; then
    679             dump "ERROR: Missing samples directory: $SAMPLES_DIRS"
    680             dump "Your NDK release installation is broken!"
    681             exit 1
    682         fi
    683         log "Using release NDK samples from: $SAMPLES_DIRS"
    684     else
    685         # This is a development work directory, we will take the samples
    686         # directly from development/ndk.
    687         DEVNDK_DIR=`dirname $NDK`/development/ndk
    688         if [ ! -d "$DEVNDK_DIR" ] ; then
    689             dump "ERROR: Could not find development NDK directory: $DEVNDK_DIR"
    690             dump "Please clone platform/development.git from android.googlesource.com"
    691             exit 1
    692         fi
    693         SAMPLES_DIRS="$DEVNDK_DIR/samples"
    694         for DIR in `ls -d $DEVNDK_DIR/platforms/android-*/samples`; do
    695             SAMPLES_DIRS="$SAMPLES_DIRS $DIR"
    696         done
    697         dump "Using development NDK samples from $DEVNDK_DIR"
    698         if [ "$VERBOSE" = "yes" ] ; then
    699             echo "$SAMPLES_DIRS" | tr ' ' '\n'
    700         fi
    701     fi
    702 
    703     #
    704     # Copy the samples to a temporary build directory
    705 
    706     build_sample ()
    707     {
    708         echo "Building NDK sample: `basename $1`"
    709         build_project $1 "no"
    710     }
    711 
    712     for DIR in $SAMPLES_DIRS; do
    713         for SUBDIR in `ls -d $DIR/*`; do
    714             if is_buildable $SUBDIR; then
    715                 build_sample $SUBDIR
    716             fi
    717         done
    718     done
    719 fi
    720 
    721 ###
    722 ###  BUILD PROJECTS UNDER tests/build/
    723 ###
    724 
    725 if is_testable build; then
    726     build_build_test ()
    727     {
    728         local NAME="$(basename $1)"
    729         echo "Building NDK build test: `basename $1`"
    730         if [ -f $1/build.sh ]; then
    731             local DIR="$BUILD_DIR/$NAME"
    732             if [ -f "$1/jni/Android.mk" -a -f "$1/jni/Application.mk" ] ; then
    733                 # exclude jni/Android.mk with import-module because it needs NDK_MODULE_PATH
    734                 grep -q  "call import-module" "$1/jni/Android.mk"
    735                 if [ $? != 0 ] ; then
    736                     if (is_broken_build $1 || is_incompatible_abi $1) then
    737                         return 0;
    738                     fi
    739                 fi
    740             fi
    741             rm -rf "$DIR" && cp -r "$1" "$DIR"
    742             export NDK
    743             (cd "$DIR" && run ./build.sh -j$JOBS $NDK_BUILD_FLAGS)
    744             if [ $? != 0 ]; then
    745                 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
    746                 if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
    747                     exit 1
    748                 fi
    749             fi
    750         else
    751             build_project $1 "yes"
    752         fi
    753     }
    754 
    755     for DIR in `ls -d $ROOTDIR/tests/build/*`; do
    756         if is_buildable $DIR; then
    757             build_build_test $DIR
    758         fi
    759     done
    760 fi
    761 
    762 ###
    763 ###  BUILD PROJECTS UNDER tests/device/
    764 ###
    765 
    766 CPU_ABIS=
    767 if is_testable device; then
    768     build_device_test ()
    769     {
    770         if is_broken_build $1 "broken device test build"; then
    771             return 0;
    772         fi
    773         echo "Building NDK device test: `basename $1`"
    774         build_project $1 "yes"
    775     }
    776 
    777     # $1: DEVICE
    778     # $2: DEVICE CPU ABI
    779     # $3: test
    780     # $4: tmp dir
    781     run_device_test ()
    782     {
    783         local DEVICE=$1
    784         local CPU_ABI=$2
    785         local TEST=$3
    786         local TEST_NAME="$(basename $TEST)"
    787         local SRCDIR
    788         local DSTDIR="$4/$TARGET_TEST_SUBDIR"
    789         local SRCFILE
    790         local DSTFILE
    791         local PROGRAM
    792         # Do not run the test if BROKEN_RUN is defined
    793         if [ -z "$RUN_TESTS" ]; then
    794             if is_broken_build $TEST "NDK device test not built"; then
    795                 return 0
    796             fi
    797             if [ -f "$TEST/BROKEN_RUN" ] ; then
    798                 if [ ! -s "$TEST/BROKEN_RUN" ] ; then
    799                     # skip all
    800                     dump "Skipping NDK device test run: $TEST_NAME"
    801                     return 0
    802                 else
    803                     # skip all tests built by toolchain
    804                     TARGET_TOOLCHAIN=`get_build_var $TEST TARGET_TOOLCHAIN`
    805                     TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
    806                     grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$TEST/BROKEN_RUN"
    807                     if [ $? = 0 ] ; then
    808                         dump "Skipping NDK device test run: $TEST_NAME (no run for binary built by $TARGET_TOOLCHAIN_VERSION)"
    809                         return 0
    810                     fi
    811                     # skip tests listed in file
    812                     SKIPPED_EXECUTABLES=`cat $TEST/BROKEN_RUN | tr '\n' ' '`
    813                     dump "Skipping NDK device test run: $TEST_NAME ($SKIPPED_EXECUTABLES)"
    814                 fi
    815             fi
    816         fi
    817         if [ "$ABI" = "$(find_ndk_unknown_archs)" ] && [ -d "$BUILD_DIR/`basename $TEST`/libs" ]; then
    818             cd $BUILD_DIR/`basename $TEST`/libs && cp -a $ABI $CPU_ABI
    819         fi
    820         SRCDIR="$BUILD_DIR/`basename $TEST`/libs/$CPU_ABI"
    821         if [ ! -d "$SRCDIR" ] || [ -z "`ls $SRCDIR`" ]; then
    822             dump "Skipping NDK device test run (no $CPU_ABI binaries): $TEST_NAME"
    823             return 0
    824         fi
    825         # First, copy all files to the device, except for gdbserver, gdb.setup, and
    826         # those declared in $TEST/BROKEN_RUN
    827         adb_shell_mkdir "$DEVICE" $DSTDIR
    828 
    829         if [ "$ABI" = "$(find_ndk_unknown_archs)" ]; then # on-the-fly on-device compilation
    830             run $ADB_CMD -s "$DEVICE" shell rm -rf $DSTDIR/abcc_tmp
    831             adb_shell_mkdir "$DEVICE" $DSTDIR/abcc_tmp
    832             run $ADB_CMD -s "$DEVICE" shell chmod 0777 $DSTDIR/abcc_tmp
    833             for SRCFILE in `ls $SRCDIR`; do
    834                 run $ADB_CMD -s "$DEVICE" push "$SRCDIR/$SRCFILE" $DSTDIR/abcc_tmp
    835                 run $ADB_CMD -s "$DEVICE" shell chmod 0644 $DSTDIR/abcc_tmp/$SRCFILE
    836             done
    837             compile_on_the_fly $DSTDIR/abcc_tmp
    838             if [ $? -ne 0 ]; then
    839                 test "$CONTINUE_ON_BUILD_FAIL" != "yes" && exit 1
    840                 return 1
    841             fi
    842             run rm -f $SRCDIR/*
    843             run $ADB_CMD -s "$DEVICE" pull $DSTDIR/abcc_tmp $SRCDIR
    844             run rm -f $SRCDIR/compile_result
    845             run rm -f $SRCDIR/compile_error
    846             run rm -f $SRCDIR/*$(get_lib_suffix_for_abi $ABI)
    847             run $ADB_CMD -s "$DEVICE" shell rm -rf $DSTDIR/abcc_tmp
    848         fi
    849 
    850         for SRCFILE in `ls $SRCDIR`; do
    851             DSTFILE=`basename $SRCFILE`
    852             echo "$DSTFILE" | grep -q -e '\.so$'
    853             if [ $? != 0 ] ; then
    854                 continue
    855             fi
    856             SRCPATH="$SRCDIR/$SRCFILE"
    857             if [ $HOST_OS = cygwin ]; then
    858                 SRCPATH=`cygpath -m $SRCPATH`
    859             fi
    860             DSTPATH="$DSTDIR/$DSTFILE"
    861             run $ADB_CMD -s "$DEVICE" push "$SRCPATH" "$DSTPATH" &&
    862             run $ADB_CMD -s "$DEVICE" shell chmod 0755 $DSTPATH
    863             if [ $? != 0 ] ; then
    864                 dump "ERROR: Could not install $SRCPATH to device $DEVICE!"
    865                 exit 1
    866             fi
    867         done
    868 
    869         for SRCFILE in `ls $SRCDIR`; do
    870             DSTFILE=`basename $SRCFILE`
    871             if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then
    872                 continue
    873             fi
    874             echo "$DSTFILE" | grep -q -e '\.so$'
    875             if [ $? = 0 ] ; then
    876               continue
    877             fi
    878             if [ -z "$RUN_TESTS" -o "$RUN_TESTS_FILTERED" = "yes" ]; then
    879                 if [ -f "$TEST/BROKEN_RUN" ]; then
    880                     grep -q -w -e "$DSTFILE" "$TEST/BROKEN_RUN"
    881                     if [ $? = 0 ] ; then
    882                         continue
    883                     fi
    884                 fi
    885             fi
    886             SRCPATH="$SRCDIR/$SRCFILE"
    887             if [ $HOST_OS = cygwin ]; then
    888                 SRCPATH=`cygpath -m $SRCPATH`
    889             fi
    890             DSTPATH="$DSTDIR/$DSTFILE"
    891             run $ADB_CMD -s "$DEVICE" push "$SRCPATH" "$DSTPATH" &&
    892             run $ADB_CMD -s "$DEVICE" shell chmod 0755 $DSTPATH
    893             DATAPATHS=
    894             if [ -f "$TEST/DATA" ]; then
    895                 if grep -q -e "$DSTFILE" "$TEST/DATA"; then
    896                     DATAPATHS=`grep -e "$DSTFILE" "$TEST/DATA" | awk '{print $2}'`
    897                     DATAPATHS=$NDK/$DATAPATHS
    898                     for DATA in $(ls $DATAPATHS); do
    899                         run $ADB_CMD -s "$DEVICE" push "$DATA" "$DSTDIR"
    900                     done
    901                 fi
    902             fi
    903             if [ $? != 0 ] ; then
    904                 dump "ERROR: Could not install $SRCPATH to device $DEVICE!"
    905                 exit 1
    906             fi
    907             PROGRAM="`basename $DSTPATH`"
    908             dump "Running device test [$CPU_ABI]: $TEST_NAME (`basename $PROGRAM`)"
    909             adb_var_shell_cmd "$DEVICE" "" "cd $DSTDIR && LD_LIBRARY_PATH=$DSTDIR ./$PROGRAM"
    910             if [ $? != 0 ] ; then
    911                 dump "   ---> TEST FAILED!!"
    912             fi
    913             adb_var_shell_cmd "$DEVICE" "" "rm -f $DSTPATH"
    914             for DATA in $(ls $DATAPATHS); do
    915                 adb_var_shell_cmd "$DEVICE" "" "rm -f $DSTDIR/`basename $DATA`"
    916             done
    917         done
    918         # Cleanup
    919         adb_var_shell_cmd "$DEVICE" "" rm -r $DSTDIR
    920     }
    921 
    922     for DIR in `ls -d $ROOTDIR/tests/device/*`; do
    923         if is_buildable $DIR; then
    924             build_device_test $DIR
    925         fi
    926     done
    927 
    928     # Do we have adb and any device connected here?
    929     # If not, we can't run our tests.
    930     #
    931     SKIP_TESTS=no
    932     if [ -z "$ADB_CMD" ] ; then
    933         dump "WARNING: No 'adb' in your path!"
    934         SKIP_TESTS=yes
    935     else
    936         # Get list of online devices, turn ' ' in device into '#'
    937         ADB_DEVICES=`$ADB_CMD devices | grep -v offline | awk 'NR>1 {gsub(/[ \t]+device$/,""); print;}' | sed '/^$/d' | sort | tr ' ' '#'`
    938         ADB_DEVICES=$(echo $ADB_DEVICES | tr '\n' ' ')
    939         log2 "ADB online devices (sorted): $ADB_DEVICES"
    940         ADB_DEVCOUNT=`echo "$ADB_DEVICES" | wc -w`
    941         if [ "$ADB_DEVCOUNT" = "0" ]; then
    942             dump "WARNING: No device connected to adb!"
    943             SKIP_TESTS=yes
    944         else
    945             ADB_DEVICES="$ADB_DEVICES "
    946             if [ -n "$ANDROID_SERIAL" ] ; then
    947                 # Expect ANDROID_SERIAL is comma-delimited of one or more devices
    948                 ANDROID_SERIAL=$(echo "$ANDROID_SERIAL" | tr ' ' '#')  # turn ' ' into '#'
    949                 ANDROID_SERIAL=$(commas_to_spaces $ANDROID_SERIAL)
    950                 for SERIAL in $ANDROID_SERIAL; do
    951                     if [ "$ADB_DEVICES" = "${ADB_DEVICES%$SERIAL *}" ] ; then
    952                         dump "WARNING: Device $SERIAL cannot be found or offline!"
    953                         SKIP_TESTS=yes
    954                     fi
    955                 done
    956                 if [ "$SKIP_TESTS" != "yes" ] ; then
    957                     ADB_DEVICES="$ANDROID_SERIAL"
    958                 fi
    959             fi
    960         fi
    961     fi
    962     if [ "$SKIP_TESTS" = "yes" ] ; then
    963         dump "SKIPPING RUNNING TESTS ON DEVICE!"
    964     else
    965         AT_LEAST_CPU_ABI_MATCH=
    966         for DEVICE in $ADB_DEVICES; do
    967             # undo earlier ' '-to-'#' translation
    968             DEVICE=$(echo "$DEVICE" | tr '#' ' ')
    969             # get device CPU_ABI and CPU_ABI2, each may contain list of abi, comma-delimited.
    970             adb_var_shell_cmd "$DEVICE" CPU_ABI1 getprop ro.product.cpu.abi
    971             adb_var_shell_cmd "$DEVICE" CPU_ABI2 getprop ro.product.cpu.abi2
    972             CPU_ABIS="$CPU_ABI1,$CPU_ABI2"
    973             CPU_ABIS=$(commas_to_spaces $CPU_ABIS)
    974             if [ "$_NDK_TESTING_ALL_" = "yes" ]; then
    975                 if [ "$CPU_ABI1" = "armeabi-v7a" -o "$CPU_ABI2" = "armeabi-v7a" ]; then
    976                     CPU_ABIS="$CPU_ABIS armeabi-v7a-hard"
    977                 fi
    978             fi
    979             if [ "$CPU_ABIS" = " " ]; then
    980               # Very old cupcake-based Android devices don't have these properties
    981               # defined. Fortunately, they are all armeabi-based.
    982               CPU_ABIS=armeabi
    983             fi
    984             log "CPU_ABIS=$CPU_ABIS"
    985             for CPU_ABI in $CPU_ABIS; do
    986                 if [ "$ABI" = "default" -o "$ABI" = "$CPU_ABI" -o "$ABI" = "$(find_ndk_unknown_archs)" ] ; then
    987                     AT_LEAST_CPU_ABI_MATCH="yes"
    988                     for DIR in `ls -d $ROOTDIR/tests/device/*`; do
    989                         if is_buildable $DIR; then
    990                             log "Running device test on $DEVICE [$CPU_ABI]: $DIR"
    991                             run_device_test "$DEVICE" "$CPU_ABI" "$DIR" /data/local/tmp
    992                         fi
    993                     done
    994                 fi
    995             done
    996         done
    997         if [ "$AT_LEAST_CPU_ABI_MATCH" != "yes" ] ; then
    998             dump "WARNING: No device matches ABI $ABI! SKIPPING RUNNING TESTS ON DEVICE!"
    999         fi
   1000     fi
   1001 fi
   1002 
   1003 dump "Cleaning up..."
   1004 if [ "$ABI" = "$(find_ndk_unknown_archs)" ]; then
   1005   # Cleanup some intermediate files for testing
   1006   run rm -rf $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
   1007   run rm -rf $NDK/$GABIXX_SUBDIR/libs/$ABI
   1008   run rm -rf $NDK/$LIBPORTABLE_SUBDIR/libs/$ABI
   1009 fi
   1010 rm -rf $BUILD_DIR
   1011 dump "Done."
   1012