Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Unified Diff: third_party/android/testrunner/run_command.py

Issue 8322008: Upstream: Test script library from Android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add a way to checkout specific version Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/android/testrunner/logger.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/android/testrunner/run_command.py
diff --git a/third_party/android/testrunner/run_command.py b/third_party/android/testrunner/run_command.py
new file mode 100644
index 0000000000000000000000000000000000000000..d398daa283b10ffe5baeadde29574d320ca72ce6
--- /dev/null
+++ b/third_party/android/testrunner/run_command.py
@@ -0,0 +1,196 @@
+#!/usr/bin/python2.4
+#
+#
+# Copyright 2007, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# System imports
+import os
+import signal
+import subprocess
+import threading
+import time
+
+# local imports
+import errors
+import logger
+
+_abort_on_error = False
+
+def SetAbortOnError(abort=True):
+ """Sets behavior of RunCommand to throw AbortError if command process returns
+ a negative error code"""
+ global _abort_on_error
+ _abort_on_error = abort
+
+def RunCommand(cmd, timeout_time=None, retry_count=3, return_output=True,
+ stdin_input=None):
+ """Spawn and retry a subprocess to run the given shell command.
+
+ Args:
+ cmd: shell command to run
+ timeout_time: time in seconds to wait for command to run before aborting.
+ retry_count: number of times to retry command
+ return_output: if True return output of command as string. Otherwise,
+ direct output of command to stdout.
+ stdin_input: data to feed to stdin
+ Returns:
+ output of command
+ """
+ result = None
+ while True:
+ try:
+ result = RunOnce(cmd, timeout_time=timeout_time,
+ return_output=return_output, stdin_input=stdin_input)
+ except errors.WaitForResponseTimedOutError:
+ if retry_count == 0:
+ raise
+ retry_count -= 1
+ logger.Log("No response for %s, retrying" % cmd)
+ else:
+ # Success
+ return result
+
+def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None):
+ """Spawns a subprocess to run the given shell command.
+
+ Args:
+ cmd: shell command to run
+ timeout_time: time in seconds to wait for command to run before aborting.
+ return_output: if True return output of command as string. Otherwise,
+ direct output of command to stdout.
+ stdin_input: data to feed to stdin
+ Returns:
+ output of command
+ Raises:
+ errors.WaitForResponseTimedOutError if command did not complete within
+ timeout_time seconds.
+ errors.AbortError is command returned error code and SetAbortOnError is on.
+ """
+ start_time = time.time()
+ so = []
+ pid = []
+ global _abort_on_error, error_occurred
+ error_occurred = False
+
+ def Run():
+ global error_occurred
+ if return_output:
+ output_dest = subprocess.PIPE
+ else:
+ # None means direct to stdout
+ output_dest = None
+ if stdin_input:
+ stdin_dest = subprocess.PIPE
+ else:
+ stdin_dest = None
+ pipe = subprocess.Popen(
+ cmd,
+ executable='/bin/bash',
+ stdin=stdin_dest,
+ stdout=output_dest,
+ stderr=subprocess.STDOUT,
+ shell=True)
+ pid.append(pipe.pid)
+ try:
+ output = pipe.communicate(input=stdin_input)[0]
+ if output is not None and len(output) > 0:
+ so.append(output)
+ except OSError, e:
+ logger.SilentLog("failed to retrieve stdout from: %s" % cmd)
+ logger.Log(e)
+ so.append("ERROR")
+ error_occurred = True
+ if pipe.returncode:
+ logger.SilentLog("Error: %s returned %d error code" %(cmd,
+ pipe.returncode))
+ error_occurred = True
+
+ t = threading.Thread(target=Run)
+ t.start()
+
+ break_loop = False
+ while not break_loop:
+ if not t.isAlive():
+ break_loop = True
+
+ # Check the timeout
+ if (not break_loop and timeout_time is not None
+ and time.time() > start_time + timeout_time):
+ try:
+ os.kill(pid[0], signal.SIGKILL)
+ except OSError:
+ # process already dead. No action required.
+ pass
+
+ logger.SilentLog("about to raise a timeout for: %s" % cmd)
+ raise errors.WaitForResponseTimedOutError
+ if not break_loop:
+ time.sleep(0.1)
+
+ t.join()
+ output = "".join(so)
+ if _abort_on_error and error_occurred:
+ raise errors.AbortError(msg=output)
+
+ return "".join(so)
+
+
+def RunHostCommand(binary, valgrind=False):
+ """Run a command on the host (opt using valgrind).
+
+ Runs the host binary and returns the exit code.
+ If successfull, the output (stdout and stderr) are discarded,
+ but printed in case of error.
+ The command can be run under valgrind in which case all the
+ output are always discarded.
+
+ Args:
+ binary: full path of the file to be run.
+ valgrind: If True the command will be run under valgrind.
+
+ Returns:
+ The command exit code (int)
+ """
+ if not valgrind:
+ subproc = subprocess.Popen(binary, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ subproc.wait()
+ if subproc.returncode != 0: # In case of error print the output
+ print subproc.communicate()[0]
+ return subproc.returncode
+ else:
+ # Need the full path to valgrind to avoid other versions on the system.
+ subproc = subprocess.Popen(["/usr/bin/valgrind", "--tool=memcheck",
+ "--leak-check=yes", "-q", binary],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ # Cannot rely on the retcode of valgrind. Instead look for an empty output.
+ valgrind_out = subproc.communicate()[0].strip()
+ if valgrind_out:
+ print valgrind_out
+ return 1
+ else:
+ return 0
+
+
+def HasValgrind():
+ """Check that /usr/bin/valgrind exists.
+
+ We look for the fullpath to avoid picking up 'alternative' valgrind
+ on the system.
+
+ Returns:
+ True if a system valgrind was found.
+ """
+ return os.path.exists("/usr/bin/valgrind")
« no previous file with comments | « third_party/android/testrunner/logger.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698