Support ART on-device testing in a chroot environment.
This change updates the ART test rules and scripts to allow
installation and ART testing in a chroot directory on device.
All existing ART testing is supported:
- ART gtests (with and without Valgrind).
- ART run-tests.
- libcore tests (with companion CL in external/vogar).
- JDWP tests (with companion CL in external/vogar).
Test: Run ART tests (gtest, run-tests, libcore tests, JDWP tests) in chroot
Bug: 34729697
Bug: 68125496
Change-Id: I398e9bafee61eccd98d827ab8d9b8f6395aaa853
diff --git a/Android.mk b/Android.mk
index 64b9400..d6472be 100644
--- a/Android.mk
+++ b/Android.mk
@@ -110,22 +110,33 @@
# Sync test files to the target, depends upon all things that must be pushed to the target.
.PHONY: test-art-target-sync
-# Check if we need to sync. In case ART_TEST_ANDROID_ROOT is not empty,
-# the code below uses 'adb push' instead of 'adb sync', which does not
-# check if the files on the device have changed.
+# Check if we need to sync. In case ART_TEST_CHROOT or ART_TEST_ANDROID_ROOT
+# is not empty, the code below uses 'adb push' instead of 'adb sync',
+# which does not check if the files on the device have changed.
+# TODO: Remove support for ART_TEST_ANDROID_ROOT when it is no longer needed.
ifneq ($(ART_TEST_NO_SYNC),true)
+# Sync system and data partitions.
ifeq ($(ART_TEST_ANDROID_ROOT),)
+ifeq ($(ART_TEST_CHROOT),)
test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
$(TEST_ART_ADB_ROOT_AND_REMOUNT)
adb sync system && adb sync data
else
test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
$(TEST_ART_ADB_ROOT_AND_REMOUNT)
- adb wait-for-device push $(PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
-# Push the contents of the `data` dir into `/data` on the device. If
-# `/data` already exists on the device, it is not overwritten, but its
-# contents are updated.
- adb push $(PRODUCT_OUT)/data /
+ adb wait-for-device
+ adb push $(PRODUCT_OUT)/system $(ART_TEST_CHROOT)/
+ adb push $(PRODUCT_OUT)/data $(ART_TEST_CHROOT)/
+endif
+else
+test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
+ $(TEST_ART_ADB_ROOT_AND_REMOUNT)
+ adb wait-for-device
+ adb push $(PRODUCT_OUT)/system $(ART_TEST_CHROOT)$(ART_TEST_ANDROID_ROOT)
+# Push the contents of the `data` dir into `$(ART_TEST_CHROOT)/data` on the device (note
+# that $(ART_TEST_CHROOT) can be empty). If `$(ART_TEST_CHROOT)/data` already exists on
+# the device, it is not overwritten, but its content is updated.
+ adb push $(PRODUCT_OUT)/data $(ART_TEST_CHROOT)/
endif
endif
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index b46f677..be040a9 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -472,17 +472,29 @@
$$(gtest_rule) valgrind-$$(gtest_rule): PRIVATE_TARGET_EXE := $$(gtest_target_exe)
+ifeq ($(ART_TEST_CHROOT),)
+# Non-chroot configuration.
+maybe_art_test_chroot :=
+maybe_chroot_command :=
+else
+# Chroot configuration.
+maybe_art_test_chroot := $(ART_TEST_CHROOT)/
+maybe_chroot_command := chroot $(ART_TEST_CHROOT)
+endif
+
+# File witnessing the success of the gtest, the presence of which means the gtest's success.
+gtest_witness := $(maybe_art_test_chroot)$(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID
+
.PHONY: $$(gtest_rule)
$$(gtest_rule): test-art-target-sync
- $(hide) adb shell touch $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID
- $(hide) adb shell rm $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID
- $(hide) adb shell chmod 755 $$(PRIVATE_TARGET_EXE)
+ $(hide) adb shell touch $(gtest_witness)
+ $(hide) adb shell rm $(gtest_witness)
+ $(hide) adb shell chmod 755 $(maybe_art_test_chroot)$$(PRIVATE_TARGET_EXE)
$(hide) $$(call ART_TEST_SKIP,$$@) && \
- (adb shell "env $(GCOV_ENV) LD_LIBRARY_PATH=$(4) \
+ (adb shell "$(maybe_chroot_command) env $(GCOV_ENV) LD_LIBRARY_PATH=$(4) \
ANDROID_ROOT=$(ART_GTEST_TARGET_ANDROID_ROOT) $$(PRIVATE_TARGET_EXE) \
- && touch $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID" \
- && (adb pull $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID /tmp/ \
- && $$(call ART_TEST_PASSED,$$@)) \
+ && touch $(gtest_witness)" \
+ && (adb pull $(gtest_witness) /tmp/ && $$(call ART_TEST_PASSED,$$@)) \
|| $$(call ART_TEST_FAILED,$$@))
$(hide) rm -f /tmp/$$@-$$$$PPID
@@ -492,19 +504,18 @@
.PHONY: valgrind-$$(gtest_rule)
valgrind-$$(gtest_rule): $(ART_VALGRIND_TARGET_DEPENDENCIES) test-art-target-sync
- $(hide) adb shell touch $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID
- $(hide) adb shell rm $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID
- $(hide) adb shell chmod 755 $$(PRIVATE_TARGET_EXE)
+ $(hide) adb shell touch $(gtest_witness)
+ $(hide) adb shell rm $(gtest_witness)
+ $(hide) adb shell chmod 755 $(maybe_art_test_chroot)$$(PRIVATE_TARGET_EXE)
$(hide) $$(call ART_TEST_SKIP,$$@) && \
- (adb shell "env $(GCOV_ENV) LD_LIBRARY_PATH=$(4) \
+ (adb shell "$(maybe_chroot_command) env $(GCOV_ENV) LD_LIBRARY_PATH=$(4) \
ANDROID_ROOT=$(ART_GTEST_TARGET_ANDROID_ROOT) \
$$$$ANDROID_ROOT/bin/valgrind \
--leak-check=full --error-exitcode=1 --workaround-gcc296-bugs=yes \
--suppressions=$(ART_TARGET_TEST_DIR)/valgrind-target-suppressions.txt \
--num-callers=50 --show-mismatched-frees=no $$(PRIVATE_TARGET_EXE) \
- && touch $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID" \
- && (adb pull $(ART_TARGET_TEST_DIR)/$(TARGET_$(3)ARCH)/$$@-$$$$PPID /tmp/ \
- && $$(call ART_TEST_PASSED,$$@)) \
+ && touch $(gtest_witness)" \
+ && (adb pull $(gtest_witness) /tmp/ && $$(call ART_TEST_PASSED,$$@)) \
|| $$(call ART_TEST_FAILED,$$@))
$(hide) rm -f /tmp/$$@-$$$$PPID
@@ -514,10 +525,12 @@
ART_TEST_TARGET_VALGRIND_GTEST_$(1)_RULES += valgrind-$$(gtest_rule)
# Clear locally defined variables.
- valgrind_gtest_rule :=
- gtest_rule :=
- gtest_exe :=
+ gtest_witness :=
+ maybe_chroot_command :=
+ maybe_art_test_chroot :=
gtest_target_exe :=
+ gtest_exe :=
+ gtest_rule :=
endef # define-art-gtest-rule-target
ART_VALGRIND_DEPENDENCIES := \
@@ -595,10 +608,9 @@
ART_TEST_HOST_VALGRIND_GTEST_$(1)_RULES += valgrind-$$(gtest_rule)
# Clear locally defined variables.
- valgrind_gtest_rule :=
- gtest_rule :=
- gtest_exe :=
gtest_deps :=
+ gtest_exe :=
+ gtest_rule :=
endef # define-art-gtest-rule-host
# Define the rules to build and run host and target gtests.
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 81e77be..fad8011 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -13,6 +13,7 @@
ARCHITECTURES_64="(arm64|x86_64|mips64|none)"
ARCHITECTURES_PATTERN="${ARCHITECTURES_32}"
BOOT_IMAGE=""
+CHROOT=
COMPILE_FLAGS=""
DALVIKVM="dalvikvm32"
DEBUGGER="n"
@@ -299,6 +300,10 @@
elif [ "x$1" = "x--no-optimize" ]; then
OPTIMIZE="n"
shift
+ elif [ "x$1" = "x--chroot" ]; then
+ shift
+ CHROOT="$1"
+ shift
elif [ "x$1" = "x--android-root" ]; then
shift
ANDROID_ROOT="$1"
@@ -367,6 +372,9 @@
fi
done
+# The DEX_LOCATION with the chroot prefix, if any.
+CHROOT_DEX_LOCATION="$CHROOT$DEX_LOCATION"
+
if [ "$USE_JVM" = "n" ]; then
FLAGS="${FLAGS} ${ANDROID_FLAGS}"
for feature in ${EXPERIMENTAL}; do
@@ -817,28 +825,28 @@
adb root > /dev/null
adb wait-for-device
if [ "$QUIET" = "n" ]; then
- adb shell rm -rf $DEX_LOCATION
- adb shell mkdir -p $DEX_LOCATION
- adb push $TEST_NAME.jar $DEX_LOCATION
- adb push $TEST_NAME-ex.jar $DEX_LOCATION
+ adb shell rm -rf $CHROOT_DEX_LOCATION
+ adb shell mkdir -p $CHROOT_DEX_LOCATION
+ adb push $TEST_NAME.jar $CHROOT_DEX_LOCATION
+ adb push $TEST_NAME-ex.jar $CHROOT_DEX_LOCATION
if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
- adb push profile $DEX_LOCATION
+ adb push profile $CHROOT_DEX_LOCATION
fi
# Copy resource folder
if [ -d res ]; then
- adb push res $DEX_LOCATION
+ adb push res $CHROOT_DEX_LOCATION
fi
else
- adb shell rm -r $DEX_LOCATION >/dev/null 2>&1
- adb shell mkdir -p $DEX_LOCATION >/dev/null 2>&1
- adb push $TEST_NAME.jar $DEX_LOCATION >/dev/null 2>&1
- adb push $TEST_NAME-ex.jar $DEX_LOCATION >/dev/null 2>&1
+ adb shell rm -rf $CHROOT_DEX_LOCATION >/dev/null 2>&1
+ adb shell mkdir -p $CHROOT_DEX_LOCATION >/dev/null 2>&1
+ adb push $TEST_NAME.jar $CHROOT_DEX_LOCATION >/dev/null 2>&1
+ adb push $TEST_NAME-ex.jar $CHROOT_DEX_LOCATION >/dev/null 2>&1
if [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then
- adb push profile $DEX_LOCATION >/dev/null 2>&1
+ adb push profile $CHROOT_DEX_LOCATION >/dev/null 2>&1
fi
# Copy resource folder
if [ -d res ]; then
- adb push res $DEX_LOCATION >/dev/null 2>&1
+ adb push res $CHROOT_DEX_LOCATION >/dev/null 2>&1
fi
fi
@@ -847,7 +855,7 @@
# Current default installation is dalvikvm 64bits and dex2oat 32bits,
# so we can only use LD_LIBRARY_PATH when testing on a local
# installation.
- LD_LIBRARY_PATH=$ANDROID_ROOT/$LIBRARY_DIRECTORY:$LD_LIBRARY_PATH
+ LD_LIBRARY_PATH="$ANDROID_ROOT/$LIBRARY_DIRECTORY:$LD_LIBRARY_PATH"
fi
# System libraries needed by libarttestd.so
@@ -889,14 +897,18 @@
fi
if [ "$QUIET" = "n" ]; then
- adb push $cmdfile $DEX_LOCATION/cmdline.sh
+ adb push $cmdfile $CHROOT_DEX_LOCATION/cmdline.sh
else
- adb push $cmdfile $DEX_LOCATION/cmdline.sh > /dev/null 2>&1
+ adb push $cmdfile $CHROOT_DEX_LOCATION/cmdline.sh >/dev/null 2>&1
fi
exit_status=0
if [ "$DRY_RUN" != "y" ]; then
- adb shell sh $DEX_LOCATION/cmdline.sh
+ if [ -n "$CHROOT" ]; then
+ adb shell chroot "$CHROOT" sh $DEX_LOCATION/cmdline.sh
+ else
+ adb shell sh $DEX_LOCATION/cmdline.sh
+ fi
exit_status=$?
fi
diff --git a/test/run-test b/test/run-test
index 5f85b08..be0a88d 100755
--- a/test/run-test
+++ b/test/run-test
@@ -121,6 +121,8 @@
export HIDDENAPI="${ANDROID_HOST_OUT}/bin/hiddenapi"
fi
+chroot=
+
info="info.txt"
build="build"
run="run"
@@ -380,6 +382,16 @@
break
fi
shift
+ elif [ "x$1" = "x--chroot" ]; then
+ shift
+ if [ "x$1" = "x" ]; then
+ echo "$0 missing argument to --chroot" 1>&2
+ usage="yes"
+ break
+ fi
+ chroot="$1"
+ run_args="${run_args} --chroot $1"
+ shift
elif [ "x$1" = "x--android-root" ]; then
shift
if [ "x$1" = "x" ]; then
@@ -449,6 +461,9 @@
fi
done
+# The DEX_LOCATION with the chroot prefix, if any.
+chroot_dex_location="$chroot$DEX_LOCATION"
+
run_args="${run_args} ${image_args}"
# Allocate file descriptor real_stderr and redirect it to the shell's error
# output (fd 2).
@@ -476,7 +491,7 @@
# tmp_dir may be relative, resolve.
#
# Cannot use realpath, as it does not exist on Mac.
-# Cannot us a simple "cd", as the path might not be created yet.
+# Cannot use a simple "cd", as the path might not be created yet.
# Cannot use readlink -m, as it does not exist on Mac.
# Fallback to nuclear option:
noncanonical_tmp_dir=$tmp_dir
@@ -550,7 +565,13 @@
if [ "$runtime" = "jvm" ]; then
if [ "$prebuild_mode" = "yes" ]; then
err_echo "--prebuild with --jvm is unsupported"
- exit 1;
+ exit 1
+ fi
+ else
+ # ART/Dalvik host mode.
+ if [ -n "$chroot" ]; then
+ err_echo "--chroot with --host is unsupported"
+ exit 1
fi
fi
fi
@@ -628,6 +649,12 @@
usage="yes"
fi
+# TODO: Chroot-based bisection search is not supported yet (see below); implement it.
+if [ "$bisection_search" = "yes" -a -n "$chroot" ]; then
+ err_echo "--chroot with --bisection-search is unsupported"
+ exit 1
+fi
+
if [ "$usage" = "no" ]; then
if [ "x$1" = "x" -o "x$1" = "x-" ]; then
test_dir=`basename "$oldwd"`
@@ -732,6 +759,7 @@
echo " Run with jvmti method redefinition stress testing"
echo " --always-clean Delete the test files even if the test fails."
echo " --never-clean Keep the test files even if the test succeeds."
+ echo " --chroot [newroot] Run with root directory set to newroot."
echo " --android-root [path] The path on target for the android root. (/system by default)."
echo " --dex2oat-swap Use a dex2oat swap file."
echo " --instruction-set-features [string]"
@@ -866,7 +894,7 @@
if [ "$run_exit" = "0" ]; then
if [ "$run_checker" = "yes" ]; then
if [ "$target_mode" = "yes" ]; then
- adb pull $cfg_output_dir/$cfg_output &> /dev/null
+ adb pull "$chroot/$cfg_output_dir/$cfg_output" &> /dev/null
fi
"$checker" $checker_args "$cfg_output" "$tmp_dir" 2>&1
checker_exit="$?"
@@ -888,7 +916,7 @@
"./${run}" $run_args "$@" >"$output" 2>&1
if [ "$run_checker" = "yes" ]; then
if [ "$target_mode" = "yes" ]; then
- adb pull $cfg_output_dir/$cfg_output &> /dev/null
+ adb pull "$chroot/$cfg_output_dir/$cfg_output" &> /dev/null
fi
"$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
fi
@@ -926,7 +954,7 @@
good_run="no"
elif [ "$run_checker" = "yes" ]; then
if [ "$target_mode" = "yes" ]; then
- adb pull $cfg_output_dir/$cfg_output &> /dev/null
+ adb pull "$chroot/$cfg_output_dir/$cfg_output" &> /dev/null
fi
"$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
checker_exit="$?"
@@ -986,6 +1014,7 @@
) 2>&${real_stderr} 1>&2
# Attempt bisection only if the test failed.
+# TODO: Implement support for chroot-based bisection search.
if [ "$bisection_search" = "yes" -a "$good" != "yes" ]; then
# Bisecting works by skipping different optimization passes which breaks checker assertions.
if [ "$run_checker" == "yes" ]; then
@@ -997,17 +1026,18 @@
maybe_device_mode=""
raw_cmd=""
if [ "$target_mode" = "yes" ]; then
- # Produce cmdline.sh in $DEX_LOCATION. "$@" is passed as a runtime option
+ # Produce cmdline.sh in $chroot_dex_location. "$@" is passed as a runtime option
# so that cmdline.sh forwards its arguments to dalvikvm. invoke-with is set
# to exec in order to preserve pid when calling dalvikvm. This is required
# for bisection search to correctly retrieve logs from device.
"./${run}" $run_args --runtime-option '"$@"' --invoke-with exec --dry-run "$@" &> /dev/null
- adb shell chmod u+x "$DEX_LOCATION/cmdline.sh"
+ adb shell chmod u+x "$chroot_dex_location/cmdline.sh"
maybe_device_mode="--device"
raw_cmd="$DEX_LOCATION/cmdline.sh"
else
raw_cmd="$cwd/${run} --external-log-tags $run_args $@"
fi
+ # TODO: Pass a `--chroot` option to the bisection_search.py script and use it there.
$ANDROID_BUILD_TOP/art/tools/bisection_search/bisection_search.py \
$maybe_device_mode \
--raw-cmd="$raw_cmd" \
@@ -1023,7 +1053,7 @@
cd "$oldwd"
rm -rf "$tmp_dir"
if [ "$target_mode" = "yes" -a "$build_exit" = "0" ]; then
- adb shell rm -rf $DEX_LOCATION
+ adb shell rm -rf $chroot_dex_location
fi
if [ "$good" = "yes" ]; then
exit 0
@@ -1040,7 +1070,7 @@
else
echo "${TEST_NAME} files left in ${tmp_dir} on host"
if [ "$target_mode" == "yes" ]; then
- echo "and in ${DEX_LOCATION} on target"
+ echo "and in ${chroot_dex_location} on target"
fi
fi
diff --git a/test/testrunner/env.py b/test/testrunner/env.py
index 7564f5a..0c1c308 100644
--- a/test/testrunner/env.py
+++ b/test/testrunner/env.py
@@ -91,6 +91,8 @@
HOST_2ND_ARCH_PREFIX_DEX2OAT_HOST_INSTRUCTION_SET_FEATURES = _env.get(
HOST_2ND_ARCH_PREFIX + 'DEX2OAT_HOST_INSTRUCTION_SET_FEATURES')
+ART_TEST_CHROOT = _env.get('ART_TEST_CHROOT')
+
ART_TEST_ANDROID_ROOT = _env.get('ART_TEST_ANDROID_ROOT')
ART_TEST_WITH_STRACE = _getEnvBoolean('ART_TEST_DEBUG_GC', False)
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 88b509d..254ffc9 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -320,6 +320,9 @@
if env.ART_TEST_BISECTION:
options_all += ' --bisection-search'
+ if env.ART_TEST_CHROOT:
+ options_all += ' --chroot ' + env.ART_TEST_CHROOT
+
if env.ART_TEST_ANDROID_ROOT:
options_all += ' --android-root ' + env.ART_TEST_ANDROID_ROOT