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

Unified Diff: test/lib/TestGyp.py

Issue 321953005: [gyp][Android] Implement TestGypAndroid.run_built_executable. (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: Created 6 years, 6 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 | « test/configurations/inheritance/gyptest-inheritance.py ('k') | test/library/gyptest-shared.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/lib/TestGyp.py
diff --git a/test/lib/TestGyp.py b/test/lib/TestGyp.py
index 119417d1c2b0c18197f3131723468fb301758382..3cea15e7bfcf0c52dc30654c08583775f95260db 100644
--- a/test/lib/TestGyp.py
+++ b/test/lib/TestGyp.py
@@ -409,10 +409,6 @@ class TestGypAndroid(TestGypBase):
"""
Subclass for testing the GYP Android makefile generator. Note that
build/envsetup.sh and lunch must have been run before running tests.
-
- TODO: This is currently an incomplete implementation. We do not support
- run_built_executable(), so we pass only tests which do not use this. As a
- result, support for host targets is not properly tested.
"""
format = 'android'
@@ -455,6 +451,20 @@ class TestGypAndroid(TestGypBase):
os.remove(os.path.join(out_dir, x, d))
super(TestGypAndroid, self).__init__(*args, **kw)
+ self._adb_path = os.path.join(os.environ['ANDROID_HOST_OUT'], 'bin', 'adb')
+ self._device_serial = None
+ adb_devices_out = self._call_adb(['devices'])
+ devices = [l.split()[0] for l in adb_devices_out.splitlines()[1:-1]
+ if l.split()[1] == 'device']
+ if len(devices) == 0:
+ self._device_serial = None
+ else:
+ if len(devices) > 1:
+ self._device_serial = random.choice(devices)
+ else:
+ self._device_serial = devices[0]
+ self._call_adb(['root'])
+ self._to_install = set()
def target_name(self, target):
if target == self.ALL:
@@ -465,6 +475,8 @@ class TestGypAndroid(TestGypBase):
return self.ALL
return target
+ _INSTALLABLE_PREFIX = 'Install: '
+
def build(self, gyp_file, target=None, **kw):
"""
Runs a build using the Android makefiles generated from the specified
@@ -479,6 +491,11 @@ class TestGypAndroid(TestGypBase):
makefile = os.path.join(self.workdir, chdir, 'GypAndroid.mk')
os.environ['ONE_SHOT_MAKEFILE'] = makefile
result = self.run(program=self.build_tool, **kw)
+ for l in self.stdout().splitlines():
+ if l.startswith(TestGypAndroid._INSTALLABLE_PREFIX):
+ self._to_install.add(os.path.abspath(os.path.join(
+ os.environ['ANDROID_BUILD_TOP'],
+ l[len(TestGypAndroid._INSTALLABLE_PREFIX):])))
del os.environ['ONE_SHOT_MAKEFILE']
return result
@@ -501,15 +518,10 @@ class TestGypAndroid(TestGypBase):
"""
# Built files are in $ANDROID_PRODUCT_OUT. This requires copying logic from
# the Android build system.
- if type == None:
+ if type == None or type == self.EXECUTABLE:
return os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'obj', 'GYP',
'shared_intermediates', name)
subdir = kw.get('subdir')
- if type == self.EXECUTABLE:
- # We don't install executables
- group = 'EXECUTABLES'
- module_name = self.android_module(group, name, subdir)
- return os.path.join(self.intermediates_dir(group, module_name), name)
if type == self.STATIC_LIB:
group = 'STATIC_LIBRARIES'
module_name = self.android_module(group, name, subdir)
@@ -522,23 +534,98 @@ class TestGypAndroid(TestGypBase):
'%s.so' % module_name)
assert False, 'Unhandled type'
+ def _adb_failure(self, command, msg, stdout, stderr):
+ """ Reports a failed adb command and fails the containing test.
+
+ Args:
+ command: The adb command that failed.
+ msg: The error description.
+ stdout: The standard output.
+ stderr: The standard error.
+ """
+ print '%s failed%s' % (' '.join(command), ': %s' % msg if msg else '')
+ print self.banner('STDOUT ')
+ stdout.seek(0)
+ print stdout.read()
+ print self.banner('STDERR ')
+ stderr.seek(0)
+ print stderr.read()
+ self.fail_test()
+
+ def _call_adb(self, command):
+ """ Calls the provided adb command.
+
+ If the command fails, the test fails.
+
+ Args:
+ command: The adb command to call.
+ Returns:
+ The command's output.
+ """
+ with tempfile.TemporaryFile(bufsize=0) as adb_out:
+ with tempfile.TemporaryFile(bufsize=0) as adb_err:
+ adb_command = [self._adb_path]
+ if self._device_serial:
+ adb_command += ['-s', self._device_serial]
+ is_shell = (command[0] == 'shell')
+ if is_shell:
+ command = [command[0], '%s; echo "\n$?";' % ' '.join(command[1:])]
+ adb_command += command
+ if subprocess.call(adb_command, stdout=adb_out, stderr=adb_err) != 0:
+ self._adb_failure(adb_command, None, adb_out, adb_err)
+ else:
+ adb_out.seek(0)
+ output = adb_out.read()
+ if is_shell:
+ output = output.splitlines(True)
+ try:
+ output[-2] = output[-2].rstrip('\r\n')
+ output, rc = (''.join(output[:-1]), int(output[-1]))
+ except ValueError:
+ self._adb_failure(adb_command, 'unexpected output format',
+ adb_out, adb_err)
+ if rc != 0:
+ self._adb_failure(adb_command, 'exited with %d' % rc, adb_out,
+ adb_err)
+ return output
+
def run_built_executable(self, name, *args, **kw):
"""
Runs an executable program built from a gyp-generated configuration.
-
- This is not correctly implemented for Android. For now, we simply check
- that the executable file exists.
"""
- # Running executables requires a device. Even if we build for target x86,
- # the binary is not built with the correct toolchain options to actually
- # run on the host.
-
- # Copied from TestCommon.run()
match = kw.pop('match', self.match)
- status = None
- if os.path.exists(self.built_file_path(name)):
- status = 1
- self._complete(None, None, None, None, status, match)
+
+ executable_file = self.built_file_path(name, type=self.EXECUTABLE, **kw)
+ if executable_file not in self._to_install:
+ self.fail_test()
+
+ if not self._device_serial:
+ self.skip_test(message='No devices attached.\n')
+
+ storage = self._call_adb(['shell', 'echo', '$ANDROID_DATA']).strip()
+ if not len(storage):
+ self.fail_test()
+
+ installed = set()
+ try:
+ for i in self._to_install:
+ a = os.path.abspath(
+ os.path.join(os.environ['ANDROID_BUILD_TOP'], i))
+ dest = '%s/%s' % (storage, os.path.basename(a))
+ self._call_adb(['push', os.path.abspath(a), dest])
+ installed.add(dest)
+ if i == executable_file:
+ device_executable = dest
+ self._call_adb(['shell', 'chmod', '755', device_executable])
+
+ out = self._call_adb(
+ ['shell', 'LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%s' % storage,
+ device_executable])
+ out = out.replace('\r\n', '\n')
+ self._complete(out, kw.pop('stdout', None), None, None, None, match)
+ finally:
+ if len(installed):
+ self._call_adb(['shell', 'rm'] + list(installed))
def match_single_line(self, lines = None, expected_line = None):
"""
« no previous file with comments | « test/configurations/inheritance/gyptest-inheritance.py ('k') | test/library/gyptest-shared.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698