Bug 1242632 - Remove TESTING_FILES from moz.build; r?glandium draft
authorMike Shal <mshal@mozilla.com>
Mon, 25 Jan 2016 13:41:22 -0500
changeset 337152 32ff6f10f5dff09640faf63ec35273cf18ae2252
parent 337151 96fec295009c422a59e60f95ba37c3317dd79493
child 515592 eafe7f147ceecd2c6d9891d2b2f6dde2a63ded6a
push id12279
push userbmo:mshal@mozilla.com
push dateSat, 05 Mar 2016 00:37:01 +0000
reviewersglandium
bugs1242632
milestone47.0a1
Bug 1242632 - Remove TESTING_FILES from moz.build; r?glandium MozReview-Commit-ID: ALy4s6Xpg7f
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozbuild/frontend/context.py
python/mozbuild/mozbuild/frontend/data.py
python/mozbuild/mozbuild/frontend/emitter.py
python/mozbuild/mozbuild/test/frontend/test_emitter.py
testing/mochitest/moz.build
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -60,17 +60,16 @@ from ..frontend.data import (
     Library,
     LocalInclude,
     PerSourceFlag,
     Program,
     SharedLibrary,
     SimpleProgram,
     Sources,
     StaticLibrary,
-    TestHarnessFiles,
     TestManifest,
     VariablePassthru,
     XPIDLFile,
 )
 from ..util import (
     ensureParentDir,
     FileAvoidWrite,
 )
@@ -522,19 +521,16 @@ class RecursiveMakeBackend(CommonBackend
 """.format(output=obj.output,
            dep_file=dep_file,
            inputs=' ' + ' '.join(obj.inputs) if obj.inputs else '',
            flags=' ' + ' '.join(obj.flags) if obj.flags else '',
            backend=' backend.mk' if obj.flags else '',
            script=obj.script,
            method=obj.method))
 
-        elif isinstance(obj, TestHarnessFiles):
-            self._process_test_harness_files(obj, backend_file)
-
         elif isinstance(obj, JARManifest):
             self._no_skip['libs'].add(backend_file.relobjdir)
             backend_file.write('JAR_MANIFEST := %s\n' % obj.path.full_path)
 
         elif isinstance(obj, Program):
             self._process_program(obj.program, backend_file)
             self._process_linked_libraries(obj, backend_file)
 
@@ -904,39 +900,16 @@ class RecursiveMakeBackend(CommonBackend
 
     def _process_defines(self, obj, backend_file, which='DEFINES'):
         """Output the DEFINES rules to the given backend file."""
         defines = list(obj.get_defines())
         if defines:
             defines = ' '.join(shell_quote(d) for d in defines)
             backend_file.write_once('%s += %s\n' % (which, defines))
 
-    def _process_test_harness_files(self, obj, backend_file):
-        for path, files in obj.srcdir_files.iteritems():
-            for source in files:
-                dest = '%s/%s' % (path, mozpath.basename(source))
-                self._install_manifests['_tests'].add_symlink(source, dest)
-
-        for path, patterns in obj.srcdir_pattern_files.iteritems():
-            for p in patterns:
-                self._install_manifests['_tests'].add_pattern_symlink(p[0], p[1], path)
-
-        for path, files in obj.objdir_files.iteritems():
-            self._no_skip['misc'].add(backend_file.relobjdir)
-            prefix = 'TEST_HARNESS_%s' % path.replace('/', '_')
-            backend_file.write("""
-%(prefix)s_FILES := %(files)s
-%(prefix)s_DEST := %(dest)s
-%(prefix)s_TARGET := misc
-INSTALL_TARGETS += %(prefix)s
-""" % { 'prefix': prefix,
-        'dest': '$(DEPTH)/_tests/%s' % path,
-        'files': ' '.join(mozpath.relpath(f, backend_file.objdir)
-                          for f in files) })
-
     def _process_installation_target(self, obj, backend_file):
         # A few makefiles need to be able to override the following rules via
         # make XPI_NAME=blah commands, so we default to the lazy evaluation as
         # much as possible here to avoid breaking things.
         if obj.xpiname:
             backend_file.write('XPI_NAME = %s\n' % (obj.xpiname))
         if obj.subdir:
             backend_file.write('DIST_SUBDIR = %s\n' % (obj.subdir))
@@ -1263,17 +1236,25 @@ INSTALL_TARGETS += %(prefix)s
         for path, files in files.walk():
             target_var = (mozpath.join(target, path)
                           if path else target).replace('/', '_')
             have_objdir_files = False
             for f in files:
                 assert not isinstance(f, RenamedSourcePath)
                 dest = mozpath.join(reltarget, path, f.target_basename)
                 if not isinstance(f, ObjDirPath):
-                    install_manifest.add_symlink(f.full_path, dest)
+                    if '*' in f:
+                        if not isinstance(f, SourcePath):
+                            raise Exception("Wildcards are only supported in "
+                                            "SourcePath objects in %s. Path is: %s" % (
+                                                type(obj), f
+                                            ))
+                        install_manifest.add_pattern_symlink(f.srcdir, f, path)
+                    else:
+                        install_manifest.add_symlink(f.full_path, dest)
                 else:
                     install_manifest.add_optional_exists(dest)
                     backend_file.write('%s_FILES += %s\n' % (
                         target_var, self._pretty_path(f, backend_file)))
                     have_objdir_files = True
             if have_objdir_files:
                 tier = 'export' if obj.install_target == 'dist/include' else 'misc'
                 self._no_skip[tier].add(backend_file.relobjdir)
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -1039,22 +1039,16 @@ VARIABLES = {
         """Disable the wrappers for STL which allow it to work with C++ exceptions
         disabled.
         """),
 
     'FINAL_TARGET_PP_FILES': (ContextDerivedTypedHierarchicalStringList(Path), list,
         """Like ``FINAL_TARGET_FILES``, with preprocessing.
         """),
 
-    'TESTING_FILES': (ContextDerivedTypedHierarchicalStringList(Path), list,
-        """List of files to be installed in the _tests directory.
-
-        This works similarly to FINAL_TARGET_FILES.
-        """),
-
     'FINAL_LIBRARY': (unicode, unicode,
         """Library in which the objects of the current directory will be linked.
 
         This variable contains the name of a library, defined elsewhere with
         ``LIBRARY_NAME``, in which the objects of the current directory will be
         linked.
         """),
 
@@ -1689,17 +1683,17 @@ VARIABLES = {
 
            Note that the ordering of flags matter here, these flags will be
            added to the linker's command line in the same order as they
            appear in the moz.build file.
 
            This variable only has an effect on Windows.
         """),
 
-    'TEST_HARNESS_FILES': (HierarchicalStringList, list,
+    'TEST_HARNESS_FILES': (ContextDerivedTypedHierarchicalStringList(Path), list,
         """List of files to be installed for test harnesses.
 
         ``TEST_HARNESS_FILES`` can be used to install files to any directory
         under $objdir/_tests. Files can be appended to a field to indicate
         which subdirectory they should be exported to. For example,
         to export ``foo.py`` to ``_tests/foo``, append to
         ``TEST_HARNESS_FILES`` like so::
            TEST_HARNESS_FILES.foo += ['foo.py']
@@ -2028,17 +2022,17 @@ SPECIAL_VARIABLES = {
 
     'EXTRA_PP_JS_MODULES': (lambda context: context['FINAL_TARGET_PP_FILES'].modules, list,
         """Additional JavaScript files to distribute.
 
         This variable contains a list of files to copy into
         ``$(FINAL_TARGET)/modules``, after preprocessing.
         """),
 
-    'TESTING_JS_MODULES': (lambda context: context['TESTING_FILES'].modules, list,
+    'TESTING_JS_MODULES': (lambda context: context['TEST_HARNESS_FILES'].modules, list,
         """JavaScript modules to install in the test-only destination.
 
         Some JavaScript modules (JSMs) are test-only and not distributed
         with Firefox. This variable defines them.
 
         To install modules in a subdirectory, use properties of this
         variable to control the final destination. e.g.
 
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -198,32 +198,16 @@ class BaseDefines(ContextDerived):
             self.defines.update(more_defines)
 
 class Defines(BaseDefines):
     pass
 
 class HostDefines(BaseDefines):
     pass
 
-class TestHarnessFiles(ContextDerived):
-    """Sandbox container object for TEST_HARNESS_FILES,
-    which is a HierarchicalStringList.
-
-    We need an object derived from ContextDerived for use in the backend, so
-    this object fills that role. It just has a reference to the underlying
-    HierarchicalStringList, which is created when parsing TEST_HARNESS_FILES.
-    """
-    __slots__ = ('srcdir_files', 'srcdir_pattern_files', 'objdir_files')
-
-    def __init__(self, context, srcdir_files, srcdir_pattern_files, objdir_files):
-        ContextDerived.__init__(self, context)
-        self.srcdir_files = srcdir_files
-        self.srcdir_pattern_files = srcdir_pattern_files
-        self.objdir_files = objdir_files
-
 class IPDLFile(ContextDerived):
     """Describes an individual .ipdl source file."""
 
     __slots__ = (
         'basename',
     )
 
     def __init__(self, context, path):
@@ -809,17 +793,20 @@ class FinalTargetPreprocessedFiles(Conte
     """
     __slots__ = ('files')
 
     def __init__(self, sandbox, files):
         ContextDerived.__init__(self, sandbox)
         self.files = files
 
 
-class TestingFiles(FinalTargetFiles):
+class TestHarnessFiles(FinalTargetFiles):
+    """Sandbox container object for TEST_HARNESS_FILES,
+    which is a HierarchicalStringList.
+    """
     @property
     def install_target(self):
         return '_tests'
 
 
 class Exports(FinalTargetFiles):
     """Context derived container object for EXPORTS, which is a
     HierarchicalStringList.
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -60,17 +60,16 @@ from .data import (
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     SharedLibrary,
     SimpleProgram,
     Sources,
     StaticLibrary,
     TestHarnessFiles,
-    TestingFiles,
     TestWebIDLFile,
     TestManifest,
     UnifiedSources,
     VariablePassthru,
     WebIDLFile,
     XPIDLFile,
 )
 from mozpack.chrome.manifest import (
@@ -788,19 +787,16 @@ class TreeMetadataEmitter(LoggingMixin):
             yield obj
 
         for path in context['CONFIGURE_SUBST_FILES']:
             sub = self._create_substitution(ConfigFileSubstitution, context,
                 path)
             generated_files.add(str(sub.relpath))
             yield sub
 
-        for obj in self._process_test_harness_files(context):
-            yield obj
-
         defines = context.get('DEFINES')
         if defines:
             yield Defines(context, defines)
 
         host_defines = context.get('HOST_DEFINES')
         if host_defines:
             yield HostDefines(context, host_defines)
 
@@ -827,49 +823,55 @@ class TreeMetadataEmitter(LoggingMixin):
             yield LocalInclude(context, local_include)
 
         components = []
         for var, cls in (
             ('BRANDING_FILES', BrandingFiles),
             ('EXPORTS', Exports),
             ('FINAL_TARGET_FILES', FinalTargetFiles),
             ('FINAL_TARGET_PP_FILES', FinalTargetPreprocessedFiles),
-            ('TESTING_FILES', TestingFiles),
+            ('TEST_HARNESS_FILES', TestHarnessFiles),
         ):
             all_files = context.get(var)
             if not all_files:
                 continue
-            if dist_install is False and var != 'TESTING_FILES':
+            if dist_install is False and var != 'TEST_HARNESS_FILES':
                 raise SandboxValidationError(
                     '%s cannot be used with DIST_INSTALL = False' % var,
                     context)
             has_prefs = False
             has_resources = False
             for base, files in all_files.walk():
+                if var == 'TEST_HARNESS_FILES' and not base:
+                    raise SandboxValidationError(
+                        'Cannot install files to the root of TEST_HARNESS_FILES', context)
                 if base == 'components':
                     components.extend(files)
                 if base == 'defaults/pref':
                     has_prefs = True
                 if mozpath.split(base)[0] == 'res':
                     has_resources = True
                 for f in files:
                     if (var == 'FINAL_TARGET_PP_FILES' and
                         not isinstance(f, SourcePath)):
                         raise SandboxValidationError(
                                 ('Only source directory paths allowed in ' +
                                 'FINAL_TARGET_PP_FILES: %s')
                                 % (f,), context)
                     if not isinstance(f, ObjDirPath):
                         path = f.full_path
-                        if not os.path.exists(path):
+                        if '*' not in path and not os.path.exists(path):
                             raise SandboxValidationError(
                                 'File listed in %s does not exist: %s'
                                 % (var, path), context)
                     else:
-                        if f.target_basename not in generated_files:
+                        # The '/' check is to allow installing files generated
+                        # from other directories, which is done occasionally for
+                        # tests.
+                        if f.target_basename not in generated_files and '/' not in f:
                             raise SandboxValidationError(
                                 ('Objdir file listed in %s not in ' +
                                  'GENERATED_FILES: %s') % (var, f), context)
 
             # Addons (when XPI_NAME is defined) and Applications (when
             # DIST_SUBDIR is defined) use a different preferences directory
             # (default/preferences) from the one the GRE uses (defaults/pref).
             # Hence, we move the files from the latter to the former in that
@@ -1013,57 +1015,16 @@ class TreeMetadataEmitter(LoggingMixin):
                             'Input for generating %s does not exist: %s'
                             % (f, p.full_path), context)
                     inputs.append(p.full_path)
             else:
                 script = None
                 method = None
             yield GeneratedFile(context, script, method, output, inputs)
 
-    def _process_test_harness_files(self, context):
-        test_harness_files = context.get('TEST_HARNESS_FILES')
-        if not test_harness_files:
-            return
-
-        srcdir_files = defaultdict(list)
-        srcdir_pattern_files = defaultdict(list)
-        objdir_files = defaultdict(list)
-
-        for path, strings in test_harness_files.walk():
-            if not path and strings:
-                raise SandboxValidationError(
-                    'Cannot install files to the root of TEST_HARNESS_FILES', context)
-
-            for s in strings:
-                # Ideally, TEST_HARNESS_FILES would expose Path instances, but
-                # subclassing HierarchicalStringList to be ContextDerived is
-                # painful, so until we actually kill HierarchicalStringList,
-                # just do Path manipulation here.
-                p = Path(context, s)
-                if isinstance(p, ObjDirPath):
-                    objdir_files[path].append(p.full_path)
-                elif '*' in s:
-                    resolved = p.full_path
-                    if s[0] == '/':
-                        pattern_start = resolved.index('*')
-                        base_path = mozpath.dirname(resolved[:pattern_start])
-                        pattern = resolved[len(base_path)+1:]
-                    else:
-                        base_path = context.srcdir
-                        pattern = s
-                    srcdir_pattern_files[path].append((base_path, pattern));
-                elif not os.path.exists(p.full_path):
-                    raise SandboxValidationError(
-                        'File listed in TEST_HARNESS_FILES does not exist: %s' % s, context)
-                else:
-                    srcdir_files[path].append(p.full_path)
-
-        yield TestHarnessFiles(context, srcdir_files,
-                               srcdir_pattern_files, objdir_files)
-
     def _process_test_manifests(self, context):
         for prefix, info in TEST_MANIFESTS.items():
             for path in context.get('%s_MANIFESTS' % prefix, []):
                 for obj in self._process_test_manifest(context, info, path):
                     yield obj
 
         for flavor in REFTEST_FLAVORS:
             for path in context.get('%s_MANIFESTS' % flavor.upper(), []):
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -314,17 +314,17 @@ class TestEmitterBasic(unittest.TestCase
         self.assertEqual(len(objs), 1)
         self.assertIsInstance(objs[0], TestHarnessFiles)
 
         expected = {
             'mochitest': ['runtests.py', 'utils.py'],
             'testing/mochitest': ['mochitest.py', 'mochitest.ini'],
         }
 
-        for path, strings in objs[0].srcdir_files.iteritems():
+        for path, strings in objs[0].files.walk():
             self.assertTrue(path in expected)
             basenames = sorted(mozpath.basename(s) for s in strings)
             self.assertEqual(sorted(expected[path]), basenames)
 
     def test_test_harness_files_root(self):
         reader = self.reader('test-harness-files-root')
         with self.assertRaisesRegexp(SandboxValidationError,
             'Cannot install files to the root of TEST_HARNESS_FILES'):
--- a/testing/mochitest/moz.build
+++ b/testing/mochitest/moz.build
@@ -23,16 +23,20 @@ if CONFIG['MOZ_BUILD_APP'] != 'mobile/an
     DEFINES['MOCHITEST_BOOTSTRAP'] = True
     FINAL_TARGET_FILES += ['bootstrap.js']
 
 MOCHITEST_MANIFESTS += [
     'tests/MochiKit-1.4.2/tests/mochitest.ini',
 ]
 MOCHITEST_CHROME_MANIFESTS += ['chrome/chrome.ini']
 
+GENERATED_FILES += [
+    'automation.py',
+]
+
 TEST_HARNESS_FILES.testing.mochitest += [
     '!automation.py',
     '/build/mobile/remoteautomation.py',
     '/build/pgo/server-locations.txt',
     '/build/sanitizers/lsan_suppressions.txt',
     '/build/valgrind/cross-architecture.sup',
     '/build/valgrind/i386-redhat-linux-gnu.sup',
     '/build/valgrind/x86_64-redhat-linux-gnu.sup',