| Index: test/lib/TestGyp.py
|
| diff --git a/test/lib/TestGyp.py b/test/lib/TestGyp.py
|
| index e085b7b9a8f074131a2f8ad962537bd8ebaa9e97..bf7afe1bbf7b9fc84ca16c9dcd66d504c578ada9 100644
|
| --- a/test/lib/TestGyp.py
|
| +++ b/test/lib/TestGyp.py
|
| @@ -10,14 +10,11 @@ import collections
|
| from contextlib import contextmanager
|
| import itertools
|
| import os
|
| -import random
|
| import re
|
| import shutil
|
| -import stat
|
| import subprocess
|
| import sys
|
| import tempfile
|
| -import time
|
|
|
| import TestCmd
|
| import TestCommon
|
| @@ -411,276 +408,6 @@ class TestGypCustom(TestGypBase):
|
| super(TestGypCustom, self).__init__(*args, **kw)
|
|
|
|
|
| -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.
|
| - """
|
| - format = 'android'
|
| -
|
| - # Note that we can't use mmm as the build tool because ...
|
| - # - it builds all targets, whereas we need to pass a target
|
| - # - it is a function, whereas the test runner assumes the build tool is a file
|
| - # Instead we use make and duplicate the logic from mmm.
|
| - build_tool_list = ['make']
|
| -
|
| - # We use our custom target 'gyp_all_modules', as opposed to the 'all_modules'
|
| - # target used by mmm, to build only those targets which are part of the gyp
|
| - # target 'all'.
|
| - ALL = 'gyp_all_modules'
|
| -
|
| - def __init__(self, gyp=None, *args, **kw):
|
| - # Android requires build and test output to be inside its source tree.
|
| - # We use the following working directory for the test's source, but the
|
| - # test's build output still goes to $ANDROID_PRODUCT_OUT.
|
| - # Note that some tests explicitly set format='gypd' to invoke the gypd
|
| - # backend. This writes to the source tree, but there's no way around this.
|
| - kw['workdir'] = os.path.join('/tmp', 'gyptest',
|
| - kw.get('workdir', 'testworkarea'))
|
| - # We need to remove all gyp outputs from out/. Ths is because some tests
|
| - # don't have rules to regenerate output, so they will simply re-use stale
|
| - # output if present. Since the test working directory gets regenerated for
|
| - # each test run, this can confuse things.
|
| - # We don't have a list of build outputs because we don't know which
|
| - # dependent targets were built. Instead we delete all gyp-generated output.
|
| - # This may be excessive, but should be safe.
|
| - out_dir = os.environ['ANDROID_PRODUCT_OUT']
|
| - obj_dir = os.path.join(out_dir, 'obj')
|
| - shutil.rmtree(os.path.join(obj_dir, 'GYP'), ignore_errors = True)
|
| - for x in ['EXECUTABLES', 'STATIC_LIBRARIES', 'SHARED_LIBRARIES']:
|
| - for d in os.listdir(os.path.join(obj_dir, x)):
|
| - if d.endswith('_gyp_intermediates'):
|
| - shutil.rmtree(os.path.join(obj_dir, x, d), ignore_errors = True)
|
| - for x in [os.path.join('obj', 'lib'), os.path.join('system', 'lib')]:
|
| - for d in os.listdir(os.path.join(out_dir, x)):
|
| - if d.endswith('_gyp.so'):
|
| - 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:
|
| - return self.ALL
|
| - # The default target is 'droid'. However, we want to use our special target
|
| - # to build only the gyp target 'all'.
|
| - if target in (None, self.DEFAULT):
|
| - 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
|
| - gyp_file. This logic is taken from Android's mmm.
|
| - """
|
| - arguments = kw.get('arguments', [])[:]
|
| - arguments.append(self.target_name(target))
|
| - arguments.append('-C')
|
| - arguments.append(os.environ['ANDROID_BUILD_TOP'])
|
| - kw['arguments'] = arguments
|
| - chdir = kw.get('chdir', '')
|
| - 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
|
| -
|
| - def android_module(self, group, name, subdir):
|
| - if subdir:
|
| - name = '%s_%s' % (subdir, name)
|
| - if group == 'SHARED_LIBRARIES':
|
| - name = 'lib_%s' % name
|
| - return '%s_gyp' % name
|
| -
|
| - def intermediates_dir(self, group, module_name):
|
| - return os.path.join(os.environ['ANDROID_PRODUCT_OUT'], 'obj', group,
|
| - '%s_intermediates' % module_name)
|
| -
|
| - def built_file_path(self, name, type=None, **kw):
|
| - """
|
| - Returns a path to the specified file name, of the specified type,
|
| - as built by Android. Note that we don't support the configuration
|
| - parameter.
|
| - """
|
| - # Built files are in $ANDROID_PRODUCT_OUT. This requires copying logic from
|
| - # the Android build system.
|
| - 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.STATIC_LIB:
|
| - group = 'STATIC_LIBRARIES'
|
| - module_name = self.android_module(group, name, subdir)
|
| - return os.path.join(self.intermediates_dir(group, module_name),
|
| - '%s.a' % module_name)
|
| - if type == self.SHARED_LIB:
|
| - group = 'SHARED_LIBRARIES'
|
| - module_name = self.android_module(group, name, subdir)
|
| - return os.path.join(self.intermediates_dir(group, module_name), 'LINKED',
|
| - '%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, timeout=15, retry=3):
|
| - """ 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
|
| -
|
| - for attempt in xrange(1, retry + 1):
|
| - adb_out.seek(0)
|
| - adb_out.truncate(0)
|
| - adb_err.seek(0)
|
| - adb_err.truncate(0)
|
| - proc = subprocess.Popen(adb_command, stdout=adb_out, stderr=adb_err)
|
| - deadline = time.time() + timeout
|
| - timed_out = False
|
| - while proc.poll() is None and not timed_out:
|
| - time.sleep(1)
|
| - timed_out = time.time() > deadline
|
| - if timed_out:
|
| - print 'Timeout for command %s (attempt %d of %s)' % (
|
| - adb_command, attempt, retry)
|
| - try:
|
| - proc.kill()
|
| - except:
|
| - pass
|
| - else:
|
| - break
|
| -
|
| - if proc.returncode != 0: # returncode is None in the case of a timeout.
|
| - self._adb_failure(
|
| - adb_command, 'retcode=%s' % proc.returncode, adb_out, adb_err)
|
| - return
|
| -
|
| - 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.
|
| - """
|
| - match = kw.pop('match', self.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],
|
| - timeout=60,
|
| - retry=1)
|
| - 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):
|
| - """
|
| - Checks that specified line appears in the text.
|
| - """
|
| - for line in lines.split('\n'):
|
| - if line == expected_line:
|
| - return 1
|
| - return
|
| -
|
| - def up_to_date(self, gyp_file, target=None, **kw):
|
| - """
|
| - Verifies that a build of the specified target is up to date.
|
| - """
|
| - kw['stdout'] = ("make: Nothing to be done for `%s'." %
|
| - self.target_name(target))
|
| -
|
| - # We need to supply a custom matcher, since we don't want to depend on the
|
| - # exact stdout string.
|
| - kw['match'] = self.match_single_line
|
| - return self.build(gyp_file, target, **kw)
|
| -
|
| -
|
| class TestGypCMake(TestGypBase):
|
| """
|
| Subclass for testing the GYP CMake generator, using cmake's ninja backend.
|
| @@ -1399,7 +1126,6 @@ class TestGypXcodeNinja(TestGypXcode):
|
|
|
| format_class_list = [
|
| TestGypGypd,
|
| - TestGypAndroid,
|
| TestGypCMake,
|
| TestGypMake,
|
| TestGypMSVS,
|
|
|