Beispiel #1
0
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 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
Beispiel #3
0
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