def _get_platform_cpes(platform): ssg_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) if platform.startswith("multi_platform_"): try: products = MULTI_PLATFORM_MAPPING[platform] except KeyError: logging.error( "Unknown multi_platform specifier: %s is not from %s" % (platform, ", ".join(MULTI_PLATFORM_MAPPING.keys()))) raise ValueError platform_cpes = set() for p in products: product_yaml_path = os.path.join(ssg_root, "products", p, "product.yml") product_yaml = load_product_yaml(product_yaml_path) p_cpes = ProductCPEs(product_yaml) platform_cpes |= set(p_cpes.get_product_cpe_names()) return platform_cpes else: # scenario platform is specified by a full product name try: product = FULL_NAME_TO_PRODUCT_MAPPING[platform] except KeyError: logging.error( "Unknown product name: %s is not from %s" % (platform, ", ".join(FULL_NAME_TO_PRODUCT_MAPPING.keys()))) raise ValueError product_yaml_path = os.path.join(ssg_root, "products", product, "product.yml") product_yaml = load_product_yaml(product_yaml_path) product_cpes = ProductCPEs(product_yaml) platform_cpes = set(product_cpes.get_product_cpe_names()) return platform_cpes
def get_product_context(product=None): """ Returns a product YAML context if any product is specified. Hard-coded to assume a debug build. """ # Load product's YAML file if present. This will allow us to parse # tests in the context of the product we're executing under. product_yaml = dict() if product: yaml_path = product_yaml_path(SSG_ROOT, product) product_yaml = load_product_yaml(yaml_path) # We could run into a DocumentationNotComplete error when loading a # rule's YAML contents. However, because the test suite isn't executed # in the context of a particular build (though, ideally it would be # linked), we may not know exactly whether the top-level rule/profile # we're testing is actually completed. Thus, forcibly set the required # property to bypass this error. product_yaml['cmake_build_type'] = 'Debug' # Set the Jinja processing environment to Test Suite, # this allows Jinja macros to behave differently in a content build time and in a test time. product_yaml['SSG_TEST_SUITE_ENV'] = True return product_yaml
def __main__(): args = parse_args() project_root = args.root if not project_root: project_root = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir) subst_dict = dict() if args.product: subst_dict = products.load_product_yaml(args.product) args.func(args, subst_dict)
def walk_through_benchmark_dirs(product=None): directories = _BENCHMARK_DIRS if product is not None: yaml_path = product_yaml_path(SSG_ROOT, product) product_base = os.path.dirname(yaml_path) product_yaml = load_product_yaml(yaml_path) benchmark_root = os.path.join(product_base, product_yaml['benchmark_root']) directories = [os.path.abspath(benchmark_root)] for dirname in directories: for dirpath, dirnames, filenames in os.walk(dirname): yield dirpath, dirnames, filenames
def template_tests(product=None): """ Create a temporary directory with test cases parsed via jinja using product-specific context. """ # Set up an empty temp directory tmpdir = tempfile.mkdtemp() # We want to remove the temporary directory on failure, but preserve # it on success. Wrap in a try/except block and reraise the original # exception after removing the temporary directory. try: # Load product's YAML file if present. This will allow us to parse # tests in the context of the product we're executing under. product_yaml = dict() if product: yaml_path = product_yaml_path(SSG_ROOT, product) product_yaml = load_product_yaml(yaml_path) # Below we could run into a DocumentationNotComplete error. However, # because the test suite isn't executed in the context of a particular # build (though, ideally it would be linked), we may not know exactly # whether the top-level rule/profile we're testing is actually # completed. Thus, forcibly set the required property to bypass this # error. product_yaml['cmake_build_type'] = 'Debug' # Note that we're not exactly copying 1-for-1 the contents of the # directory structure into the temporary one. Instead we want a # flattened mapping with all rules in a single top-level directory # and all tests immediately contained within it. That is: # # /group_a/rule_a/tests/something.pass.sh -> /rule_a/something.pass.sh for dirpath, dirnames, _ in walk_through_benchmark_dirs(product): # Skip anything that isn't obviously a rule. if "tests" not in dirnames or not is_rule_dir(dirpath): continue # Load rule content in our environment. We use this to satisfy # some implied properties that might be used in the test suite. rule_path = get_rule_dir_yaml(dirpath) rule = RuleYAML.from_yaml(rule_path, product_yaml) # Note that most places would check prodtype, but we don't care # about that here: if the rule is available to the product, we # load and parse it anyways as we have no knowledge of the # top-level profile or rule passed into the test suite. prodtypes = parse_prodtype(rule.prodtype) # Our local copy of env_yaml needs some properties from rule.yml # for completeness. local_env_yaml = dict() local_env_yaml.update(product_yaml) local_env_yaml['rule_id'] = rule.id_ local_env_yaml['rule_title'] = rule.title local_env_yaml['products'] = prodtypes # Create the destination directory. dest_path = os.path.join(tmpdir, rule.id_) os.mkdir(dest_path) # Walk the test directory, writing all tests into the output # directory, recursively. tests_dir_path = os.path.join(dirpath, "tests") tests_dir_path = os.path.abspath(tests_dir_path) for dirpath, dirnames, filenames in os.walk(tests_dir_path): for dirname in dirnames: # We want to recreate the correct path under the temporary # directory. Resolve it to a relative path from the tests/ # directory. dir_path = _rel_abs_path(os.path.join(dirpath, dirname), tests_dir_path) assert '../' not in dir_path tmp_dir_path = os.path.join(dest_path, dir_path) os.mkdir(tmp_dir_path) for filename in filenames: # We want to recreate the correct path under the temporary # directory. Resolve it to a relative path from the tests/ # directory. Assumption: directories should be created # prior to recursing into them, so we don't need to handle # if a file's parent directory doesn't yet exist under the # destination. src_test_path = os.path.join(dirpath, filename) rel_test_path = _rel_abs_path(src_test_path, tests_dir_path) dest_test_path = os.path.join(dest_path, rel_test_path) # Rather than performing an OS-level copy, we need to # first parse the test with jinja and then write it back # out to the destination. parsed_test = process_file(src_test_path, local_env_yaml) with open(dest_test_path, 'w') as output_fp: print(parsed_test, file=output_fp) except Exception as exp: shutil.rmtree(tmpdir, ignore_errors=True) raise exp return tmpdir