Bug 616999. Xpcshell manifest support; xpccheck.py for missing tests. r=ted, a=test-only
authorJoel Maher <jmaher@mozilla.com>
Fri, 20 May 2011 07:15:41 -0400
changeset 70016 9e2f8321f4800c3ff03f26bda29930afba94975a
parent 70015 40195c0187d3069b848b012065476ab8868e6d0c
child 70017 84114a3f3c8bdf3ac7d6247997fe04a85df72e93
push idunknown
push userunknown
push dateunknown
reviewersted, test-only
bugs616999
milestone6.0a1
Bug 616999. Xpcshell manifest support; xpccheck.py for missing tests. r=ted, a=test-only
build/manifestparser.py
build/xpccheck.py
--- a/build/manifestparser.py
+++ b/build/manifestparser.py
@@ -169,38 +169,36 @@ class ManifestParser(object):
 
     ### methods for reading manifests
 
     def __init__(self, manifests=(), defaults=None, strict=True):
         self._defaults = defaults or {}
         self.tests = []
         self.strict = strict
         self.rootdir = None
-        self.relativeRoot = None
         if manifests:
             self.read(*manifests)
 
-    def getRelativeRoot(self):
-        return self.relativeRoot
+    def getRelativeRoot(self, root):
+        return root
 
     def read(self, *filenames, **defaults):
 
         # ensure all files exist
         missing = [ filename for filename in filenames
                     if not os.path.exists(filename) ]
         if missing:
             raise IOError('Missing files: %s' % ', '.join(missing))
 
         # process each file
         for filename in filenames:
 
             # set the per file defaults
             defaults = defaults.copy() or self._defaults.copy()
             here = os.path.dirname(os.path.abspath(filename))
-            self.relativeRoot = here
             defaults['here'] = here
 
             if self.rootdir is None:
                 # set the root directory
                 # == the directory of the first manifest given
                 self.rootdir = here
 
             # read the configuration
@@ -211,17 +209,17 @@ class ManifestParser(object):
 
                 # a file to include
                 # TODO: keep track of included file structure:
                 # self.manifests = {'manifest.ini': 'relative/path.ini'}
                 if section.startswith('include:'):
                     include_file = section.split('include:', 1)[-1]
                     include_file = normalize_path(include_file)
                     if not os.path.isabs(include_file):
-                        include_file = os.path.join(self.getRelativeRoot(), include_file)
+                        include_file = os.path.join(self.getRelativeRoot(here), include_file)
                     if not os.path.exists(include_file):
                         if self.strict:
                             raise IOError("File '%s' does not exist" % include_file)
                         else:
                             continue
                     include_defaults = data.copy()
                     self.read(include_file, **include_defaults)
                     continue
new file mode 100644
--- /dev/null
+++ b/build/xpccheck.py
@@ -0,0 +1,141 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla build system.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Joel Maher <joel.maher@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisiwons above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+'''A generic script to verify all test files are in the 
+corresponding .ini file.
+
+Usage: xpccheck.py <directory> [<directory> ...]
+'''
+
+import sys
+import os
+from glob import glob
+import manifestparser
+
+class srcManifestParser(manifestparser.ManifestParser):
+  def __init__(self, manifests=(), defaults=None, strict=True, testroot=None):
+    self.testroot = testroot
+    manifestparser.ManifestParser.__init__(self, manifests, defaults, strict)
+
+  def getRelativeRoot(self, here):
+    if self.testroot is None:
+        return manifestparser.ManifestParser.getRelativeRoot(self, self.rootdir)
+    return self.testroot
+
+
+def getIniTests(testdir):
+  mp = manifestparser.ManifestParser(strict=False)
+  mp.read(os.path.join(testdir, 'xpcshell.ini'))
+  return mp.tests
+
+def verifyDirectory(initests, directory):
+  files = glob(os.path.join(os.path.abspath(directory), "test_*"))
+  for f in files:
+    if (not os.path.isfile(f)):
+      continue
+
+    name = os.path.basename(f)
+    if name.endswith('.in'):
+      name = name[:-3]
+
+    if not name.endswith('.js'):
+      continue
+
+    found = False
+    for test in initests:
+      if os.path.join(os.path.abspath(directory), name) == test['path']:
+        found = True
+        break
+   
+    if not found:
+      print >>sys.stderr, "TEST-UNEXPECTED-FAIL | xpccheck | test %s is missing from test manifest %s!" % (name, os.path.join(directory, 'xpcshell.ini'))
+      sys.exit(1)
+
+def verifyIniFile(initests, directory):
+  files = glob(os.path.join(os.path.abspath(directory), "test_*"))
+  for test in initests:
+    name = test['path'].split('/')[-1]
+
+    found = False
+    for f in files:
+
+      fname = f.split('/')[-1]
+      if fname.endswith('.in'):
+        fname = '.in'.join(fname.split('.in')[:-1])
+
+      if os.path.join(os.path.abspath(directory), fname) == test['path']:
+        found = True
+        break
+
+    if not found:
+      print >>sys.stderr, "TEST-UNEXPECTED-FAIL | xpccheck | found %s in xpcshell.ini and not in directory '%s'" % (name, directory)
+      sys.exit(1)
+
+def verifyMasterIni(mastername, topsrcdir, directory):
+  mp = srcManifestParser(strict=False, testroot=topsrcdir)
+  mp.read(mastername)
+  tests = mp.tests
+
+  found = False
+  for test in tests:
+    if test['manifest'] == os.path.abspath(os.path.join(directory, 'xpcshell.ini')):
+      found = True
+      break
+
+  if not found:
+    print >>sys.stderr, "TEST-UNEXPECTED-FAIL | xpccheck | directory %s is missing from master xpcshell.ini file %s" % (directory, mastername)
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+  if len(sys.argv) < 4:
+    print >>sys.stderr, "Usage: xpccheck.py <topsrcdir> <path/master.ini> <directory> [<directory> ...]"
+    sys.exit(1)
+
+  topsrcdir = sys.argv[1]
+  for d in sys.argv[3:]:
+    # xpcshell-unpack is a copy of xpcshell sibling directory and in the Makefile
+    # we copy all files (including xpcshell.ini from the sibling directory.
+    if d.endswith('toolkit/mozapps/extensions/test/xpcshell-unpack'):
+      continue
+
+    initests = getIniTests(d)
+    verifyDirectory(initests, d)
+    verifyIniFile(initests, d)
+    verifyMasterIni(sys.argv[2], topsrcdir, d)
+
+