--- a/python/mozbuild/mozbuild/frontend/mach_commands.py
+++ b/python/mozbuild/mozbuild/frontend/mach_commands.py
@@ -1,15 +1,16 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, print_function, unicode_literals
from collections import defaultdict
+import json
import os
from mach.decorators import (
CommandArgument,
CommandProvider,
Command,
SubCommand,
)
@@ -111,16 +112,86 @@ class MozbuildFileCommands(MachCommandBa
print(e.message)
return 1
for component, files in sorted(components.items(), key=lambda x: (x is None, x)):
print('%s :: %s' % (component.product, component.component) if component else 'UNKNOWN')
for f in sorted(files):
print(' %s' % f)
+
+ @SubCommand('file-info', 'test-bug-components-associations',
+ 'Show relations between tests and bug components.')
+ @CommandArgument('paths', nargs='+',
+ help='Paths whose data to query')
+ def associations(self, paths):
+ """Show metadata for each test file.
+
+ Given a requested path print a break down of bug components to test files
+ """
+ from mozbuild.testing import TestResolver
+ resolver = self._spawn(TestResolver)
+
+ # This information comes from the build generated all-tests.pkl file
+ # {u'dir_relpath': u'toolkit/mozapps/update/tests/chrome',
+ # u'file_relpath': u'toolkit/mozapps/update/tests/chrome/test_0010_background_basic.xul',
+ # u'flavor': u'chrome',
+ # 'here': u'/Users/armenzg/repos/firefox/obj-x86_64-apple-darwin16.5.0/_tests/testing/mochitest/chrome/toolkit/mozapps/update/tests/chrome',
+ # 'manifest': u'/Users/armenzg/repos/firefox/toolkit/mozapps/update/tests/chrome/chrome.ini',
+ # 'name': 'test_0010_background_basic.xul',
+ # 'path': u'/Users/armenzg/repos/firefox/obj-x86_64-apple-darwin16.5.0/_tests/testing/mochitest/chrome/toolkit/mozapps/update/tests/chrome/test_0010_background_basic.xul',
+ # 'relpath': u'toolkit/mozapps/update/tests/chrome/test_0010_background_basic.xul',
+ # 'support-files': '\nutils.js\nupdate.sjs',
+ # 'tags': 'appupdate'}
+ tests = list(resolver.resolve_tests(paths=paths))
+
+ # This data structure will help determine if a file is a test file
+ tests_by_path = {}
+ # NOTE: Metadata generated by resolve_tests() can have multiple items for
+ # the same test file. Some test files have different configurations.
+ # Each test configuration is represented as its own test entry in the test resolver.
+ # We're de-duping based on file path
+ for metadata in tests:
+ # Metadata for reftests use 'file_relpath' while the rest use 'relpath'
+ path = metadata.get('relpath', metadata.get('file_relpath'))
+ # Bug 1334525 - We can't handle web-platform proplery; ignore for now
+ if path and 'web-platform' not in path:
+ tests_by_path[path] = metadata
+
+ print('We have %d tests under this/these paths: %s' % (len(tests_by_path), paths))
+
+ # Collect bug components for each file
+ files_info = self._get_files_info(tests_by_path.keys())
+
+ # Both data structures should have the same number of file paths
+ assert sorted(files_info.keys()) == sorted(tests_by_path.keys())
+
+ # Let's create a data structure to contain the bug components recognized
+ components_to_files_metadata = defaultdict(list)
+ for path, module_info in files_info.items():
+ m = module_info.get('BUG_COMPONENT', 'UNKNOWN')
+ if m != 'UNKNOWN':
+ m = '%s::%s' % (m.product, m.component)
+ components_to_files_metadata[m].append(path)
+
+ print('We have found tests in %d components' % len(components_to_files_metadata))
+
+ # Order the list to guarantee deterministic output when dumping to file
+ for k, _ in components_to_files_metadata.items():
+ components_to_files_metadata[k].sort()
+
+ with open('tests_in_bug_components.json', 'w') as fd:
+ fd.write(json.dumps(components_to_files_metadata, indent=4, sort_keys=True))
+
+ for c, files in sorted(components_to_files_metadata.items()):
+ print('%s -> %s test files' % (c, len(files)))
+
+ print('We have generated the file tests_in_bug_components.json with more data')
+
+
@SubCommand('file-info', 'missing-bugzilla',
'Show files missing Bugzilla component info')
@CommandArgument('-r', '--rev',
help='Version control revision to look up info from')
@CommandArgument('paths', nargs='+',
help='Paths whose data to query')
def file_info_missing_bugzilla(self, paths, rev=None):
try: