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