summaryrefslogtreecommitdiffstats
path: root/build/compare-mozconfig
diff options
context:
space:
mode:
Diffstat (limited to 'build/compare-mozconfig')
-rw-r--r--build/compare-mozconfig/compare-mozconfigs-wrapper.py68
-rw-r--r--build/compare-mozconfig/compare-mozconfigs.py170
2 files changed, 238 insertions, 0 deletions
diff --git a/build/compare-mozconfig/compare-mozconfigs-wrapper.py b/build/compare-mozconfig/compare-mozconfigs-wrapper.py
new file mode 100644
index 000000000..e1888eed7
--- /dev/null
+++ b/build/compare-mozconfig/compare-mozconfigs-wrapper.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+# 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 unicode_literals
+
+import logging
+import mozunit
+import subprocess
+import sys
+import unittest
+
+from os import path
+from buildconfig import substs
+
+log = logging.getLogger(__name__)
+
+def determine_platform():
+ platform_mapping = {'WINNT': {'x86_64': 'win64',
+ 'i686': 'win32'},
+ 'Darwin': {'x86_64': 'macosx-universal',
+ 'i386':'macosx-universal'},
+ 'Linux': {'x86_64': 'linux64',
+ 'i686': 'linux32'}}
+
+ os_type = substs['OS_TARGET']
+ cpu_type = substs['TARGET_CPU']
+ return platform_mapping.get(os_type, {}).get(cpu_type, None)
+
+
+class TestCompareMozconfigs(unittest.TestCase):
+ def test_compare_mozconfigs(self):
+ """ A wrapper script that calls compare-mozconfig.py
+ based on the platform that the machine is building for"""
+ platform = determine_platform()
+
+ if platform is not None:
+ python_exe = substs['PYTHON']
+ topsrcdir = substs['top_srcdir']
+
+ # construct paths and args for compare-mozconfig
+ browser_dir = path.join(topsrcdir, 'browser')
+ script_path = path.join(topsrcdir, 'build/compare-mozconfig/compare-mozconfigs.py')
+ whitelist_path = path.join(browser_dir, 'config/mozconfigs/whitelist')
+ beta_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'beta')
+ release_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'release')
+ nightly_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'nightly')
+
+ log.info("Comparing beta against nightly mozconfigs")
+ ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+ whitelist_path, '--no-download',
+ platform + ',' + beta_mozconfig_path +
+ ',' + nightly_mozconfig_path])
+
+ if ret_code > 0:
+ return ret_code
+
+ log.info("Comparing release against nightly mozconfigs")
+ ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+ whitelist_path, '--no-download',
+ platform + ',' + release_mozconfig_path +
+ ',' + nightly_mozconfig_path])
+
+ self.assertEqual(0, ret_code)
+
+if __name__ == '__main__':
+ mozunit.main()
diff --git a/build/compare-mozconfig/compare-mozconfigs.py b/build/compare-mozconfig/compare-mozconfigs.py
new file mode 100644
index 000000000..876e336fe
--- /dev/null
+++ b/build/compare-mozconfig/compare-mozconfigs.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+# 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/.
+
+# originally from http://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py
+
+from __future__ import unicode_literals
+
+import logging
+import os
+import site
+import sys
+import urllib2
+import difflib
+
+FAILURE_CODE = 1
+SUCCESS_CODE = 0
+
+log = logging.getLogger(__name__)
+
+class ConfigError(Exception):
+ pass
+
+def make_hg_url(hgHost, repoPath, protocol='https', revision=None,
+ filename=None):
+ """construct a valid hg url from a base hg url (hg.mozilla.org),
+ repoPath, revision and possible filename"""
+ base = '%s://%s' % (protocol, hgHost)
+ repo = '/'.join(p.strip('/') for p in [base, repoPath])
+ if not filename:
+ if not revision:
+ return repo
+ else:
+ return '/'.join([p.strip('/') for p in [repo, 'rev', revision]])
+ else:
+ assert revision
+ return '/'.join([p.strip('/') for p in [repo, 'raw-file', revision,
+ filename]])
+
+def readConfig(configfile, keys=[], required=[]):
+ c = {}
+ execfile(configfile, c)
+ for k in keys:
+ c = c[k]
+ items = c.keys()
+ err = False
+ for key in required:
+ if key not in items:
+ err = True
+ log.error("Required item `%s' missing from %s" % (key, c))
+ if err:
+ raise ConfigError("Missing at least one item in config, see above")
+ return c
+
+def verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, platform,
+ mozconfigWhitelist={}):
+ """Compares mozconfig to nightly_mozconfig and compare to an optional
+ whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair
+ are pairs containing the mozconfig's identifier and the list of lines in
+ the mozconfig."""
+
+ # unpack the pairs to get the names, the names are just for
+ # identifying the mozconfigs when logging the error messages
+ mozconfig_name, mozconfig_lines = mozconfig_pair
+ nightly_mozconfig_name, nightly_mozconfig_lines = nightly_mozconfig_pair
+
+ missing_args = mozconfig_lines == [] or nightly_mozconfig_lines == []
+ if missing_args:
+ log.info("Missing mozconfigs to compare for %s" % platform)
+ return False
+
+ success = True
+
+ diff_instance = difflib.Differ()
+ diff_result = diff_instance.compare(mozconfig_lines, nightly_mozconfig_lines)
+ diff_list = list(diff_result)
+
+ for line in diff_list:
+ clean_line = line[1:].strip()
+ if (line[0] == '-' or line[0] == '+') and len(clean_line) > 1:
+ # skip comment lines
+ if clean_line.startswith('#'):
+ continue
+ # compare to whitelist
+ message = ""
+ if line[0] == '-':
+ # handle lines that move around in diff
+ if '+' + line[1:] in diff_list:
+ continue
+ if platform in mozconfigWhitelist.get('release', {}):
+ if clean_line in \
+ mozconfigWhitelist['release'][platform]:
+ continue
+ elif line[0] == '+':
+ if '-' + line[1:] in diff_list:
+ continue
+ if platform in mozconfigWhitelist.get('nightly', {}):
+ if clean_line in \
+ mozconfigWhitelist['nightly'][platform]:
+ continue
+ else:
+ log.warning("%s not in %s %s!" % (
+ clean_line, platform,
+ mozconfigWhitelist['nightly'][platform]))
+ else:
+ log.error("Skipping line %s!" % line)
+ continue
+ message = "found in %s but not in %s: %s"
+ if line[0] == '-':
+ log.error(message % (mozconfig_name,
+ nightly_mozconfig_name, clean_line))
+ else:
+ log.error(message % (nightly_mozconfig_name,
+ mozconfig_name, clean_line))
+ success = False
+ return success
+
+def get_mozconfig(path, options):
+ """Consumes a path and returns a list of lines from
+ the mozconfig file. If download is required, the path
+ specified should be relative to the root of the hg
+ repository e.g browser/config/mozconfigs/linux32/nightly"""
+ if options.no_download:
+ return open(path, 'r').readlines()
+ else:
+ url = make_hg_url(options.hghost, options.branch, 'http',
+ options.revision, path)
+ return urllib2.urlopen(url).readlines()
+
+if __name__ == '__main__':
+ from optparse import OptionParser
+ parser = OptionParser()
+
+ parser.add_option('--branch', dest='branch')
+ parser.add_option('--revision', dest='revision')
+ parser.add_option('--hghost', dest='hghost', default='hg.mozilla.org')
+ parser.add_option('--whitelist', dest='whitelist')
+ parser.add_option('--no-download', action='store_true', dest='no_download',
+ default=False)
+ options, args = parser.parse_args()
+
+ logging.basicConfig(level=logging.INFO)
+
+ missing_args = options.branch is None or options.revision is None
+ if not options.no_download and missing_args:
+ logging.error('Not enough arguments to download mozconfigs')
+ sys.exit(FAILURE_CODE)
+
+ mozconfig_whitelist = readConfig(options.whitelist, ['whitelist'])
+
+ for arg in args:
+ platform, mozconfig_path, nightly_mozconfig_path = arg.split(',')
+
+ mozconfig_lines = get_mozconfig(mozconfig_path, options)
+ nightly_mozconfig_lines = get_mozconfig(nightly_mozconfig_path, options)
+
+ mozconfig_pair = (mozconfig_path, mozconfig_lines)
+ nightly_mozconfig_pair = (nightly_mozconfig_path,
+ nightly_mozconfig_lines)
+
+ passed = verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair,
+ platform, mozconfig_whitelist)
+
+ if passed:
+ logging.info('Mozconfig check passed!')
+ else:
+ logging.error('Mozconfig check failed!')
+ sys.exit(FAILURE_CODE)
+ sys.exit(SUCCESS_CODE)