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