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