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