1#!/bin/bash
2#
3# Copyright (C) 2015 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
17if [ ! -d libcore ]; then
18  echo "Script needs to be run at the root of the android tree"
19  exit 1
20fi
21
22source build/envsetup.sh >&/dev/null # for get_build_var, setpaths
23setpaths # include platform prebuilt java, javac, etc in $PATH.
24
25if [ -z "$ANDROID_HOST_OUT" ] ; then
26  ANDROID_HOST_OUT=${OUT_DIR-$ANDROID_BUILD_TOP/out}/host/linux-x86
27fi
28
29# "Root" (actually "system") directory on device (in the case of
30# target testing).
31android_root=${ART_TEST_ANDROID_ROOT:-/system}
32
33java_lib_location="${ANDROID_HOST_OUT}/../common/obj/JAVA_LIBRARIES"
34make_target_name="apache-harmony-jdwp-tests-hostdex"
35
36function boot_classpath_arg {
37  local dir="$1"
38  local suffix="$2"
39  shift 2
40  local separator=""
41  for var
42  do
43    if [ "$var" = "conscrypt" ] && [ "$mode" = "target" ]; then
44      printf -- "${separator}/apex/com.android.conscrypt/javalib/conscrypt.jar";
45    elif [ "$var" = "core-icu4j" ] && [ "$mode" = "target" ]; then
46      printf -- "${separator}/apex/com.android.i18n/javalib/core-icu4j.jar";
47    else
48      printf -- "${separator}${dir}/${var}${suffix}.jar";
49    fi
50    separator=":"
51  done
52}
53
54# Note: This must start with the CORE_IMG_JARS in Android.common_path.mk
55# because that's what we use for compiling the boot.art image.
56# It may contain additional modules from TEST_CORE_JARS.
57BOOT_CLASSPATH_JARS="core-oj core-libart okhttp bouncycastle apache-xml core-icu4j conscrypt"
58
59vm_args=""
60art="$android_root/bin/art"
61mode="target"
62art_debugee="sh $android_root/bin/art"
63args=$@
64chroot_option=
65debuggee_args="-Xcompiler-option --debuggable"
66device_dir="--device-dir=/data/local/tmp"
67# We use the art script on target to ensure the runner and the debuggee share the same
68# image.
69vm_command="--vm-command=$art"
70image_compiler_option=""
71plugin=""
72debug="no"
73explicit_debug="no"
74verbose="no"
75image="-Ximage:/apex/com.android.art/javalib/boot.art"
76boot_classpath="$(boot_classpath_arg /apex/com.android.art/javalib "" $BOOT_CLASSPATH_JARS)"
77boot_classpath_locations=""
78with_jdwp_path=""
79agent_wrapper=""
80vm_args=""
81# By default, we run the whole JDWP test suite.
82has_specific_test="no"
83test="org.apache.harmony.jpda.tests.share.AllTests"
84# Use JIT compiling by default.
85use_jit=true
86instant_jit=false
87variant_cmdline_parameter="--variant=X32"
88dump_command="/bin/true"
89called_from_libjdwp=${RUN_JDWP_TESTS_CALLED_FROM_LIBJDWP:-false}
90run_internal_jdwp_test=false
91# Let LUCI bots do what they want.
92if test -v LUCI_CONTEXT; then
93  run_internal_jdwp_test=true
94fi
95# Timeout of JDWP test in ms.
96#
97# Note: some tests expect a timeout to check that *no* reply/event is received for a specific case.
98# A lower timeout can save up several minutes when running the whole test suite, especially for
99# continuous testing. This value can be adjusted to fit the configuration of the host machine(s).
100jdwp_test_timeout=10000
101
102skip_tests=
103gdb_target=
104has_gdb="no"
105
106while true; do
107  if [[ "$1" == "--mode=host" ]]; then
108    mode="host"
109    # Specify bash explicitly since the art script cannot, since it has to run on the device
110    # with mksh.
111    art="bash ${OUT_DIR-out}/host/linux-x86/bin/art"
112    art_debugee="bash ${OUT_DIR-out}/host/linux-x86/bin/art"
113    # We force generation of a new image to avoid build-time and run-time classpath differences.
114    image="-Ximage:/system/non/existent/vogar.art"
115    # Pass the host boot classpath.
116    if [ "${ANDROID_HOST_OUT:0:${#ANDROID_BUILD_TOP}+1}" = "${ANDROID_BUILD_TOP}/" ]; then
117      framework_location="${ANDROID_HOST_OUT:${#ANDROID_BUILD_TOP}+1}/framework"
118    else
119      echo "error: ANDROID_BUILD_TOP/ is not a prefix of ANDROID_HOST_OUT"
120      echo "ANDROID_BUILD_TOP=${ANDROID_BUILD_TOP}"
121      echo "ANDROID_HOST_OUT=${ANDROID_HOST_OUT}"
122      exit
123    fi
124    boot_classpath="$(boot_classpath_arg ${ANDROID_HOST_OUT}/framework -hostdex $BOOT_CLASSPATH_JARS)"
125    boot_classpath_locations="$(boot_classpath_arg ${framework_location} -hostdex $BOOT_CLASSPATH_JARS)"
126    # We do not need a device directory on host.
127    device_dir=""
128    # Vogar knows which VM to use on host.
129    vm_command=""
130    shift
131  elif [[ "$1" == "--mode=jvm" ]]; then
132    mode="ri"
133    make_target_name="apache-harmony-jdwp-tests"
134    run_internal_jdwp_test=true
135    art="$(which java)"
136    art_debugee="$(which java)"
137    # No need for extra args.
138    debuggee_args=""
139    # No image. On the RI.
140    image=""
141    boot_classpath=""
142    boot_classpath_locations=""
143    # We do not need a device directory on RI.
144    device_dir=""
145    # Vogar knows which VM to use on RI.
146    vm_command=""
147    # We don't care about jit with the RI
148    use_jit=false
149    shift
150  elif [[ $1 == --skip-test ]]; then
151    skip_tests="${skip_tests},${2}"
152    # remove the --skip-test
153    args=${args/$1}
154    shift
155    # remove the arg
156    args=${args/$1}
157    shift
158  elif [[ $1 == --force-run-test ]]; then
159    run_internal_jdwp_test=true
160    # remove the --force-run-test
161    args=${args/$1}
162    shift
163  elif [[ $1 == --test-timeout-ms ]]; then
164    # Remove the --test-timeout-ms from the arguments.
165    args=${args/$1}
166    shift
167    jdwp_test_timeout=$1
168    # Remove the argument
169    args=${args/$1}
170    shift
171  elif [[ $1 == --agent-wrapper ]]; then
172    # Remove the --agent-wrapper from the arguments.
173    args=${args/$1}
174    shift
175    agent_wrapper=${agent_wrapper}${1},
176    # Remove the argument
177    args=${args/$1}
178    shift
179  elif [[ $1 == -Ximage:* ]]; then
180    image="$1"
181    shift
182  elif [[ "$1" == "--instant-jit" ]]; then
183    instant_jit=true
184    # Remove the --instant-jit from the arguments.
185    args=${args/$1}
186    shift
187  elif [[ "$1" == "--no-jit" ]]; then
188    use_jit=false
189    # Remove the --no-jit from the arguments.
190    args=${args/$1}
191    shift
192  elif [[ $1 == "--no-debug" ]]; then
193    explicit_debug="yes"
194    debug="no"
195    # Remove the --no-debug from the arguments.
196    args=${args/$1}
197    shift
198  elif [[ $1 == "--debug" ]]; then
199    explicit_debug="yes"
200    debug="yes"
201    # Remove the --debug from the arguments.
202    args=${args/$1}
203    shift
204  elif [[ $1 == "--verbose" ]]; then
205    verbose="yes"
206    # Remove the --verbose from the arguments.
207    args=${args/$1}
208    shift
209  elif [[ $1 == "--gdbserver" ]]; then
210    # Remove the --gdbserver from the arguments.
211    args=${args/$1}
212    has_gdb="yes"
213    shift
214    gdb_target=$1
215    # Remove the target from the arguments.
216    args=${args/$1}
217    shift
218  elif [[ $1 == "--test" ]]; then
219    # Remove the --test from the arguments.
220    args=${args/$1}
221    shift
222    has_specific_test="yes"
223    test=$1
224    # Remove the test from the arguments.
225    args=${args/$1}
226    shift
227  elif [[ "$1" == "--jdwp-path" ]]; then
228    # Remove the --jdwp-path from the arguments.
229    args=${args/$1}
230    shift
231    with_jdwp_path=$1
232    # Remove the path from the arguments.
233    args=${args/$1}
234    shift
235  elif [[ "$1" == "" ]]; then
236    break
237  elif [[ $1 == --variant=* ]]; then
238    variant_cmdline_parameter=$1
239    shift
240  elif [[ $1 == -Xplugin:* ]]; then
241    plugin="$1"
242    args=${args/$1}
243    shift
244  else
245    shift
246  fi
247done
248
249if [ ! -t 1 ] ; then
250  # Suppress color codes if not attached to a terminal
251  args="$args --no-color"
252fi
253
254if [[ $mode == "target" ]]; then
255  # Honor environment variable ART_TEST_CHROOT.
256  if [[ -n "$ART_TEST_CHROOT" ]]; then
257    # Set Vogar's `--chroot` option.
258    chroot_option="--chroot $ART_TEST_CHROOT"
259    # Adjust settings for chroot environment.
260    art="/system/bin/art"
261    art_debugee="sh /system/bin/art"
262    vm_command="--vm-command=$art"
263    device_dir="--device-dir=/tmp"
264  fi
265fi
266
267if [[ $called_from_libjdwp != "true" ]]; then
268  if [[ $run_internal_jdwp_test = "false" ]]; then
269    echo "Calling run_jdwp_tests.sh directly is probably not what you want. You probably want to"
270    echo "run ./art/tools/run-libjdwp-tests.sh instead in order to test the JDWP implementation"
271    echo "used by apps. If you really wish to run these tests using the deprecated internal JDWP"
272    echo "implementation pass the '--force-run-test' flag."
273    exit 1
274  fi
275fi
276
277if [[ $has_gdb = "yes" ]]; then
278  if [[ $explicit_debug = "no" ]]; then
279    debug="yes"
280  fi
281fi
282
283if [[ $mode == "ri" ]]; then
284  if [[ "x$with_jdwp_path" != "x" ]]; then
285    vm_args="${vm_args} --vm-arg -Djpda.settings.debuggeeAgentArgument=-agentpath:${agent_wrapper}"
286    vm_args="${vm_args} --vm-arg -Djpda.settings.debuggeeAgentName=$with_jdwp_path"
287  fi
288  if [[ "x$image" != "x" ]]; then
289    echo "Cannot use -Ximage: with --mode=jvm"
290    exit 1
291  elif [[ $has_gdb = "yes" ]]; then
292    echo "Cannot use --gdbserver with --mode=jvm"
293    exit 1
294  elif [[ $debug == "yes" ]]; then
295    echo "Cannot use --debug with --mode=jvm"
296    exit 1
297  fi
298else
299  if [[ "$mode" == "host" ]]; then
300    dump_command="/bin/kill -3"
301  else
302    # Note that this dumping command won't work when `$android_root`
303    # is different from `/system` (e.g. on ART Buildbot devices) when
304    # the device is running Android N, as the debuggerd protocol
305    # changed in an incompatible way in Android O (see b/32466479).
306    dump_command="$android_root/xbin/su root $android_root/bin/debuggerd"
307  fi
308  if [[ $has_gdb = "yes" ]]; then
309    if [[ $mode == "target" ]]; then
310      echo "Cannot use --gdbserver with --mode=target"
311      exit 1
312    else
313      art_debugee="$art_debugee --gdbserver $gdb_target"
314      # The tests absolutely require some timeout. We set a ~2 week timeout since we can kill the
315      # test with gdb if it goes on too long.
316      jdwp_test_timeout="1000000000"
317    fi
318  fi
319  if [[ "x$with_jdwp_path" != "x" ]]; then
320    vm_args="${vm_args} --vm-arg -Djpda.settings.debuggeeAgentArgument=-agentpath:${agent_wrapper}"
321    vm_args="${vm_args} --vm-arg -Djpda.settings.debuggeeAgentName=${with_jdwp_path}"
322  fi
323  vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --debuggable"
324  # we don't want to be trying to connect to adbconnection which might not have
325  # been built.
326  vm_args="${vm_args} --vm-arg -XjdwpProvider:none"
327  # Make sure the debuggee doesn't re-generate, nor clean up what the debugger has generated.
328  art_debugee="$art_debugee --no-compile --no-clean"
329fi
330
331function jlib_name {
332  local path=$1
333  local str="classes"
334  local suffix="jar"
335  if [[ $mode == "ri" ]]; then
336    str="javalib"
337  fi
338  echo "$path/$str.$suffix"
339}
340
341# Jar containing all the tests.
342test_jar=$(jlib_name "${java_lib_location}/${make_target_name}_intermediates")
343
344if [[ ! -f $test_jar ]]; then
345  echo "Before running, you must build jdwp tests and vogar:" \
346       "m ${make_target_name} vogar"
347  exit 1
348fi
349
350# For the host:
351#
352# If, on the other hand, there is a variant set, use it to modify the art_debugee parameter to
353# force the fork to have the same bitness as the controller. This should be fine and not impact
354# testing (cross-bitness), as the protocol is always 64-bit anyways (our implementation).
355#
356# Note: this isn't necessary for the device as the BOOTCLASSPATH environment variable is set there
357#       and used as a fallback.
358if [[ $mode == "host" ]]; then
359  variant=${variant_cmdline_parameter:10}
360  if [[ $variant == "x32" || $variant == "X32" ]]; then
361    art_debugee="$art_debugee --32"
362  elif [[ $variant == "x64" || $variant == "X64" ]]; then
363    art_debugee="$art_debugee --64"
364  else
365    echo "Error, do not understand variant $variant_cmdline_parameter."
366    exit 1
367  fi
368fi
369
370if [[ "$image" != "" ]]; then
371  vm_args="$vm_args --vm-arg $image"
372  debuggee_args="$debuggee_args $image"
373fi
374if [[ "$boot_classpath" != "" ]]; then
375  vm_args="$vm_args --vm-arg -Xbootclasspath:${boot_classpath}"
376  debuggee_args="$debuggee_args -Xbootclasspath:${boot_classpath}"
377fi
378if [[ "$boot_classpath_locations" != "" ]]; then
379  vm_args="$vm_args --vm-arg -Xbootclasspath-locations:${boot_classpath_locations}"
380  debuggee_args="$debuggee_args -Xbootclasspath-locations:${boot_classpath_locations}"
381fi
382
383if [[ "$plugin" != "" ]]; then
384  vm_args="$vm_args --vm-arg $plugin"
385fi
386
387if [[ $mode != "ri" ]]; then
388  # Because we're running debuggable, we discard any AOT code.
389  # Therefore we run de2oat with 'quicken' to avoid spending time compiling.
390  vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken"
391  debuggee_args="$debuggee_args -Xcompiler-option --compiler-filter=quicken"
392
393  if $instant_jit; then
394    debuggee_args="$debuggee_args -Xjitthreshold:0"
395  fi
396
397  vm_args="$vm_args --vm-arg -Xusejit:$use_jit"
398  debuggee_args="$debuggee_args -Xusejit:$use_jit"
399fi
400
401if [[ $debug == "yes" ]]; then
402  art="$art -d"
403  art_debugee="$art_debugee -d"
404  vm_args="$vm_args --vm-arg -XXlib:libartd.so --vm-arg -XX:SlowDebug=true"
405fi
406if [[ $verbose == "yes" ]]; then
407  # Enable JDWP logs in the debuggee.
408  art_debugee="$art_debugee -verbose:jdwp"
409fi
410
411if [[ $mode != "ri" ]]; then
412  toolchain_args="--toolchain d8 --language CUR"
413  if [[ "x$with_jdwp_path" == "x" ]]; then
414    # Need to enable the internal jdwp implementation.
415    art_debugee="${art_debugee} -XjdwpProvider:internal"
416  else
417    # need to disable the jdwpProvider since we give the agent explicitly on the
418    # cmdline.
419    art_debugee="${art_debugee} -XjdwpProvider:none"
420  fi
421else
422  toolchain_args="--toolchain javac --language CUR"
423fi
424
425# Run the tests using vogar.
426vogar $vm_command \
427      $vm_args \
428      --verbose \
429      $args \
430      $chroot_option \
431      $device_dir \
432      $image_compiler_option \
433      --timeout 800 \
434      --vm-arg -Djpda.settings.verbose=true \
435      --vm-arg -Djpda.settings.timeout=$jdwp_test_timeout \
436      --vm-arg -Djpda.settings.waitingTime=$jdwp_test_timeout \
437      --vm-arg -Djpda.settings.transportAddress=127.0.0.1:55107 \
438      --vm-arg -Djpda.settings.dumpProcess="$dump_command" \
439      --vm-arg -Djpda.settings.debuggeeJavaPath="$art_debugee $plugin $debuggee_args" \
440      --vm-arg -Djpda.settings.badTestCases="$skip_tests" \
441      --classpath "$test_jar" \
442      $toolchain_args \
443      $test
444
445vogar_exit_status=$?
446
447echo "Killing stalled dalvikvm processes..."
448if [[ $mode == "host" ]]; then
449  pkill -9 -f /bin/dalvikvm
450else
451  # Tests may run on older Android versions where pkill requires "-l SIGNAL"
452  # rather than "-SIGNAL".
453  adb shell pkill -l 9 -f /bin/dalvikvm
454fi
455echo "Done."
456
457exit $vogar_exit_status
458