Running ART tests in a custom root

ART tests are normally run using system binaries (e.g. /system/bin/dex2oat). This can be a significant issue, as it is not rare that images built from AOSP tip for a specific device are broken (the device does not boot properly). Fortunately, it is possible to work around this issue by using a separate custom root in which the most recent system files are put, allowing to run the tests independently from the real root (think of it as a chrooted environment). The only requirement is having root access to the device (userdebug/eng build), using a stable branch to build the images is fine.

This page explains how to run tests from a custom root on ARMv8 devices. Because of linker limitations, it is currently impossible to run tests both in 32b and 64b mode using the same custom root (with standard lunch targets). Nevertheless, this has been made possible using patches that are currently in the public Gerrit, until they can be merged upstream.

Building and pushing files to the device

Start from an Android tree containing the ART tree you want to test. Make sure that your device is plugged in and accessible through adb. First, apply the required patches (visit the URLs in the comments to check for newer patchsets):

# Linker patch ( )
(cd bionic && git fetch refs/changes/45/16445/3 && git cherry-pick FETCH_HEAD)
# run-test patch ( )
(cd art && git fetch refs/changes/56/16456/2 && git cherry-pick FETCH_HEAD)
# patches ( and
(cd art && git fetch refs/changes/21/222821/4 && git cherry-pick FETCH_HEAD)
(cd art && git fetch refs/changes/00/229400/1 && git cherry-pick FETCH_HEAD)

Then build and sync:

# Setup environment
. build/
# If you use the same tree to "normally" compile AOSP (that is for /system),
# you might want to change the output directory to avoid rebuilds, e.g.:
# export OUT_DIR=out_customroot
# This will also rebuild the host executables, unfortunately there doesn't
# seem to be a way to change only the target build destination.
lunch aosp_bullhead-eng # Replace with appropriate device

# Build necessary files for our custom root
export ART_TEST_ANDROID_ROOT=/data/local/tmp/system
# Override dynamic linker not to depend on anything from the real root
# (assuming ARCH=arm64 and 2ND_ARCH=arm)
./art/tools/ --target
# does not build bin/linker for some reason, build it
# explicitly
m linker

# Sync built files (deleting the old root is necessary, otherwise adb will push
adb wait-for-device shell rm -rf $ART_TEST_ANDROID_ROOT
m test-art-target-sync


ANDROID_ROOT support is not comprehensive. For running ART tests, this should be enough. However, some programs may fail because bionic's libc uses a hardcoded path to sh. This can only be fixed by making _PATH_BSHELL in bionic/libc/include/paths.h point to sh in the custom root (and then recompiling), i.e.:

sed -iE "s,(_PATH_BSHELL\s*)\".*\",\1\"$ANDROID_ROOT/bin/sh\"," libc/include/paths.h

Running tests in the custom root

Once the custom root has been synced, art/test/run-test can be used to run tests in the custom root by passing it --android-root $ART_TEST_ANDROID_ROOT. For instance, to run a test with Optimizing in 64b:

cd art/test
./run-test --android-root $ART_TEST_ANDROID_ROOT --64 --optimizing <test>

You can also use the usual make targets (make sure that ART_TEST_ANDROID_ROOT is exported), to avoid syncing the custom root every time define ART_TEST_NO_SYNC, for instance:

export ART_TEST_NO_SYNC=true
m test-art-target-run-test-optimizing

ART/CustomRoot (last modified 2016-09-01 16:30:37)