Revision: 11975
Author: [email protected]
Date: Tue Jul 3 00:45:58 2012
Log: Add Makefile targets for running tests on Android.
This allows to run tests on the attached Android device using
make android.check
make android.debug.check
make android.release.check
ANDROID_V8=/data/local/v8 TESTJOBS=-j4 make android.release.check -j10
Tests and binaries are copied to device location specified by the ANDROID_V8
variable and then tests are executed using the 'adb shell' program.
[email protected]
Review URL: https://chromiumcodereview.appspot.com/10696048
http://code.google.com/p/v8/source/detail?r=11975
Added:
/branches/bleeding_edge/tools/android-run.py
/branches/bleeding_edge/tools/android-sync.sh
Modified:
/branches/bleeding_edge/Makefile
/branches/bleeding_edge/test/cctest/cctest.status
/branches/bleeding_edge/test/cctest/testcfg.py
/branches/bleeding_edge/test/mjsunit/mjsunit.status
/branches/bleeding_edge/tools/test-wrapper-gypbuild.py
/branches/bleeding_edge/tools/test.py
=======================================
--- /dev/null
+++ /branches/bleeding_edge/tools/android-run.py Tue Jul 3 00:45:58 2012
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+#
+# Copyright 2012 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This script executes the passed command line on Android device
+# using 'adb shell' command. Unfortunately, 'adb shell' always
+# returns exit code 0, ignoring the exit code of executed command.
+# Since we need to return non-zero exit code if the command failed,
+# we augment the passed command line with exit code checking statement
+# and output special error string in case of non-zero exit code.
+# Then we parse the output of 'adb shell' and look for that error string.
+
+import os
+from os.path import join, dirname, abspath
+import subprocess
+import sys
+import tempfile
+
+def Check(output, errors):
+ failed = any([s.startswith('/system/bin/sh:') or s.startswith('Error')
+ for s in output.split('\n')])
+ return 1 if failed else 0
+
+def Execute(cmdline):
+ (fd_out, outname) = tempfile.mkstemp()
+ (fd_err, errname) = tempfile.mkstemp()
+ process = subprocess.Popen(
+ args=cmdline,
+ shell=True,
+ stdout=fd_out,
+ stderr=fd_err,
+ )
+ exit_code = process.wait()
+ os.close(fd_out)
+ os.close(fd_err)
+ output = file(outname).read()
+ errors = file(errname).read()
+ os.unlink(outname)
+ os.unlink(errname)
+ sys.stdout.write(output)
+ sys.stderr.write(errors)
+ return exit_code or Check(output, errors)
+
+def Escape(arg):
+ def ShouldEscape():
+ for x in arg:
+ if not x.isalnum() and x != '-' and x != '_':
+ return True
+ return False
+
+ return arg if not ShouldEscape() else '"%s"' % (arg.replace('"', '\\"'))
+
+def WriteToTemporaryFile(data):
+ (fd, fname) = tempfile.mkstemp()
+ os.close(fd)
+ tmp_file = open(fname, "w")
+ tmp_file.write(data)
+ tmp_file.close()
+ return fname
+
+def Main():
+ if (len(sys.argv) == 1):
+ print("Usage: %s <command-to-run-on-device>" % sys.argv[0])
+ return 1
+ workspace = abspath(join(dirname(sys.argv[0]), '..'))
+ android_workspace = os.getenv("ANDROID_V8", "/data/local/v8")
+ args = [Escape(arg) for arg in sys.argv[1:]]
+ script = (" ".join(args) + "\n"
+ "if [ $? -ne 0 ]\n"
+ " then echo \"Error returned by test\";\n"
+ "fi\n")
+ script = script.replace(workspace, android_workspace)
+ script_file = WriteToTemporaryFile(script)
+ android_script_file = android_workspace + "/" + script_file
+ command = ("adb push '%s' %s;" % (script_file, android_script_file) +
+ "adb shell 'sh %s';" % android_script_file +
+ "adb shell 'rm %s'" % android_script_file)
+ error_code = Execute(command)
+ os.unlink(script_file)
+ return error_code
+
+if __name__ == '__main__':
+ sys.exit(Main())
=======================================
--- /dev/null
+++ /branches/bleeding_edge/tools/android-sync.sh Tue Jul 3 00:45:58 2012
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright 2012 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This script pushes android binaries and test data to the device.
+# The first argument can be either "android.release" or "android.debug".
+# The second argument is a relative path to the output directory with
binaries.
+# The third argument is the absolute path to the V8 directory on the host.
+# The fourth argument is the absolute path to the V8 directory on the
device.
+
+if [ ${#@} -lt 4 ] ; then
+ echo "Error: need 4 arguments"
+ exit 1
+fi
+
+ARCH_MODE=$1
+OUTDIR=$2
+HOST_V8=$3
+ANDROID_V8=$4
+
+function sync_file {
+ local FILE=$1
+ local ANDROID_HASH=$(adb shell "md5 \"$ANDROID_V8/$FILE\"")
+ local HOST_HASH=$(md5sum "$HOST_V8/$FILE")
+ if [ "${ANDROID_HASH%% *}" != "${HOST_HASH%% *}" ]; then
+ adb push "$HOST_V8/$FILE" "$ANDROID_V8/$FILE" &> /dev/null
+ fi
+ echo -n "."
+}
+
+function sync_dir {
+ local DIR=$1
+ echo -n "sync to $ANDROID_V8/$DIR"
+ for FILE in $(find "$HOST_V8/$DIR" -type f); do
+ local RELATIVE_FILE=${FILE:${#HOST_V8}}
+ sync_file "$RELATIVE_FILE"
+ done
+ echo ""
+}
+
+echo -n "sync to $ANDROID_V8/$OUTDIR/$ARCH_MODE"
+sync_file "$OUTDIR/$ARCH_MODE/cctest"
+sync_file "$OUTDIR/$ARCH_MODE/d8"
+sync_file "$OUTDIR/$ARCH_MODE/preparser"
+echo ""
+echo -n "sync to $ANDROID_V8/tools"
+sync_file tools/consarray.js
+sync_file tools/codemap.js
+sync_file tools/csvparser.js
+sync_file tools/profile.js
+sync_file tools/splaytree.js
+echo ""
+sync_dir test/message
+sync_dir test/mjsunit
+sync_dir test/preparser
=======================================
--- /branches/bleeding_edge/Makefile Thu Jun 14 01:01:05 2012
+++ /branches/bleeding_edge/Makefile Tue Jul 3 00:45:58 2012
@@ -35,6 +35,7 @@
TESTFLAGS ?=
ANDROID_NDK_ROOT ?=
ANDROID_TOOL_PREFIX =
$(ANDROID_NDK_ROOT)/toolchain/bin/arm-linux-androideabi
+ANDROID_V8 ?= /data/local/v8
# Special build flags. Use them like this: "make library=shared"
@@ -107,7 +108,7 @@
# - every combination <arch>.<mode>, e.g. "ia32.release"
# - "native": current host's architecture, release mode
# - any of the above with .check appended, e.g. "ia32.release.check"
-# - "android": cross-compile for Android/ARM (release mode)
+# - "android": cross-compile for Android/ARM
# - default (no target specified): build all DEFAULT_ARCHES and MODES
# - "check": build all targets and run all tests
# - "<arch>.clean" for any <arch> in ARCHES
@@ -120,6 +121,7 @@
ARCHES = ia32 x64 arm mips
DEFAULT_ARCHES = ia32 x64 arm
MODES = release debug
+ANDROID_MODES = android.release android.debug
# List of files that trigger Makefile regeneration:
GYPFILES = build/all.gyp build/common.gypi build/standalone.gypi \
@@ -166,8 +168,9 @@
CXX="$(CXX)" LINK="$(LINK)" BUILDTYPE=Release \
builddir="$(shell pwd)/$(OUTDIR)/$@"
-# TODO(jkummerow): add "android.debug" when we need it.
-android android.release: $(OUTDIR)/Makefile.android
+android: $(ANDROID_MODES)
+
+$(ANDROID_MODES): $(OUTDIR)/Makefile.android
@$(MAKE) -C "$(OUTDIR)" -f Makefile.android \
CXX="$(ANDROID_TOOL_PREFIX)-g++" \
AR="$(ANDROID_TOOL_PREFIX)-ar" \
@@ -175,8 +178,9 @@
CC="$(ANDROID_TOOL_PREFIX)-gcc" \
LD="$(ANDROID_TOOL_PREFIX)-ld" \
LINK="$(ANDROID_TOOL_PREFIX)-g++" \
- BUILDTYPE=Release \
- builddir="$(shell pwd)/$(OUTDIR)/android.release"
+ BUILDTYPE=$(shell echo $(subst .,,$(suffix $@)) | \
+ python -c "print raw_input().capitalize()") \
+ builddir="$(shell pwd)/$(OUTDIR)/$@"
# Test targets.
check: all
@@ -196,6 +200,17 @@
@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \
--arch-and-mode=$(basename $@) $(TESTFLAGS)
+$(addsuffix .sync, $(ANDROID_MODES)): $$(basename $$@)
+ @tools/android-sync.sh $(basename $@) $(OUTDIR) \
+ $(shell pwd) $(ANDROID_V8)
+
+$(addsuffix .check, $(ANDROID_MODES)): $$(basename $$@).sync
+ @tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR) \
+ --arch-and-mode=$(basename $@) \
+ --special-command="tools/android-run.py @"
+
+android.check: android.release.check android.debug.check
+
native.check: native
@tools/test-wrapper-gypbuild.py $(TESTJOBS) --outdir=$(OUTDIR)/native \
--arch-and-mode=. $(TESTFLAGS)
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.status Fri Jun 8 07:47:12
2012
+++ /branches/bleeding_edge/test/cctest/cctest.status Tue Jul 3 00:45:58
2012
@@ -54,7 +54,7 @@
test-weakmaps/Shrinking: FAIL
##############################################################################
-[ $arch == arm ]
+[ $arch == arm || $arch == android ]
# We cannot assume that we can throw OutOfMemory exceptions in all
situations.
# Apparently our ARM box is in such a state. Skip the test as it also runs
for
=======================================
--- /branches/bleeding_edge/test/cctest/testcfg.py Fri May 11 05:18:09 2012
+++ /branches/bleeding_edge/test/cctest/testcfg.py Tue Jul 3 00:45:58 2012
@@ -93,7 +93,8 @@
if utils.IsWindows():
executable += '.exe'
executable = join(self.context.buildspace, executable)
- output = test.Execute([executable, '--list'], self.context)
+ full_command = self.context.processor([executable, '--list'])
+ output = test.Execute(full_command, self.context)
if output.exit_code != 0:
print output.stdout
print output.stderr
=======================================
--- /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Jun 26 00:48:04
2012
+++ /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Jul 3 00:45:58
2012
@@ -49,28 +49,27 @@
##############################################################################
# This one uses a built-in that's only present in debug mode. It takes
# too long to run in debug mode on ARM and MIPS.
-fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm || $arch ==
mips)
-
-big-object-literal: PASS, SKIP if ($arch == arm)
+fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm || $arch ==
android || $arch == mips)
+
+big-object-literal: PASS, SKIP if ($arch == arm || $arch == android)
# Issue 488: this test sometimes times out.
array-constructor: PASS || TIMEOUT
# Very slow on ARM and MIPS, contains no architecture dependent code.
-unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch ==
mips)
+unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch ==
android || $arch == mips)
# Test Crankshaft compilation time. Expected to take too long in debug
mode.
regress/regress-1969: PASS, SKIP if $mode == debug
##############################################################################
-[ $isolates ]
-
# This test sets the umask on a per-process basis and hence cannot be
# used in multi-threaded runs.
-d8-os: SKIP
+# On android there is no /tmp directory.
+d8-os: PASS, SKIP if ($isolates || $arch == android)
##############################################################################
-[ $arch == arm ]
+[ $arch == arm || $arch == android ]
# Slow tests which times out in debug mode.
try: PASS, SKIP if $mode == debug
=======================================
--- /branches/bleeding_edge/tools/test-wrapper-gypbuild.py Thu Jun 28
07:31:03 2012
+++ /branches/bleeding_edge/tools/test-wrapper-gypbuild.py Tue Jul 3
00:45:58 2012
@@ -148,7 +148,7 @@
print "Unknown mode %s" % mode
return False
for arch in options.arch:
- if not arch in ['ia32', 'x64', 'arm', 'mips']:
+ if not arch in ['ia32', 'x64', 'arm', 'mips', 'android']:
print "Unknown architecture %s" % arch
return False
if options.buildbot:
=======================================
--- /branches/bleeding_edge/tools/test.py Fri Jun 8 07:47:12 2012
+++ /branches/bleeding_edge/tools/test.py Tue Jul 3 00:45:58 2012
@@ -140,9 +140,9 @@
parts = []
for part in command:
if ' ' in part:
- # Escape spaces. We may need to escape more characters for this
- # to work properly.
- parts.append('"%s"' % part)
+ # Escape spaces and double quotes. We may need to escape more
characters
+ # for this to work properly.
+ parts.append('"%s"' % part.replace('"', '\\"'))
else:
parts.append(part)
return " ".join(parts)
@@ -1283,7 +1283,7 @@
options.scons_flags.append("arch=" + options.arch)
# Simulators are slow, therefore allow a longer default timeout.
if options.timeout == -1:
- if options.arch == 'arm' or options.arch == 'mips':
+ if options.arch in ['android', 'arm', 'mips']:
options.timeout = 2 * TIMEOUT_DEFAULT;
else:
options.timeout = TIMEOUT_DEFAULT;
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev