Example #1
0
 def _expand_paths(paths):
     '''
     Expand any comma-separated lists of paths, and return a set of all
     paths to ensure there are no duplicates.
     '''
     ret = set()
     for path in paths:
         if ',' in path:
             ret.update([x.strip() for x in path.split(',')])
         else:
             ret.add(path.strip())
     return ret
Example #2
0
def from_filenames_collection_modifyitems(config, items):
    from_filenames = config.getoption("--from-filenames")
    if not from_filenames:
        # Don't do anything
        return

    test_categories_paths = (
        (TESTS_DIR / "integration").relative_to(CODE_DIR),
        (TESTS_DIR / "multimaster").relative_to(CODE_DIR),
        (TESTS_DIR / "unit").relative_to(CODE_DIR),
        (PYTESTS_DIR / "e2e").relative_to(CODE_DIR),
        (PYTESTS_DIR / "functional").relative_to(CODE_DIR),
        (PYTESTS_DIR / "integration").relative_to(CODE_DIR),
        (PYTESTS_DIR / "unit").relative_to(CODE_DIR),
    )

    test_module_paths = set()
    from_filenames_listing = set()
    for path in [pathlib.Path(path.strip()) for path in from_filenames.split(",")]:
        if path.is_absolute():
            # In this case, this path is considered to be a file containing a line separated list
            # of files to consider
            with salt.utils.files.fopen(str(path)) as rfh:
                for line in rfh:
                    line_path = pathlib.Path(line.strip())
                    if not line_path.exists():
                        continue
                    from_filenames_listing.add(line_path)
            continue
        from_filenames_listing.add(path)

    filename_map = yaml.deserialize((TESTS_DIR / "filename_map.yml").read_text())
    # Let's add the match all rule
    for rule, matches in filename_map.items():
        if rule == "*":
            for match in matches:
                test_module_paths.add(_match_to_test_file(match))
            break

    # Let's now go through the list of files gathered
    for filename in from_filenames_listing:
        if str(filename).startswith("tests/"):
            # Tests in the listing don't require additional matching and will be added to the
            # list of tests to run
            test_module_paths.add(filename)
            continue
        if filename.name == "setup.py" or str(filename).startswith("salt/"):
            if path.name == "__init__.py":
                # No direct macthing
                continue
            # Now let's try a direct match between the passed file and possible test modules
            for test_categories_path in test_categories_paths:
                test_module_path = test_categories_path / "test_{}".format(path.name)
                if test_module_path.is_file():
                    test_module_paths.add(test_module_path)
                    continue

            # Do we have an entry in tests/filename_map.yml
            for rule, matches in filename_map.items():
                if rule == "*":
                    continue
                elif "|" in rule:
                    # This is regex
                    if re.match(rule, str(filename)):
                        for match in matches:
                            test_module_paths.add(_match_to_test_file(match))
                elif "*" in rule or "\\" in rule:
                    # Glob matching
                    for filerule in CODE_DIR.glob(rule):
                        if not filerule.exists():
                            continue
                        filerule = filerule.relative_to(CODE_DIR)
                        if filerule != filename:
                            continue
                        for match in matches:
                            test_module_paths.add(_match_to_test_file(match))
                else:
                    if str(filename) != rule:
                        continue
                    # Direct file paths as rules
                    filerule = pathlib.Path(rule)
                    if not filerule.exists():
                        continue
                    for match in matches:
                        test_module_paths.add(_match_to_test_file(match))
            continue
        else:
            log.debug("Don't know what to do with path %s", filename)

    selected = []
    deselected = []
    for item in items:
        itempath = pathlib.Path(str(item.fspath)).resolve().relative_to(CODE_DIR)
        if itempath in test_module_paths:
            selected.append(item)
        else:
            deselected.append(item)

    items[:] = selected
    if deselected:
        config.hook.pytest_deselected(items=deselected)
Example #3
0
def from_filenames_collection_modifyitems(config, items):
    from_filenames = config.getoption("--from-filenames")
    if not from_filenames:
        # Don't do anything
        return

    log.info(
        "Calculating test modules to run based on the paths in --from-filenames"
    )
    from_filenames_paths = set()
    for path in [path.strip() for path in from_filenames.split(",")]:
        # Make sure that, no matter what kind of path we're passed, Windows or Posix path,
        # we resolve it to the platform slash separator
        properly_slashed_path = pathlib.Path(
            path.replace("\\", os.sep).replace("/", os.sep))
        if not properly_slashed_path.exists():
            log.info(
                "The path %s(%s) passed in --from-filenames does not exist",
                path,
                properly_slashed_path,
            )
            continue
        if properly_slashed_path.is_absolute():
            # In this case, this path is considered to be a file containing a line separated list
            # of files to consider
            with salt.utils.files.fopen(str(path)) as rfh:
                for line in rfh:
                    line_path = pathlib.Path(line.strip().replace(
                        "\\", os.sep).replace("/", os.sep))
                    if not line_path.exists():
                        log.info(
                            "The path %s contained in %s passed in --from-filenames does not exist",
                            line_path,
                            properly_slashed_path,
                        )
                        continue
                    from_filenames_paths.add(line_path)
            continue
        from_filenames_paths.add(properly_slashed_path)

    # Let's start collecting test modules
    test_module_paths = set()

    filename_map = yaml.deserialize(
        (TESTS_DIR / "filename_map.yml").read_text())
    # Let's add the match all rule
    for rule, matches in filename_map.items():
        if rule == "*":
            for match in matches:
                test_module_paths.add(_match_to_test_file(match))
            break

    # Let's now go through the list of files gathered
    for path in from_filenames_paths:
        if path.as_posix().startswith("tests/"):
            if path.name == "conftest.py":
                # This is not a test module, but consider any test_*.py files in child directories
                for match in path.parent.rglob("test_*.py"):
                    test_module_paths.add(match)
                continue
            # Tests in the listing don't require additional matching and will be added to the
            # list of tests to run
            test_module_paths.add(path)
            continue
        if path.name == "setup.py" or path.as_posix().startswith("salt/"):
            if path.name == "__init__.py":
                # No direct matching
                continue

            # Let's try a direct match between the passed file and possible test modules
            glob_patterns = (
                # salt/version.py ->
                #    tests/unit/test_version.py
                #    tests/pytests/unit/test_version.py
                "**/test_{}".format(path.name),
                # salt/modules/grains.py ->
                #    tests/pytests/integration/modules/grains/tests_*.py
                # salt/modules/saltutil.py ->
                #    tests/pytests/integration/modules/saltutil/test_*.py
                "**/{}/test_*.py".format(path.stem),
                # salt/modules/config.py ->
                #    tests/unit/modules/test_config.py
                #    tests/integration/modules/test_config.py
                #    tests/pytests/unit/modules/test_config.py
                #    tests/pytests/integration/modules/test_config.py
                "**/{}/test_{}".format(path.parent.name, path.name),
            )
            for pattern in glob_patterns:
                for match in TESTS_DIR.rglob(pattern):
                    relative_path = match.relative_to(CODE_DIR)
                    log.info("Glob pattern %r matched '%s'", pattern,
                             relative_path)
                    test_module_paths.add(relative_path)

            # Do we have an entry in tests/filename_map.yml
            for rule, matches in filename_map.items():
                if rule == "*":
                    continue
                elif "|" in rule:
                    # This is regex
                    if re.match(rule, path.as_posix()):
                        for match in matches:
                            test_module_paths.add(_match_to_test_file(match))
                elif "*" in rule or "\\" in rule:
                    # Glob matching
                    for filerule in CODE_DIR.glob(rule):
                        if not filerule.exists():
                            continue
                        filerule = filerule.relative_to(CODE_DIR)
                        if filerule != path:
                            continue
                        for match in matches:
                            test_module_paths.add(_match_to_test_file(match))
                else:
                    if path.as_posix() != rule:
                        continue
                    # Direct file paths as rules
                    filerule = pathlib.Path(rule)
                    if not filerule.exists():
                        continue
                    for match in matches:
                        test_module_paths.add(_match_to_test_file(match))
            continue
        else:
            log.info("Don't know what to do with path %s", path)

    log.info(
        "Collected the following paths from --from-filenames processing:\n%s",
        "\n".join(sorted(map(str, test_module_paths))),
    )
    selected = []
    deselected = []
    for item in items:
        itempath = pathlib.Path(str(
            item.fspath)).resolve().relative_to(CODE_DIR)
        if itempath in test_module_paths:
            selected.append(item)
        else:
            deselected.append(item)

    items[:] = selected
    if deselected:
        config.hook.pytest_deselected(items=deselected)