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=*)  # 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
    118 done
    119 
    120 if [ "$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
    148 fi
    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 #
    156 adb_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.
    181 adb_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
    212 var_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 #
    220 is_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
    226 if [ -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     }
    231 elif [ "$FULL_TESTS" = "yes" ] ; then
    232     is_buildable () {
    233         [ -f $1/build.sh -o -f $1/jni/Android.mk ]
    234     }
    235 else # !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     }
    240 fi # !FULL_TESTS
    241 
    242 
    243 TEST_DIR="/tmp/ndk-$USER/tests"
    244 mkdir -p $TEST_DIR
    245 setup_default_log_file "$TEST_DIR/build-tests.log"
    246 
    247 if [ -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/*`
    257 fi
    258 
    259 #
    260 # Check the NDK install path.
    261 #
    262 if [ -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"
    274 else
    275     NDK="$ROOTDIR"
    276 fi
    277 
    278 #
    279 # Create log file
    280 #
    281 
    282 BUILD_DIR=$TEST_DIR/build
    283 mkdir -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
    294 run_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 
    331 run_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 
    351 if 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
    356 fi
    357 
    358 ###
    359 ###  REBUILD ALL SAMPLES FIRST
    360 ###
    361 
    362 # Special case, if ABI is 'armeabi' or 'armeabi-v7a'
    363 # we want to build both armeabi and armeabi-v7a machine code
    364 # even if we will only run the armeabi test programs on the
    365 # device. This is done by not forcing the definition of APP_ABI
    366 NDK_BUILD_FLAGS="-B"
    367 case $ABI in
    368     armeabi|armeabi-v7a)
    369         ;;
    370     x86|mips)
    371         NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI"
    372         ;;
    373     *)
    374         echo "ERROR: Unsupported abi value: $ABI"
    375         exit 1
    376         ;;
    377 esac
    378 
    379 # Force all tests to run at one API level
    380 if [ "$PLATFORM" != "" ]; then
    381     NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_PLATFORM=$PLATFORM"
    382 fi
    383 
    384 # Use --verbose twice to see build commands for the tests
    385 if [ "$VERBOSE2" = "yes" ] ; then
    386     NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS V=1"
    387 fi
    388 
    389 run_ndk_build ()
    390 {
    391     if [ "$WINE" ]; then
    392         run wine cmd /c Z:$NDK/ndk-build.cmd -j$JOBS "$@"
    393     else
    394         run $NDK/ndk-build -j$JOBS "$@"
    395     fi
    396 }
    397 
    398 build_project ()
    399 {
    400     local NAME=`basename $1`
    401     local DIR="$BUILD_DIR/$NAME"
    402     if [ -f "$1/BROKEN_BUILD" -a -z "$RUN_TESTS" ] ; then
    403         echo "Skipping $1: (build)"
    404         return 0
    405     fi
    406     rm -rf "$DIR" && cp -r "$1" "$DIR"
    407     (cd "$DIR" && run_ndk_build $NDK_BUILD_FLAGS)
    408     RET=$?
    409     if [ -f "$1/BUILD_SHOULD_FAIL" ]; then
    410         if [ $RET = 0 ]; then
    411             echo "!!! FAILURE: BUILD SHOULD HAVE FAILED [$1]"
    412             exit 1
    413         fi
    414         log "!!! SUCCESS: BUILD FAILED AS EXPECTED [$(basename $1)]"
    415         RET=0
    416     fi
    417     if [ $RET != 0 ] ; then
    418         echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
    419         exit 1
    420     fi
    421 }
    422 
    423 #
    424 # Determine list of samples directories.
    425 #
    426 if is_testable samples; then
    427     if [ -f "$NDK/RELEASE.TXT" ] ; then
    428         # This is a release package, all samples should be under $NDK/samples
    429         SAMPLES_DIRS="$NDK/samples"
    430         if [ ! -d "$SAMPLES_DIRS" ] ; then
    431             dump "ERROR: Missing samples directory: $SAMPLES_DIRS"
    432             dump "Your NDK release installation is broken!"
    433             exit 1
    434         fi
    435         log "Using release NDK samples from: $SAMPLES_DIRS"
    436     else
    437         # This is a development work directory, we will take the samples
    438         # directly from development/ndk.
    439         DEVNDK_DIR=`dirname $NDK`/development/ndk
    440         if [ ! -d "$DEVNDK_DIR" ] ; then
    441             dump "ERROR: Could not find development NDK directory: $DEVNDK_DIR"
    442             dump "Please clone platform/development.git from android.googlesource.com"
    443             exit 1
    444         fi
    445         SAMPLES_DIRS="$DEVNDK_DIR/samples"
    446         for DIR in `ls -d $DEVNDK_DIR/platforms/android-*/samples`; do
    447             SAMPLES_DIRS="$SAMPLES_DIRS $DIR"
    448         done
    449         dump "Using development NDK samples from $DEVNDK_DIR"
    450         if [ "$VERBOSE" = "yes" ] ; then
    451             echo "$SAMPLES_DIRS" | tr ' ' '\n'
    452         fi
    453     fi
    454 
    455     #
    456     # Copy the samples to a temporary build directory
    457 
    458     build_sample ()
    459     {
    460         echo "Building NDK sample: `basename $1`"
    461         build_project $1
    462     }
    463 
    464     for DIR in $SAMPLES_DIRS; do
    465         for SUBDIR in `ls -d $DIR/*`; do
    466             if is_buildable $SUBDIR; then
    467                 build_sample $SUBDIR
    468             fi
    469         done
    470     done
    471 fi
    472 
    473 ###
    474 ###  BUILD PROJECTS UNDER tests/build/
    475 ###
    476 
    477 if is_testable build; then
    478     build_build_test ()
    479     {
    480         echo "Building NDK build test: `basename $1`"
    481         if [ -f $1/build.sh ]; then
    482             export NDK
    483             run $1/build.sh $NDK_BUILD_FLAGS
    484             if [ $? != 0 ]; then
    485                 echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
    486                 exit 1
    487             fi
    488         else
    489             build_project $1
    490         fi
    491     }
    492 
    493     for DIR in `ls -d $ROOTDIR/tests/build/*`; do
    494         if is_buildable $DIR; then
    495             build_build_test $DIR
    496         fi
    497     done
    498 fi
    499 
    500 ###
    501 ###  BUILD PROJECTS UNDER tests/device/
    502 ###  XXX: TODO: RUN THEM ON A DEVICE/EMULATOR WITH ADB
    503 ###
    504 
    505 if is_testable device; then
    506     build_device_test ()
    507     {
    508         # Do not build test if BROKEN_BUILD is defined, except if we
    509         # Have listed the test explicitely.
    510         if [ -f "$1/BROKEN_BUILD" -a -z "$RUN_TESTS" ] ; then
    511             echo "Skipping broken device test build: `basename $1`"
    512             return 0
    513         fi
    514         echo "Building NDK device test: `basename $1` in $1"
    515         build_project $1
    516     }
    517 
    518     run_device_test ()
    519     {
    520         local SRCDIR="$BUILD_DIR/`basename $1`/libs/$ABI"
    521         local DSTDIR="$2/ndk-tests"
    522         local SRCFILE
    523         local DSTFILE
    524         local PROGRAMS=
    525         local PROGRAM
    526         # Do not run the test if BROKEN_RUN is defined
    527         if [ -f "$1/BROKEN_RUN" -o -f "$1/BROKEN_BUILD" ] ; then
    528 	    if [ -z "$RUN_TESTS" ]; then
    529 		dump "Skipping NDK device test run: `basename $1`"
    530 		return 0
    531 	    fi
    532         fi
    533         if [ ! -d "$SRCDIR" ]; then
    534             dump "Skipping NDK device test run (no $ABI binaries): `basename $1`"
    535             return 0
    536         fi
    537         # First, copy all files to the device, except for gdbserver
    538         # or gdb.setup.
    539         adb_cmd_mkdir $DSTDIR
    540         for SRCFILE in `ls $SRCDIR`; do
    541             DSTFILE=`basename $SRCFILE`
    542             if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then
    543                 continue
    544             fi
    545             DSTFILE="$DSTDIR/$DSTFILE"
    546             run $ADB_CMD push "$SRCDIR/$SRCFILE" "$DSTFILE" &&
    547             run $ADB_CMD shell chmod 0755 $DSTFILE
    548             if [ $? != 0 ] ; then
    549                 dump "ERROR: Could not install $SRCFILE to device!"
    550                 exit 1
    551             fi
    552             # If its name doesn't end with .so, add it to PROGRAMS
    553             echo "$DSTFILE" | grep -q -e '\.so$'
    554             if [ $? != 0 ] ; then
    555                 PROGRAMS="$PROGRAMS $DSTFILE"
    556             fi
    557         done
    558         for PROGRAM in $PROGRAMS; do
    559             dump "Running device test: `basename $PROGRAM`"
    560             adb_cmd LD_LIBRARY_PATH="$DSTDIR" $PROGRAM
    561             if [ $? != 0 ] ; then
    562                 dump "   ---> TEST FAILED!!"
    563             fi
    564         done
    565         # Cleanup
    566         adb_cmd rm -r $DSTDIR
    567     }
    568 
    569     for DIR in `ls -d $ROOTDIR/tests/device/*`; do
    570         if is_buildable $DIR; then
    571             build_device_test $DIR
    572         fi
    573     done
    574 
    575     # Do we have adb and any device connected here?
    576     # If not, we can't run our tests.
    577     #
    578     SKIP_TESTS=no
    579     if [ -z "$ADB_CMD" ] ; then
    580         dump "WARNING: No 'adb' in your path!"
    581         SKIP_TESTS=yes
    582     else
    583         ADB_DEVICES=`$ADB_CMD devices`
    584         log2 "ADB devices: $ADB_DEVICES"
    585         ADB_DEVCOUNT=`echo "$ADB_DEVICES" | wc -l`
    586         ADB_DEVCOUNT=`expr $ADB_DEVCOUNT - 1`
    587         log2 "ADB Device count: $ADB_DEVCOUNT"
    588         if [ "$ADB_DEVCOUNT" = "0" ]; then
    589             dump "WARNING: No device connected to adb!"
    590             SKIP_TESTS=yes
    591         elif [ "$ADB_DEVCOUNT" != 1 -a -z "$ANDROID_SERIAL" ] ; then
    592             dump "WARNING: More than one device connected to adb. Please define ANDROID_SERIAL!"
    593             SKIP_TESTS=yes
    594         fi
    595         echo "$ADB_DEVICES" | grep -q -e "offline"
    596         if [ $? = 0 ] ; then
    597             dump "WARNING: Device is offline, can't run device tests!"
    598             SKIP_TESTS=yes
    599         fi
    600     fi
    601 
    602     if [ "$SKIP_TESTS" = "yes" ] ; then
    603         dump "SKIPPING RUNNING TESTS ON DEVICE!"
    604     else
    605         for DIR in `ls -d $ROOTDIR/tests/device/*`; do
    606             log "Running device test: $DIR"
    607             if is_buildable $DIR; then
    608                 run_device_test $DIR /data/local/tmp
    609             fi
    610         done
    611     fi
    612 fi
    613 
    614 dump "Cleaning up..."
    615 rm -rf $BUILD_DIR
    616 dump "Done."
    617