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 . $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