Source code for tests.test_profile_stability

from __future__ import print_function

import argparse
import fnmatch
import os.path
import sys

import ssg.yaml

from tests.common import stability


[docs] def describe_change(difference, name): msg = "" msg += stability.describe_changeset( "Following selections were added to the {name} profile:\n".format(name=name), difference.added, ) msg += stability.describe_changeset( "Following selections were removed from the {name} profile:\n".format(name=name), difference.removed, ) return msg.rstrip()
[docs] def compare_sets(reference, sample): reference = set(reference) sample = set(sample) result = stability.Difference() result.added = list(sample.difference(reference)) result.removed = list(reference.difference(sample)) return result
[docs] def get_references_filenames(ref_root): found = [] for root, dirs, files in os.walk(ref_root): for basename in files: if fnmatch.fnmatch(basename, "*.profile"): filename = os.path.join(root, basename) found.append(filename) return found
[docs] def corresponding_product_built(build_dir, reference_fname): ref_path_components = reference_fname.split(os.path.sep) product_id = ref_path_components[-2] return os.path.isdir(os.path.join(build_dir, product_id))
[docs] def get_matching_compiled_profile_filename(build_dir, reference_fname): ref_path_components = reference_fname.split(os.path.sep) product_id = ref_path_components[-2] profile_fname = ref_path_components[-1] matching_filename = os.path.join(build_dir, product_id, "profiles", profile_fname) if os.path.isfile(matching_filename): return matching_filename
[docs] def get_selections_key_from_yaml(yaml_fname): return ssg.yaml.open_raw(yaml_fname)["selections"]
[docs] def get_profile_name_from_reference_filename(fname): path_components = fname.split(os.path.sep) product_id = path_components[-2] profile_id = os.path.splitext(path_components[-1])[0] name = "{product_id}'s {profile_id}".format( product_id=product_id, profile_id=profile_id) return name
[docs] def get_reference_vs_built_difference(reference_fname, built_fname): ref_selections = get_selections_key_from_yaml(reference_fname) built_selections = get_selections_key_from_yaml(built_fname) difference = compare_sets(ref_selections, built_selections) return difference
[docs] def inform_and_append_fix_based_on_reference_compiled_profile(ref, build_root, fix_commands): if not corresponding_product_built(build_root, ref): return compiled_profile = get_matching_compiled_profile_filename(build_root, ref) if not compiled_profile: msg = ("Unexpectedly unable to find compiled profile corresponding" "to the test file {ref}, although the corresponding product has been built. " "This indicates that a profile we have tests for is missing." .format(ref=ref)) raise RuntimeError(msg) difference = get_reference_vs_built_difference(ref, compiled_profile) if not difference.empty: comprehensive_profile_name = get_profile_name_from_reference_filename(ref) stability.report_comparison(comprehensive_profile_name, difference, describe_change) fix_commands.append( "cp '{compiled}' '{reference}'" .format(compiled=compiled_profile, reference=ref) )
[docs] def main(): parser = argparse.ArgumentParser() parser.add_argument("build_root") parser.add_argument("test_data_root") args = parser.parse_args() reference_files = get_references_filenames(args.test_data_root) if not reference_files: raise RuntimeError("Unable to find any reference profiles in {test_root}" .format(test_root=args.test_data_root)) fix_commands = [] for ref in reference_files: inform_and_append_fix_based_on_reference_compiled_profile( ref, args.build_root, fix_commands) if fix_commands: msg = ( "If changes to mentioned profiles are intentional, " "copy those compiled files, so they become the new reference:\n{fixes}\n" "Please remember that if you change a profile that is extended by other profiles, " "changes propagate to derived profiles. " "If those changes are unwanted, you have to supress them " "using explicit selections or !unselections in derived profiles." .format(fixes="\n".join(fix_commands))) print(msg, file=sys.stderr) sys.exit(bool(fix_commands))
if __name__ == "__main__": main()