Bug 1373796 - Normalize xpcshell manifests in errorsummary, r?jgraham draft
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Tue, 20 Jun 2017 10:52:33 -0400
changeset 597438 034f1f7320a71ee0dd50b06b416754dc8397000c
parent 597264 7a6baa6cca3292e8099e652b64d27e74df560874
child 634239 feda660f94d5fe207f4dff312cd23d5f6b2d31b3
push id64940
push userahalberstadt@mozilla.com
push dateTue, 20 Jun 2017 15:49:32 +0000
reviewersjgraham
bugs1373796
milestone56.0a1
Bug 1373796 - Normalize xpcshell manifests in errorsummary, r?jgraham MozReview-Commit-ID: It2HPXMuqLA
testing/xpcshell/runxpcshelltests.py
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -6,30 +6,30 @@
 
 import copy
 import importlib
 import json
 import math
 import mozdebug
 import mozinfo
 import os
-import os.path
 import random
 import re
 import shutil
 import signal
 import sys
 import tempfile
 import time
 import traceback
 
+from argparse import ArgumentParser
 from collections import defaultdict, deque, namedtuple
 from distutils import dir_util
+from functools import partial
 from multiprocessing import cpu_count
-from argparse import ArgumentParser
 from subprocess import Popen, PIPE, STDOUT
 from tempfile import mkdtemp, gettempdir
 from threading import (
     Timer,
     Thread,
     Event,
     current_thread,
 )
@@ -822,16 +822,31 @@ class XPCShellTests(object):
 
         if os.path.exists(ini_path):
             return TestManifest([ini_path], strict=True)
         else:
             print >> sys.stderr, ("Failed to find manifest at %s; use --manifest "
                                   "to set path explicitly." % (ini_path,))
             sys.exit(1)
 
+    def normalizeTest(self, root, test_object):
+        path = test_object.get('file_relpath', test_object['relpath'])
+        if 'dupe-manifest' in test_object and 'ancestor-manifest' in test_object:
+            test_object['id'] = '%s:%s' % (os.path.basename(test_object['ancestor-manifest']), path)
+        else:
+            test_object['id'] = path
+
+        test_object['manifest'] = os.path.relpath(test_object['manifest'], root)
+
+        if os.sep != '/':
+            for key in ('id', 'manifest'):
+                test_object[key] = test_object[key].replace(os.sep, '/')
+
+        return test_object
+
     def buildTestList(self, test_tags=None, test_paths=None):
         """
           read the xpcshell.ini manifest and set self.alltests to be
           an array of test objects.
 
           if we are chunking tests, it will be done here as well
         """
 
@@ -839,28 +854,29 @@ class XPCShellTests(object):
             test_paths = []
 
         if len(test_paths) == 1 and test_paths[0].endswith(".js"):
             self.singleFile = os.path.basename(test_paths[0])
         else:
             self.singleFile = None
 
         mp = self.getTestManifest(self.manifest)
+        normalize = partial(self.normalizeTest, mp.rootdir)
 
         filters = []
         if test_tags:
             filters.append(tags(test_tags))
 
         if test_paths:
             filters.append(pathprefix(test_paths))
 
         if self.singleFile is None and self.totalChunks > 1:
             filters.append(chunk_by_slice(self.thisChunk, self.totalChunks))
         try:
-            self.alltests = mp.active_tests(filters=filters, **mozinfo.info)
+            self.alltests = map(normalize, mp.active_tests(filters=filters, **mozinfo.info))
         except TypeError:
             sys.stderr.write("*** offending mozinfo.info: %s\n" % repr(mozinfo.info))
             raise
 
         if len(self.alltests) == 0:
             self.log.error("no tests to run using specified "
                            "combination of filters: {}".format(
                                 mp.fmt_filters()))
@@ -1080,26 +1096,16 @@ class XPCShellTests(object):
         else:
             self.xpcsRunArgs = ['-e', '_execute_test(); quit(0);']
 
     def addTestResults(self, test):
         self.passCount += test.passCount
         self.failCount += test.failCount
         self.todoCount += test.todoCount
 
-    def makeTestId(self, test_object):
-        """Calculate an identifier for a test based on its path or a combination of
-        its path and the source manifest."""
-
-        relpath_key = 'file_relpath' if 'file_relpath' in test_object else 'relpath'
-        path = test_object[relpath_key].replace('\\', '/');
-        if 'dupe-manifest' in test_object and 'ancestor-manifest' in test_object:
-            return '%s:%s' % (os.path.basename(test_object['ancestor-manifest']), path)
-        return path
-
     def runTests(self, xpcshell=None, xrePath=None, appPath=None, symbolsPath=None,
                  manifest=None, testPaths=None, mobileArgs=None, tempDir=None,
                  interactive=False, verbose=False, keepGoing=False, logfiles=True,
                  thisChunk=1, totalChunks=1, debugger=None,
                  debuggerArgs=None, debuggerInteractive=False,
                  profileName=None, mozInfo=None, sequential=False, shuffle=False,
                  testingModulesDir=None, pluginsPath=None,
                  testClass=XPCShellTestThread, failureManifest=None,
@@ -1335,17 +1341,16 @@ class XPCShellTests(object):
         # also a list for the tests that need to be run sequentially
         sequential_tests = []
         for test_object in self.alltests:
             # Test identifiers are provided for the convenience of logging. These
             # start as path names but are rewritten in case tests from the same path
             # are re-run.
 
             path = test_object['path']
-            test_object['id'] = self.makeTestId(test_object)
 
             if self.singleFile and not path.endswith(self.singleFile):
                 continue
 
             self.testCount += 1
 
             test = testClass(test_object, self.event, self.cleanup_dir_list,
                     app_dir_key=appDirKey,