From 1d9928aaf7ce454f30824a804c9f1f04cc778d28 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Tue, 29 Sep 2009 15:14:05 -0700 Subject: [PATCH] Import testrunner changes from puppetmaster to keep them in sync. --- testrunner/android_manifest.py | 46 ++++++++++++++++++++++++++++------ testrunner/run_command.py | 45 +++++++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/testrunner/android_manifest.py b/testrunner/android_manifest.py index 7ede96c58..5406f56ee 100644 --- a/testrunner/android_manifest.py +++ b/testrunner/android_manifest.py @@ -22,6 +22,7 @@ http://developer.android.com/guide/topics/manifest/manifest-intro.html """ # python imports +import os import xml.dom.minidom import xml.parsers @@ -29,7 +30,7 @@ import xml.parsers class AndroidManifest(object): """In memory representation of AndroidManifest.xml file.""" - FILENAME = "AndroidManifest.xml" + FILENAME = 'AndroidManifest.xml' def __init__(self, app_path=None): if app_path: @@ -41,10 +42,10 @@ class AndroidManifest(object): Returns: Package name if defined, otherwise None """ - manifests = self._dom.getElementsByTagName("manifest") - if not manifests or not manifests[0].getAttribute("package"): + manifest = self._GetManifestElement() + if not manifest or not manifest.hasAttribute('package'): return None - return manifests[0].getAttribute("package") + return manifest.getAttribute('package') def ParseManifest(self, app_path): """Parse AndroidManifest.xml at the specified path. @@ -55,6 +56,37 @@ class AndroidManifest(object): IOError: AndroidManifest.xml cannot be found at given path, or cannot be opened for reading """ - self.app_path = app_path.rstrip("/") - self.manifest_path = "%s/%s" % (self.app_path, self.FILENAME) - self._dom = xml.dom.minidom.parse(self.manifest_path) + self._manifest_path = os.path.join(app_path, self.FILENAME) + self._dom = xml.dom.minidom.parse(self._manifest_path) + + def AddUsesSdk(self, min_sdk_version): + """Adds a uses-sdk element to manifest. + + Args: + min_sdk_version: value to provide for minSdkVersion attribute. + """ + manifest = self._GetManifestElement() + uses_sdk_elements = manifest.getElementsByTagName('uses-sdk') + if uses_sdk_elements: + uses_sdk_element = uses_sdk_elements[0] + else: + uses_sdk_element = self._dom.createElement('uses-sdk') + manifest.appendChild(uses_sdk_element) + + uses_sdk_element.setAttribute('android:minSdkVersion', min_sdk_version) + self._SaveXml() + + def _GetManifestElement(self): + """Retrieve the root manifest element. + + Returns: + the DOM element for manifest or None. + """ + manifests = self._dom.getElementsByTagName('manifest') + if not manifests: + return None + return manifests[0] + + def _SaveXml(self): + """Saves the manifest to disk.""" + self._dom.writexml(open(self._manifest_path, mode='w'), encoding='utf-8') diff --git a/testrunner/run_command.py b/testrunner/run_command.py index c522e000f..926cc6b77 100755 --- a/testrunner/run_command.py +++ b/testrunner/run_command.py @@ -34,16 +34,25 @@ def SetAbortOnError(abort=True): global _abort_on_error _abort_on_error = abort -def RunCommand(cmd, timeout_time=None, retry_count=3, return_output=True): - """Spawns a subprocess to run the given shell command, and checks for - timeout_time. If return_output is True, the output of the command is returned - as a string. Otherwise, output of command directed to stdout """ +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) + return_output=return_output, stdin_input=stdin_input) except errors.WaitForResponseTimedOutError: if retry_count == 0: raise @@ -53,7 +62,22 @@ def RunCommand(cmd, timeout_time=None, retry_count=3, return_output=True): # Success return result -def RunOnce(cmd, timeout_time=None, return_output=True): +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 = [] @@ -67,15 +91,20 @@ def RunOnce(cmd, timeout_time=None, return_output=True): 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()[0] + output = pipe.communicate(input=stdin_input)[0] if output is not None and len(output) > 0: so.append(output) except OSError, e: @@ -84,7 +113,7 @@ def RunOnce(cmd, timeout_time=None, return_output=True): so.append("ERROR") error_occurred = True if pipe.returncode != 0: - logger.SilentLog("Error: %s returned %s error code" %(cmd, + logger.SilentLog("Error: %s returned %d error code" %(cmd, pipe.returncode)) error_occurred = True