1#!/bin/bash
2#
3# Runner for an individual run-test.
4
5msg() {
6    if [ "$QUIET" = "n" ]; then
7        echo "$@"
8    fi
9}
10
11ANDROID_ROOT="/system"
12ARCHITECTURES_32="(arm|x86|mips|none)"
13ARCHITECTURES_64="(arm64|x86_64|mips64|none)"
14ARCHITECTURES_PATTERN="${ARCHITECTURES_32}"
15BOOT_IMAGE=""
16COMPILE_FLAGS=""
17DALVIKVM="dalvikvm32"
18DEBUGGER="n"
19DEV_MODE="n"
20DEX2OAT=""
21FALSE_BIN="/system/bin/false"
22FLAGS=""
23GDB=""
24GDB_ARGS=""
25GDB_SERVER="gdbserver"
26HAVE_IMAGE="y"
27HOST="n"
28INTERPRETER="n"
29JIT="n"
30INVOKE_WITH=""
31ISA=x86
32LIBRARY_DIRECTORY="lib"
33MAIN=""
34OPTIMIZE="y"
35PATCHOAT=""
36PREBUILD="y"
37QUIET="n"
38RELOCATE="y"
39SECONDARY_DEX=""
40TIME_OUT="y"
41# Value in minutes.
42TIME_OUT_VALUE=10
43USE_GDB="n"
44USE_JVM="n"
45VERIFY="y"
46ZYGOTE=""
47DEX_VERIFY=""
48USE_DEX2OAT_AND_PATCHOAT="y"
49
50while true; do
51    if [ "x$1" = "x--quiet" ]; then
52        QUIET="y"
53        shift
54    elif [ "x$1" = "x--lib" ]; then
55        shift
56        if [ "x$1" = "x" ]; then
57            echo "$0 missing argument to --lib" 1>&2
58            exit 1
59        fi
60        LIB="$1"
61        shift
62    elif [ "x$1" = "x-Xcompiler-option" ]; then
63        shift
64        option="$1"
65        FLAGS="${FLAGS} -Xcompiler-option $option"
66        COMPILE_FLAGS="${COMPILE_FLAGS} $option"
67        shift
68    elif [ "x$1" = "x--runtime-option" ]; then
69        shift
70        option="$1"
71        FLAGS="${FLAGS} $option"
72        shift
73    elif [ "x$1" = "x--boot" ]; then
74        shift
75        BOOT_IMAGE="$1"
76        shift
77    elif [ "x$1" = "x--no-dex2oat" ]; then
78        DEX2OAT="-Xcompiler:${FALSE_BIN}"
79        USE_DEX2OAT_AND_PATCHOAT="n"
80        shift
81    elif [ "x$1" = "x--no-patchoat" ]; then
82        PATCHOAT="-Xpatchoat:${FALSE_BIN}"
83        USE_DEX2OAT_AND_PATCHOAT="n"
84        shift
85    elif [ "x$1" = "x--relocate" ]; then
86        RELOCATE="y"
87        shift
88    elif [ "x$1" = "x--no-relocate" ]; then
89        RELOCATE="n"
90        shift
91    elif [ "x$1" = "x--prebuild" ]; then
92        PREBUILD="y"
93        shift
94    elif [ "x$1" = "x--host" ]; then
95        HOST="y"
96        ANDROID_ROOT="$ANDROID_HOST_OUT"
97        shift
98    elif [ "x$1" = "x--no-prebuild" ]; then
99        PREBUILD="n"
100        shift
101    elif [ "x$1" = "x--no-image" ]; then
102        HAVE_IMAGE="n"
103        shift
104    elif [ "x$1" = "x--secondary" ]; then
105        SECONDARY_DEX=":$DEX_LOCATION/$TEST_NAME-ex.jar"
106        shift
107    elif [ "x$1" = "x--debug" ]; then
108        DEBUGGER="y"
109        TIME_OUT="n"
110        shift
111    elif [ "x$1" = "x--gdb" ]; then
112        USE_GDB="y"
113        DEV_MODE="y"
114        TIME_OUT="n"
115        shift
116    elif [ "x$1" = "x--gdb-arg" ]; then
117        shift
118        gdb_arg="$1"
119        GDB_ARGS="${GDB_ARGS} $gdb_arg"
120        shift
121    elif [ "x$1" = "x--zygote" ]; then
122        ZYGOTE="-Xzygote"
123        msg "Spawning from zygote"
124        shift
125    elif [ "x$1" = "x--dev" ]; then
126        DEV_MODE="y"
127        shift
128    elif [ "x$1" = "x--interpreter" ]; then
129        INTERPRETER="y"
130        shift
131    elif [ "x$1" = "x--jit" ]; then
132        JIT="y"
133        shift
134    elif [ "x$1" = "x--jvm" ]; then
135        USE_JVM="y"
136        shift
137    elif [ "x$1" = "x--invoke-with" ]; then
138        shift
139        if [ "x$1" = "x" ]; then
140            echo "$0 missing argument to --invoke-with" 1>&2
141            exit 1
142        fi
143        if [ "x$INVOKE_WITH" = "x" ]; then
144            INVOKE_WITH="$1"
145        else
146            INVOKE_WITH="$INVOKE_WITH $1"
147        fi
148        shift
149    elif [ "x$1" = "x--no-verify" ]; then
150        VERIFY="n"
151        shift
152    elif [ "x$1" = "x--no-optimize" ]; then
153        OPTIMIZE="n"
154        shift
155    elif [ "x$1" = "x--android-root" ]; then
156        shift
157        ANDROID_ROOT="$1"
158        shift
159    elif [ "x$1" = "x--" ]; then
160        shift
161        break
162    elif [ "x$1" = "x--64" ]; then
163        ISA="x86_64"
164        GDB_SERVER="gdbserver64"
165        DALVIKVM="dalvikvm64"
166        LIBRARY_DIRECTORY="lib64"
167        ARCHITECTURES_PATTERN="${ARCHITECTURES_64}"
168        shift
169    elif [ "x$1" = "x--pic-test" ]; then
170        FLAGS="${FLAGS} -Xcompiler-option --compile-pic"
171        COMPILE_FLAGS="${COMPILE_FLAGS} --compile-pic"
172        shift
173    elif expr "x$1" : "x--" >/dev/null 2>&1; then
174        echo "unknown $0 option: $1" 1>&2
175        exit 1
176    else
177        break
178    fi
179done
180
181if [ "x$1" = "x" ] ; then
182  MAIN="Main"
183else
184  MAIN="$1"
185  shift
186fi
187
188if [ "$ZYGOTE" = "" ]; then
189    if [ "$OPTIMIZE" = "y" ]; then
190        if [ "$VERIFY" = "y" ]; then
191            DEX_OPTIMIZE="-Xdexopt:verified"
192        else
193            DEX_OPTIMIZE="-Xdexopt:all"
194        fi
195        msg "Performing optimizations"
196    else
197        DEX_OPTIMIZE="-Xdexopt:none"
198        msg "Skipping optimizations"
199    fi
200
201    if [ "$VERIFY" = "y" ]; then
202        JVM_VERIFY_ARG="-Xverify:all"
203        msg "Performing verification"
204    else
205        DEX_VERIFY="-Xverify:none"
206        JVM_VERIFY_ARG="-Xverify:none"
207        msg "Skipping verification"
208    fi
209fi
210
211msg "------------------------------"
212
213if [ "$DEBUGGER" = "y" ]; then
214  # Use this instead for ddms and connect by running 'ddms':
215  # DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
216  # TODO: add a separate --ddms option?
217
218  PORT=12345
219  msg "Waiting for jdb to connect:"
220  if [ "$HOST" = "n" ]; then
221    msg "    adb forward tcp:$PORT tcp:$PORT"
222  fi
223  msg "    jdb -attach localhost:$PORT"
224  DEBUGGER_OPTS="-agentlib:jdwp=transport=dt_socket,address=$PORT,server=y,suspend=y"
225fi
226
227if [ "$USE_JVM" = "y" ]; then
228  # Xmx is necessary since we don't pass down the ART flags to JVM.
229  cmdline="${JAVA} ${DEBUGGER_OPTS} ${JVM_VERIFY_ARG} -Xmx256m -classpath classes ${FLAGS} $MAIN $@"
230  if [ "$DEV_MODE" = "y" ]; then
231    echo $cmdline
232  fi
233  $cmdline
234  exit
235fi
236
237
238if [ "$HAVE_IMAGE" = "n" ]; then
239    DALVIKVM_BOOT_OPT="-Ximage:/system/non-existant/core.art"
240else
241    DALVIKVM_BOOT_OPT="-Ximage:${BOOT_IMAGE}"
242fi
243
244
245if [ "$USE_GDB" = "y" ]; then
246  if [ "$HOST" = "n" ]; then
247    GDB="$GDB_SERVER :5039"
248  else
249    if [ `uname` = "Darwin" ]; then
250        GDB=lldb
251        GDB_ARGS="$GDB_ARGS -- $DALVIKVM"
252        DALVIKVM=
253    else
254        GDB=gdb
255        GDB_ARGS="$GDB_ARGS --args $DALVIKVM"
256        # Enable for Emacs "M-x gdb" support. TODO: allow extra gdb arguments on command line.
257        # gdbargs="--annotate=3 $gdbargs"
258    fi
259  fi
260fi
261
262if [ "$INTERPRETER" = "y" ]; then
263    INT_OPTS="-Xint"
264    if [ "$VERIFY" = "y" ] ; then
265      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=interpret-only"
266    else
267      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none"
268      DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
269    fi
270fi
271
272if [ "$JIT" = "y" ]; then
273    INT_OPTS="-Xusejit:true"
274    if [ "$VERIFY" = "y" ] ; then
275      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-at-runtime"
276    else
277      COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none"
278      DEX_VERIFY="${DEX_VERIFY} -Xverify:none"
279    fi
280fi
281
282JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
283
284if [ "$RELOCATE" = "y" ]; then
285    COMPILE_FLAGS="${COMPILE_FLAGS} --include-patch-information --runtime-arg -Xnorelocate"
286    FLAGS="${FLAGS} -Xrelocate -Xcompiler-option --include-patch-information"
287    if [ "$HOST" = "y" ]; then
288        # Run test sets a fairly draconian ulimit that we will likely blow right over
289        # since we are relocating. Get the total size of the /system/framework directory
290        # in 512 byte blocks and set it as the ulimit. This should be more than enough
291        # room.
292        if [ ! `uname` = "Darwin" ]; then  # TODO: Darwin doesn't support "du -B..."
293          ulimit -S $(du -c -B512 ${ANDROID_HOST_OUT}/framework | tail -1 | cut -f1) || exit 1
294        fi
295    fi
296else
297    FLAGS="$FLAGS -Xnorelocate"
298    COMPILE_FLAGS="${COMPILE_FLAGS} --runtime-arg -Xnorelocate"
299fi
300
301if [ "$HOST" = "n" ]; then
302  ISA=$(adb shell ls -F /data/dalvik-cache | grep -Ewo "${ARCHITECTURES_PATTERN}")
303  if [ x"$ISA" = "x" ]; then
304    echo "Unable to determine architecture"
305    exit 1
306  fi
307fi
308
309dex2oat_cmdline="true"
310mkdir_cmdline="mkdir -p ${DEX_LOCATION}/dalvik-cache/$ISA"
311
312if [ "$PREBUILD" = "y" ]; then
313  dex2oat_cmdline="$INVOKE_WITH $ANDROID_ROOT/bin/dex2oatd \
314                      $COMPILE_FLAGS \
315                      --boot-image=${BOOT_IMAGE} \
316                      --dex-file=$DEX_LOCATION/$TEST_NAME.jar \
317                      --oat-file=$DEX_LOCATION/dalvik-cache/$ISA/$(echo $DEX_LOCATION/$TEST_NAME.jar/classes.dex | cut -d/ -f 2- | sed "s:/:@:g") \
318                      --instruction-set=$ISA"
319  if [ "x$INSTRUCTION_SET_FEATURES" != "x" ] ; then
320    dex2oat_cmdline="${dex2oat_cmdline} --instruction-set-features=${INSTRUCTION_SET_FEATURES}"
321  fi
322
323  # Add in a timeout. This is important for testing the compilation/verification time of
324  # pathological cases.
325  # Note: as we don't know how decent targets are (e.g., emulator), only do this on the host for
326  #       now. We should try to improve this.
327  #       The current value is rather arbitrary. run-tests should compile quickly.
328  if [ "$HOST" != "n" ]; then
329    # Use SIGRTMIN+2 to try to dump threads.
330    # Use -k 1m to SIGKILL it a minute later if it hasn't ended.
331    dex2oat_cmdline="timeout -k 1m -s SIGRTMIN+2 1m ${dex2oat_cmdline}"
332  fi
333fi
334
335dalvikvm_cmdline="$INVOKE_WITH $GDB $ANDROID_ROOT/bin/$DALVIKVM \
336                  $GDB_ARGS \
337                  $FLAGS \
338                  $DEX_VERIFY \
339                  -XXlib:$LIB \
340                  $PATCHOAT \
341                  $DEX2OAT \
342                  $ZYGOTE \
343                  $JNI_OPTS \
344                  $INT_OPTS \
345                  $DEBUGGER_OPTS \
346                  $DALVIKVM_BOOT_OPT \
347                  -cp $DEX_LOCATION/$TEST_NAME.jar$SECONDARY_DEX $MAIN"
348
349# Remove whitespace.
350dex2oat_cmdline=$(echo $dex2oat_cmdline)
351dalvikvm_cmdline=$(echo $dalvikvm_cmdline)
352
353if [ "$HOST" = "n" ]; then
354    adb root > /dev/null
355    adb wait-for-device
356    if [ "$QUIET" = "n" ]; then
357      adb shell rm -r $DEX_LOCATION
358      adb shell mkdir -p $DEX_LOCATION
359      adb push $TEST_NAME.jar $DEX_LOCATION
360      adb push $TEST_NAME-ex.jar $DEX_LOCATION
361    else
362      adb shell rm -r $DEX_LOCATION >/dev/null 2>&1
363      adb shell mkdir -p $DEX_LOCATION >/dev/null 2>&1
364      adb push $TEST_NAME.jar $DEX_LOCATION >/dev/null 2>&1
365      adb push $TEST_NAME-ex.jar $DEX_LOCATION >/dev/null 2>&1
366    fi
367
368    LD_LIBRARY_PATH=
369    if [ "$ANDROID_ROOT" != "/system" ]; then
370      # Current default installation is dalvikvm 64bits and dex2oat 32bits,
371      # so we can only use LD_LIBRARY_PATH when testing on a local
372      # installation.
373      LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBRARY_DIRECTORY
374    fi
375
376    # Create a script with the command. The command can get longer than the longest
377    # allowed adb command and there is no way to get the exit status from a adb shell
378    # command.
379    cmdline="cd $DEX_LOCATION && \
380             export ANDROID_DATA=$DEX_LOCATION && \
381             export DEX_LOCATION=$DEX_LOCATION && \
382             export ANDROID_ROOT=$ANDROID_ROOT && \
383             $mkdir_cmdline && \
384             export LD_LIBRARY_PATH=$LD_LIBRARY_PATH && \
385             export PATH=$ANDROID_ROOT/bin:$PATH && \
386             $dex2oat_cmdline && \
387             $dalvikvm_cmdline"
388
389    cmdfile=$(tempfile -p "cmd-" -s "-$TEST_NAME")
390    echo "$cmdline" > $cmdfile
391
392    if [ "$DEV_MODE" = "y" ]; then
393      echo $cmdline
394    fi
395
396    if [ "$QUIET" = "n" ]; then
397      adb push $cmdfile $DEX_LOCATION/cmdline.sh
398    else
399      adb push $cmdfile $DEX_LOCATION/cmdline.sh > /dev/null 2>&1
400    fi
401
402    adb shell sh $DEX_LOCATION/cmdline.sh
403
404    rm -f $cmdfile
405else
406    export ANDROID_PRINTF_LOG=brief
407
408    # By default, and for prebuild dex2oat, we are interested in errors being logged. In dev mode
409    # we want debug messages.
410    if [ "$DEV_MODE" = "y" ]; then
411        export ANDROID_LOG_TAGS='*:d'
412    else
413        export ANDROID_LOG_TAGS='*:e'
414    fi
415
416    export ANDROID_DATA="$DEX_LOCATION"
417    export ANDROID_ROOT="${ANDROID_ROOT}"
418    export LD_LIBRARY_PATH="${ANDROID_ROOT}/lib"
419    export DYLD_LIBRARY_PATH="${ANDROID_ROOT}/lib"
420    export PATH="$PATH:${ANDROID_ROOT}/bin"
421
422    cmdline="$dalvikvm_cmdline"
423
424    if [ "$TIME_OUT" = "y" ]; then
425      # Add timeout command if time out is desired.
426      #
427      # Note: We use nested timeouts. The inner timeout sends SIGRTMIN+2 (usually 36) to ART, which
428      #       will induce a full thread dump before abort. However, dumping threads might deadlock,
429      #       so the outer timeout sends the regular SIGTERM after an additional minute to ensure
430      #       termination (without dumping all threads).
431      TIME_PLUS_ONE=$(($TIME_OUT_VALUE + 1))
432      cmdline="timeout ${TIME_PLUS_ONE}m timeout -s SIGRTMIN+2 ${TIME_OUT_VALUE}m $cmdline"
433    fi
434
435    if [ "$DEV_MODE" = "y" ]; then
436      if [ "$PREBUILD" = "y" ]; then
437        echo "$mkdir_cmdline && $dex2oat_cmdline && $cmdline"
438      elif [ "$RELOCATE" = "y" ]; then
439        echo "$mkdir_cmdline && $cmdline"
440      else
441        echo $cmdline
442      fi
443    fi
444
445    cd $ANDROID_BUILD_TOP
446
447    $mkdir_cmdline || exit 1
448    $dex2oat_cmdline || { echo "Dex2oat failed." >&2 ; exit 2; }
449
450    # For running, we must turn off logging when dex2oat or patchoat are missing. Otherwise we use
451    # the same defaults as for prebuilt: everything when --dev, otherwise errors and above only.
452    if [ "$DEV_MODE" = "y" ]; then
453        export ANDROID_LOG_TAGS='*:d'
454    elif [ "$USE_DEX2OAT_AND_PATCHOAT" = "n" ]; then
455        # All tests would log the error of failing dex2oat/patchoat. Be silent here and only
456        # log fatal events.
457        export ANDROID_LOG_TAGS='*:s'
458    else
459        # We are interested in LOG(ERROR) output.
460        export ANDROID_LOG_TAGS='*:e'
461    fi
462
463    if [ "$USE_GDB" = "y" ]; then
464      # When running under gdb, we cannot do piping and grepping...
465      $cmdline "$@"
466    else
467      $cmdline "$@" 2>&1
468      # Add extra detail if time out is enabled.
469      if [ ${PIPESTATUS[0]} = 124 ] && [ "$TIME_OUT" = "y" ]; then
470        echo -e "\e[91mTEST TIMED OUT!\e[0m" >&2
471      fi
472    fi
473fi
474