1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#!/usr/bin/env python 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Copyright 2012 the V8 project authors. All rights reserved. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Redistribution and use in source and binary forms, with or without 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# modification, are permitted provided that the following conditions are 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# met: 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Redistributions of source code must retain the above copyright 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# notice, this list of conditions and the following disclaimer. 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Redistributions in binary form must reproduce the above 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# copyright notice, this list of conditions and the following 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# disclaimer in the documentation and/or other materials provided 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# with the distribution. 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# * Neither the name of Google Inc. nor the names of its 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# contributors may be used to endorse or promote products derived 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# from this software without specific prior written permission. 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# This script executes the passed command line on Android device 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# using 'adb shell' command. Unfortunately, 'adb shell' always 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# returns exit code 0, ignoring the exit code of executed command. 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Since we need to return non-zero exit code if the command failed, 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# we augment the passed command line with exit code checking statement 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# and output special error string in case of non-zero exit code. 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch# Then we parse the output of 'adb shell' and look for that error string. 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport os 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfrom os.path import join, dirname, abspath 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport subprocess 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport sys 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochimport tempfile 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Check(output, errors): 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch failed = any([s.startswith('/system/bin/sh:') or s.startswith('ANDROID') 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for s in output.split('\n')]) 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 if failed else 0 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Execute(cmdline): 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (fd_out, outname) = tempfile.mkstemp() 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (fd_err, errname) = tempfile.mkstemp() 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch process = subprocess.Popen( 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch args=cmdline, 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shell=True, 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stdout=fd_out, 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stderr=fd_err, 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ) 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch exit_code = process.wait() 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.close(fd_out) 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.close(fd_err) 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch output = file(outname).read() 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch errors = file(errname).read() 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.unlink(outname) 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.unlink(errname) 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.stdout.write(output) 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.stderr.write(errors) 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return exit_code or Check(output, errors) 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Escape(arg): 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch def ShouldEscape(): 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for x in arg: 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if not x.isalnum() and x != '-' and x != '_': 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return True 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return False 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return arg if not ShouldEscape() else '"%s"' % (arg.replace('"', '\\"')) 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef WriteToTemporaryFile(data): 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (fd, fname) = tempfile.mkstemp() 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.close(fd) 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp_file = open(fname, "w") 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp_file.write(data) 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tmp_file.close() 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fname 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdef Main(): 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (len(sys.argv) == 1): 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print("Usage: %s <command-to-run-on-device>" % sys.argv[0]) 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 1 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch workspace = abspath(join(dirname(sys.argv[0]), '..')) 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch android_workspace = os.getenv("ANDROID_V8", "/data/local/tmp/v8") 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch args = [Escape(arg) for arg in sys.argv[1:]] 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch script = (" ".join(args) + "\n" 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "case $? in\n" 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " 0) ;;\n" 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch " *) echo \"ANDROID: Error returned by test\";;\n" 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "esac\n") 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch script = script.replace(workspace, android_workspace) 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch script_file = WriteToTemporaryFile(script) 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch android_script_file = android_workspace + "/" + script_file 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch command = ("adb push '%s' %s;" % (script_file, android_script_file) + 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "adb shell 'sh %s';" % android_script_file + 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "adb shell 'rm %s'" % android_script_file) 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch error_code = Execute(command) 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os.unlink(script_file) 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return error_code 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochif __name__ == '__main__': 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sys.exit(Main()) 110