1d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#!/usr/bin/env python
2d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#
369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org# Copyright 2012 the V8 project authors. All rights reserved.
4192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# Redistribution and use in source and binary forms, with or without
5770963f23f4fc313db0fa3bac18b1b8aafb55f17robertphillips@google.com# modification, are permitted provided that the following conditions are
6192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# met:
7d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#
8d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#     * Redistributions of source code must retain the above copyright
9192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org#       notice, this list of conditions and the following disclaimer.
10d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#     * Redistributions in binary form must reproduce the above
11d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#       copyright notice, this list of conditions and the following
12d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#       disclaimer in the documentation and/or other materials provided
13d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#       with the distribution.
14d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#     * Neither the name of Google Inc. nor the names of its
15e4d3e605f74a23d050abad29909af421d8b1cf1amtklein#       contributors may be used to endorse or promote products derived
16e4d3e605f74a23d050abad29909af421d8b1cf1amtklein#       from this software without specific prior written permission.
17e4d3e605f74a23d050abad29909af421d8b1cf1amtklein#
18e4d3e605f74a23d050abad29909af421d8b1cf1amtklein# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19e4d3e605f74a23d050abad29909af421d8b1cf1amtklein# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20e4d3e605f74a23d050abad29909af421d8b1cf1amtklein# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21e4d3e605f74a23d050abad29909af421d8b1cf1amtklein# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22e4d3e605f74a23d050abad29909af421d8b1cf1amtklein# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265fb2ce38b3dcb8e60e9e112df23c9d42456d7069commit-bot@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org
3084b18c7e3e042bf206e1ace3d1b6ea5bb929fe51robertphillips@google.com# This script executes the passed command line on Android device
31192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# using 'adb shell' command. Unfortunately, 'adb shell' always
32192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# returns exit code 0, ignoring the exit code of executed command.
33266420722e18dcc8b6d4a7379a42b8591ccd2b6dcommit-bot@chromium.org# Since we need to return non-zero exit code if the command failed,
3438aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org# we augment the passed command line with exit code checking statement
35192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# and output special error string in case of non-zero exit code.
36192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org# Then we parse the output of 'adb shell' and look for that error string.
37192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org
38266420722e18dcc8b6d4a7379a42b8591ccd2b6dcommit-bot@chromium.orgimport os
39266420722e18dcc8b6d4a7379a42b8591ccd2b6dcommit-bot@chromium.orgfrom os.path import join, dirname, abspath
4090b5a2a653b312ff9bcd7102412da2dbeb52368ccommit-bot@chromium.orgimport subprocess
4190b5a2a653b312ff9bcd7102412da2dbeb52368ccommit-bot@chromium.orgimport sys
42192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.orgimport tempfile
43192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org
44192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.orgdef Check(output, errors):
45192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org  failed = any([s.startswith('/system/bin/sh:') or s.startswith('ANDROID')
469b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips                for s in output.split('\n')])
47192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org  return 1 if failed else 0
48192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org
49192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.orgdef Execute(cmdline):
5069031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  (fd_out, outname) = tempfile.mkstemp()
5169031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  (fd_err, errname) = tempfile.mkstemp()
5269031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  process = subprocess.Popen(
5369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    args=cmdline,
5469031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    shell=True,
5569031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    stdout=fd_out,
5669031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    stderr=fd_err,
5769031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  )
5869031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  exit_code = process.wait()
5969031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  os.close(fd_out)
6069031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  os.close(fd_err)
6169031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  output = file(outname).read()
6269031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  errors = file(errname).read()
6369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  os.unlink(outname)
6469031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  os.unlink(errname)
6569031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  sys.stdout.write(output)
6669031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  sys.stderr.write(errors)
6769031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  return exit_code or Check(output, errors)
68192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org
6969031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.orgdef Escape(arg):
7069031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  def ShouldEscape():
7169031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    for x in arg:
7269031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org      if not x.isalnum() and x != '-' and x != '_':
7369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org        return True
7469031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    return False
7569031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org
7669031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  return arg if not ShouldEscape() else '"%s"' % (arg.replace('"', '\\"'))
7769031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org
7869031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.orgdef WriteToTemporaryFile(data):
7969031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  (fd, fname) = tempfile.mkstemp()
8069031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  os.close(fd)
8169031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  tmp_file = open(fname, "w")
8269031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  tmp_file.write(data)
8369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  tmp_file.close()
8469031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  return fname
8569031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org
8669031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.orgdef Main():
8769031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  if (len(sys.argv) == 1):
8869031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    print("Usage: %s <command-to-run-on-device>" % sys.argv[0])
8969031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org    return 1
9069031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  workspace = abspath(join(dirname(sys.argv[0]), '..'))
9169031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  android_workspace = os.getenv("ANDROID_V8", "/data/local/tmp/v8")
9269031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  args = [Escape(arg) for arg in sys.argv[1:]]
9369031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org  script = (" ".join(args) + "\n"
9469031a44273ccb7656df88c6bcb7b62f4d2731bbcommit-bot@chromium.org            "case $? in\n"
959c4ff80d9b76e1bda532fb9182f66f67cfc95324mtklein            "  0) ;;\n"
969c4ff80d9b76e1bda532fb9182f66f67cfc95324mtklein            "  *) echo \"ANDROID: Error returned by test\";;\n"
979c4ff80d9b76e1bda532fb9182f66f67cfc95324mtklein            "esac\n")
989c4ff80d9b76e1bda532fb9182f66f67cfc95324mtklein  script = script.replace(workspace, android_workspace)
999c4ff80d9b76e1bda532fb9182f66f67cfc95324mtklein  script_file = WriteToTemporaryFile(script)
100192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org  android_script_file = android_workspace + "/" + script_file
101192cbf67b281b20477320134962d554ed823c691commit-bot@chromium.org  command =  ("adb push '%s' %s;" % (script_file, android_script_file) +
102d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com              "adb shell 'sh %s';" % android_script_file +
103              "adb shell 'rm %s'" % android_script_file)
104  error_code = Execute(command)
105  os.unlink(script_file)
106  return error_code
107
108if __name__ == '__main__':
109  sys.exit(Main())
110