• 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. $NDK_BUILDTOOLS_PATH/ndk-common.sh
33. $NDK_BUILDTOOLS_PATH/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 test-googletest-full"
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/tools/prebuilt-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=wine17
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="$APP_LDFLAGS -fuse-ld=mcld" # 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    if [ "$WINE" ]; then
421        if [ "$WINE" = "wine12" ]; then
422            run $WINE cmd /c Z:$NDK/ndk-build.cmd -j$JOBS "$@" APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
423        else
424            # do "clean" instead of -B
425            run $WINE cmd /c Z:$NDK/ndk-build.cmd clean
426            # make.exe can't do parallel build in wine > 1.2.x
427            run $WINE cmd /c Z:$NDK/ndk-build.cmd "$@" -j1 APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
428        fi
429    else
430        run $NDK/ndk-build -j$JOBS "$@" APP_LDFLAGS="$APP_LDFLAGS" APP_CFLAGS="$APP_CFLAGS"
431    fi
432}
433
434# get build var
435# $1: project directory
436# $2: var
437get_build_var ()
438{
439    local PROJECT=$1
440    local VAR=$2
441
442    if [ -z "$GNUMAKE" ] ; then
443        GNUMAKE=make
444    fi
445    $GNUMAKE --no-print-dir -f $NDK/build/core/build-local.mk -C $PROJECT DUMP_$VAR | tail -1
446}
447
448
449# check if the project is broken and shouldn't be built
450# $1: project directory
451# $2: optional error message
452is_broken_build ()
453{
454    local PROJECT="$1"
455    local ERRMSG="$2"
456
457    if [ -z "$RUN_TESTS" ] ; then
458        if [ -f "$PROJECT/BROKEN_BUILD" ] ; then
459            if [ ! -s "$PROJECT/BROKEN_BUILD" ] ; then
460                # skip all
461                if [ -z "$ERRMSG" ] ; then
462                    echo "Skipping `basename $PROJECT`: (build)"
463                else
464                    echo "Skipping $ERRMSG: `basename $PROJECT`"
465                fi
466                return 0
467            else
468                # only skip listed in file
469                TARGET_TOOLCHAIN=`get_build_var $PROJECT TARGET_TOOLCHAIN`
470                TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
471                grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$PROJECT/BROKEN_BUILD"
472                if [ $? = 0 ] ; then
473                    if [ -z "$ERRMSG" ] ; then
474                        echo "Skipping `basename $PROJECT`: (no build for $TARGET_TOOLCHAIN_VERSION)"
475                    else
476                        echo "Skipping $ERRMSG: `basename $PROJECT` (no build for $TARGET_TOOLCHAIN_VERSION)"
477                    fi
478                    return 0
479                fi
480                # skip incompatible forced platform
481                if [ "$PLATFORM" != "" ] ; then
482                    grep -q -e "$PLATFORM" "$PROJECT/BROKEN_BUILD" || grep -q -e "android-forced" "$PROJECT/BROKEN_BUILD"
483                    if [ $? = 0 ] ; then
484                        if [ -z "$ERRMSG" ] ; then
485                            echo "Skipping `basename $PROJECT`: (no build for $PLATFORM)"
486                        else
487                            echo "Skipping $ERRMSG: `basename $PROJECT` (no build for $PLATFORM)"
488                        fi
489                        return 0
490                    fi
491                fi
492            fi
493        fi
494    fi
495    return 1
496}
497
498# check if $ABI is incompatible and shouldn't be built
499# $1: project directory
500is_incompatible_abi ()
501{
502    local PROJECT="$1"
503
504    if [ "$ABI" != "default" ] ; then
505        # check APP_ABI
506        local APP_ABIS=`get_build_var $PROJECT APP_ABI`
507        APP_ABIS=$APP_ABIS" "
508        if [ "$APP_ABIS" != "${APP_ABIS%%all*}" ] ; then
509        # replace the first "all" with all available ABIs
510          ALL_ABIS=`get_build_var $PROJECT NDK_ALL_ABIS`
511          APP_ABIS_FRONT="${APP_ABIS%%all*}"
512          APP_ABIS_BACK="${APP_ABIS#*all}"
513          APP_ABIS="${APP_ABIS_FRONT}${ALL_ABIS}${APP_ABIS_BACK}"
514        fi
515        if [ "$APP_ABIS" = "${APP_ABIS%$ABI *}" ] ; then
516            echo "Skipping `basename $PROJECT`: incompatible ABI, needs $APP_ABIS"
517            return 0
518        fi
519    fi
520    return 1
521}
522
523build_project ()
524{
525    local NAME=`basename $1`
526    local CHECK_ABI=$2
527    local DIR="$BUILD_DIR/$NAME"
528
529    if is_broken_build $1; then
530        return 0;
531    fi
532    if [ "$CHECK_ABI" = "yes" ] ; then
533        if is_incompatible_abi $1 ; then
534            return 0
535        fi
536    fi
537    rm -rf "$DIR" && cp -r "$1" "$DIR"
538    # build it
539    (run cd "$DIR" && run_ndk_build $NDK_BUILD_FLAGS)
540    RET=$?
541    if [ -f "$1/BUILD_SHOULD_FAIL" ]; then
542        if [ $RET = 0 ]; then
543            echo "!!! FAILURE: BUILD SHOULD HAVE FAILED [$1]"
544            if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
545                exit 1
546            fi
547        fi
548        log "!!! SUCCESS: BUILD FAILED AS EXPECTED [$(basename $1)]"
549        RET=0
550    fi
551    if [ $RET != 0 ] ; then
552        echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
553        if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
554            exit 1
555        fi
556    fi
557}
558
559#
560# Determine list of samples directories.
561#
562if is_testable samples; then
563    if [ -f "$NDK/RELEASE.TXT" ] ; then
564        # This is a release package, all samples should be under $NDK/samples
565        SAMPLES_DIRS="$NDK/samples"
566        if [ ! -d "$SAMPLES_DIRS" ] ; then
567            dump "ERROR: Missing samples directory: $SAMPLES_DIRS"
568            dump "Your NDK release installation is broken!"
569            exit 1
570        fi
571        log "Using release NDK samples from: $SAMPLES_DIRS"
572    else
573        # This is a development work directory, we will take the samples
574        # directly from development/ndk.
575        DEVNDK_DIR=`dirname $NDK`/development/ndk
576        if [ ! -d "$DEVNDK_DIR" ] ; then
577            dump "ERROR: Could not find development NDK directory: $DEVNDK_DIR"
578            dump "Please clone platform/development.git from android.googlesource.com"
579            exit 1
580        fi
581        SAMPLES_DIRS="$DEVNDK_DIR/samples"
582        for DIR in `ls -d $DEVNDK_DIR/platforms/android-*/samples`; do
583            SAMPLES_DIRS="$SAMPLES_DIRS $DIR"
584        done
585        dump "Using development NDK samples from $DEVNDK_DIR"
586        if [ "$VERBOSE" = "yes" ] ; then
587            echo "$SAMPLES_DIRS" | tr ' ' '\n'
588        fi
589    fi
590
591    #
592    # Copy the samples to a temporary build directory
593
594    build_sample ()
595    {
596        echo "Building NDK sample: `basename $1`"
597        build_project $1 "no"
598    }
599
600    for DIR in $SAMPLES_DIRS; do
601        for SUBDIR in `ls -d $DIR/*`; do
602            if is_buildable $SUBDIR; then
603                build_sample $SUBDIR
604            fi
605        done
606    done
607fi
608
609###
610###  BUILD PROJECTS UNDER tests/build/
611###
612
613if is_testable build; then
614    build_build_test ()
615    {
616        local NAME="$(basename $1)"
617        echo "Building NDK build test: `basename $1`"
618        if [ -f $1/build.sh ]; then
619            local DIR="$BUILD_DIR/$NAME"
620            if [ -f "$1/jni/Android.mk" -a -f "$1/jni/Application.mk" ] ; then
621                # exclude jni/Android.mk with import-module because it needs NDK_MODULE_PATH
622                grep -q  "call import-module" "$1/jni/Android.mk"
623                if [ $? != 0 ] ; then
624                    if (is_broken_build $1 || is_incompatible_abi $1) then
625                        return 0;
626                    fi
627                fi
628            fi
629            rm -rf "$DIR" && cp -r "$1" "$DIR"
630            export NDK
631            (cd "$DIR" && run ./build.sh -j$JOBS $NDK_BUILD_FLAGS)
632            if [ $? != 0 ]; then
633                echo "!!! BUILD FAILURE [$1]!!! See $NDK_LOGFILE for details or use --verbose option!"
634                if [ "$CONTINUE_ON_BUILD_FAIL" != yes ] ; then
635                    exit 1
636                fi
637            fi
638        else
639            build_project $1 "yes"
640        fi
641    }
642
643    for DIR in `ls -d $ROOTDIR/tests/build/*`; do
644        if is_buildable $DIR; then
645            build_build_test $DIR
646        fi
647    done
648fi
649
650###
651###  BUILD PROJECTS UNDER tests/device/
652###
653
654CPU_ABIS=
655if is_testable device; then
656    build_device_test ()
657    {
658        if is_broken_build $1 "broken device test build"; then
659            return 0;
660        fi
661        echo "Building NDK device test: `basename $1`"
662        build_project $1 "yes"
663    }
664
665    # $1: DEVICE
666    # $2: DEVICE CPU ABI
667    # $3: test
668    # $4: tmp dir
669    run_device_test ()
670    {
671        local DEVICE=$1
672        local CPU_ABI=$2
673        local TEST=$3
674        local TEST_NAME="$(basename $TEST)"
675        local SRCDIR
676        local DSTDIR="$4/ndk-tests"
677        local SRCFILE
678        local DSTFILE
679        local PROGRAM
680        # Do not run the test if BROKEN_RUN is defined
681        if [ -z "$RUN_TESTS" ]; then
682            if is_broken_build $TEST "NDK device test not built"; then
683                return 0
684            fi
685            if [ -f "$TEST/BROKEN_RUN" ] ; then
686                if [ ! -s "$TEST/BROKEN_RUN" ] ; then
687                    # skip all
688                    dump "Skipping NDK device test run: $TEST_NAME"
689                    return 0
690                else
691                    # skip all tests built by toolchain
692                    TARGET_TOOLCHAIN=`get_build_var $TEST TARGET_TOOLCHAIN`
693                    TARGET_TOOLCHAIN_VERSION=`echo $TARGET_TOOLCHAIN | tr '-' '\n' | tail -1`
694                    grep -q -e "$TARGET_TOOLCHAIN_VERSION" "$TEST/BROKEN_RUN"
695                    if [ $? = 0 ] ; then
696                        dump "Skipping NDK device test run: $TEST_NAME (no run for binary built by $TARGET_TOOLCHAIN_VERSION)"
697                        return 0
698                    fi
699                    # skip tests listed in file
700                    SKIPPED_EXECUTABLES=`cat $TEST/BROKEN_RUN | tr '\n' ' '`
701                    dump "Skipping NDK device test run: $TEST_NAME ($SKIPPED_EXECUTABLES)"
702                fi
703            fi
704        fi
705        SRCDIR="$BUILD_DIR/`basename $TEST`/libs/$CPU_ABI"
706        if [ ! -d "$SRCDIR" ]; then
707            dump "Skipping NDK device test run (no $CPU_ABI binaries): $TEST_NAME"
708            return 0
709        fi
710        # First, copy all files to the device, except for gdbserver, gdb.setup, and
711        # those declared in $TEST/BROKEN_RUN
712        adb_shell_mkdir "$DEVICE" $DSTDIR
713
714        # Prepare gabi++ runtime
715        if [ ! -z "$NDK_ABI_FILTER" ]; then
716            SRCFILE="$NDK/sources/cxx-stl/gabi++/libs/$CPU_ABI/libgabi++_shared.so"
717            run $ADB_CMD -s "$DEVICE" push "$SRCFILE" "$DSTDIR" &&
718            run $ADB_CMD -s "$DEVICE" shell chmod 0755 "$DSTDIR/libgabi++_shared.so"
719            if [ $? != 0 ] ; then
720                dump "ERROR: Could not install $SRCFILE to device $DEVICE!"
721                exit 1
722            fi
723        fi
724
725        for SRCFILE in `ls $SRCDIR`; do
726            DSTFILE=`basename $SRCFILE`
727            echo "$DSTFILE" | grep -q -e '\.so$'
728            if [ $? != 0 ] ; then
729                continue
730            fi
731            SRCFILE="$SRCDIR/$SRCFILE"
732            if [ $HOST_OS = cygwin ]; then
733                SRCFILE=`cygpath -m $SRCFILE`
734            fi
735            DSTFILE="$DSTDIR/$DSTFILE"
736            run $ADB_CMD -s "$DEVICE" push "$SRCFILE" "$DSTFILE" &&
737            run $ADB_CMD -s "$DEVICE" shell chmod 0755 $DSTFILE
738            if [ $? != 0 ] ; then
739                dump "ERROR: Could not install $SRCFILE to device $DEVICE!"
740                exit 1
741            fi
742        done
743
744        for SRCFILE in `ls $SRCDIR`; do
745            DSTFILE=`basename $SRCFILE`
746            if [ "$DSTFILE" = "gdbserver" -o "$DSTFILE" = "gdb.setup" ] ; then
747                continue
748            fi
749            echo "$DSTFILE" | grep -q -e '\.so$'
750            if [ $? = 0 ] ; then
751              continue
752            fi
753            if [ -z "$RUN_TESTS" -a -f "$TEST/BROKEN_RUN" ]; then
754                grep -q -w -e "$DSTFILE" "$TEST/BROKEN_RUN"
755                if [ $? = 0 ] ; then
756                    continue
757                fi
758            fi
759            SRCFILE="$SRCDIR/$SRCFILE"
760            if [ $HOST_OS = cygwin ]; then
761                SRCFILE=`cygpath -m $SRCFILE`
762            fi
763            DSTFILE="$DSTDIR/$DSTFILE"
764            run $ADB_CMD -s "$DEVICE" push "$SRCFILE" "$DSTFILE" &&
765            run $ADB_CMD -s "$DEVICE" shell chmod 0755 $DSTFILE
766            if [ $? != 0 ] ; then
767                dump "ERROR: Could not install $SRCFILE to device $DEVICE!"
768                exit 1
769            fi
770            PROGRAM="`basename $DSTFILE`"
771            dump "Running device test [$CPU_ABI]: $TEST_NAME (`basename $PROGRAM`)"
772            adb_var_shell_cmd "$DEVICE" "" "cd $DSTDIR && LD_LIBRARY_PATH=$DSTDIR ./$PROGRAM"
773            if [ $? != 0 ] ; then
774                dump "   ---> TEST FAILED!!"
775            fi
776        done
777        # Cleanup
778        adb_var_shell_cmd "$DEVICE" "" rm -r $DSTDIR
779    }
780
781    for DIR in `ls -d $ROOTDIR/tests/device/*`; do
782        if is_buildable $DIR; then
783            build_device_test $DIR
784        fi
785    done
786
787    # Do we have adb and any device connected here?
788    # If not, we can't run our tests.
789    #
790    SKIP_TESTS=no
791    if [ -z "$ADB_CMD" ] ; then
792        dump "WARNING: No 'adb' in your path!"
793        SKIP_TESTS=yes
794    else
795        # Get list of online devices, turn ' ' in device into '#'
796        ADB_DEVICES=`$ADB_CMD devices | grep -v offline | awk 'NR>1 {gsub(/[ \t]+device$/,""); print;}' | sed '/^$/d' | sort | tr ' ' '#'`
797        ADB_DEVICES=$(echo $ADB_DEVICES | tr '\n' ' ')
798        log2 "ADB online devices (sorted): $ADB_DEVICES"
799        ADB_DEVCOUNT=`echo "$ADB_DEVICES" | wc -w`
800        if [ "$ADB_DEVCOUNT" = "0" ]; then
801            dump "WARNING: No device connected to adb!"
802            SKIP_TESTS=yes
803        else
804            ADB_DEVICES="$ADB_DEVICES "
805            if [ -n "$ANDROID_SERIAL" ] ; then
806                ADB_SERIAL=$(echo "$ANDROID_SERIAL" | tr ' ' '#')  # turn ' ' into '#'
807                if [ "$ADB_DEVICES" = "${ADB_DEVICES%$ADB_SERIAL *}" ] ; then
808                    dump "WARNING: Device $ANDROID_SERIAL cannot be found or offline!"
809                    SKIP_TESTS=yes
810                else
811                    ADB_DEVICES="$ANDROID_SERIAL"
812                fi
813            fi
814        fi
815    fi
816    if [ "$SKIP_TESTS" = "yes" ] ; then
817        dump "SKIPPING RUNNING TESTS ON DEVICE!"
818    else
819        AT_LEAST_CPU_ABI_MATCH=
820        for DEVICE in $ADB_DEVICES; do
821            # undo earlier ' '-to-'#' translation
822            DEVICE=$(echo "$DEVICE" | tr '#' ' ')
823            # get device CPU_ABI and CPU_ABI2, each may contain list of abi, comma-delimited.
824            adb_var_shell_cmd "$DEVICE" CPU_ABI1 getprop ro.product.cpu.abi
825            adb_var_shell_cmd "$DEVICE" CPU_ABI2 getprop ro.product.cpu.abi2
826            CPU_ABIS="$CPU_ABI1,$CPU_ABI2"
827            CPU_ABIS=$(commas_to_spaces $CPU_ABIS)
828            if [ "$CPU_ABIS" = " " ]; then
829              # Very old cupcake-based Android devices don't have these properties
830              # defined. Fortunately, they are all armeabi-based.
831              CPU_ABIS=armeabi
832            fi
833            for CPU_ABI in $CPU_ABIS; do
834                if [ "$ABI" = "default" -o "$ABI" = "$CPU_ABI" ] ; then
835                    AT_LEAST_CPU_ABI_MATCH="yes"
836                    for DIR in `ls -d $ROOTDIR/tests/device/*`; do
837                        if is_buildable $DIR; then
838                            log "Running device test on $DEVICE [$CPU_ABI]: $DIR"
839                            run_device_test "$DEVICE" "$CPU_ABI" "$DIR" /data/local/tmp
840                        fi
841                    done
842                fi
843            done
844        done
845        if [ "$AT_LEAST_CPU_ABI_MATCH" != "yes" ] ; then
846            dump "WARNING: No device matches ABI $ABI! SKIPPING RUNNING TESTS ON DEVICE!"
847        fi
848    fi
849fi
850
851dump "Cleaning up..."
852rm -rf $BUILD_DIR
853dump "Done."
854