diff options
Diffstat (limited to 'build/compare-mozconfig/compare-mozconfigs.py')
-rw-r--r-- | build/compare-mozconfig/compare-mozconfigs.py | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/build/compare-mozconfig/compare-mozconfigs.py b/build/compare-mozconfig/compare-mozconfigs.py new file mode 100644 index 0000000000..210fd0568e --- /dev/null +++ b/build/compare-mozconfig/compare-mozconfigs.py @@ -0,0 +1,176 @@ +#!/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 https://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py # NOQA: E501 + +import difflib +import logging +import os +import unittest + +import buildconfig +import mozunit + +FAILURE_CODE = 1 +SUCCESS_CODE = 0 + +PLATFORMS = ( + "linux32", + "linux64", + "macosx64", + "win32", + "win64", + "win64-aarch64", +) + +log = logging.getLogger(__name__) + + +class ConfigError(Exception): + pass + + +def readConfig(configfile): + c = {} + execfile(configfile, c) + return c["whitelist"] + + +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 + + if not mozconfig_lines or not nightly_mozconfig_lines: + 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): + """Consumes a path and returns a list of lines from the mozconfig file.""" + with open(path, "rb") as fh: + return fh.readlines() + + +def compare(topsrcdir): + app = os.path.join(topsrcdir, "browser") + whitelist = readConfig(os.path.join(app, "config", "mozconfigs", "whitelist")) + + success = True + + def normalize_lines(lines): + return {l.strip() for l in lines} + + for platform in PLATFORMS: + log.info("Comparing platform %s" % platform) + + mozconfigs_path = os.path.join(app, "config", "mozconfigs", platform) + + nightly_path = os.path.join(mozconfigs_path, "nightly") + beta_path = os.path.join(mozconfigs_path, "beta") + release_path = os.path.join(mozconfigs_path, "release") + + nightly_lines = get_mozconfig(nightly_path) + beta_lines = get_mozconfig(beta_path) + release_lines = get_mozconfig(release_path) + + # Validate that entries in whitelist['nightly'][platform] are actually + # present. + whitelist_normalized = normalize_lines(whitelist["nightly"].get(platform, [])) + nightly_normalized = normalize_lines(nightly_lines) + + for line in sorted(whitelist_normalized - nightly_normalized): + log.error("extra line in nightly whitelist: %s" % line) + success = False + + log.info("Comparing beta and nightly mozconfigs") + passed = verify_mozconfigs( + (beta_path, beta_lines), (nightly_path, nightly_lines), platform, whitelist + ) + + if not passed: + success = False + + log.info("Comparing release and nightly mozconfigs") + passed = verify_mozconfigs( + (release_path, release_lines), + (nightly_path, nightly_lines), + platform, + whitelist, + ) + if not passed: + success = False + + return success + + +class TestCompareMozconfigs(unittest.TestCase): + def test_compare_mozconfigs(self): + topsrcdir = buildconfig.substs["top_srcdir"] + self.assertTrue(compare(topsrcdir)) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + mozunit.main() |