summaryrefslogtreecommitdiff
path: root/tests/external_plugins.py
blob: 9a5e0450130c16bbad6c1dd69b9819cc46abe60f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import glob
import os
import subprocess
import sys

import pytest


# An ExternalPluginRepo represents a git repository containing a plugin
# with tests that we wish to use as part of our test suite.
#
# Args:
#    name (str): The name of the repository. This is used for impormational purposes
#    url (str): The location from which therepository can be cloned
#    ref (str): A known git ref that we wish to test against
#    test_match_patterns (list[str]): A list of shell style globs which may be
#          used to specify a subset of test files from the repository to run.
#          These must be specified relative to the root of the repository.
class ExternalPluginRepo:
    def __init__(self, name, url, ref, test_match_patterns=None):
        self.name = name
        self.url = url
        self.ref = ref

        if test_match_patterns is None:
            test_match_patterns = ["tests"]

        self._test_match_patterns = test_match_patterns
        self._clone_location = None

    def clone(self, location):
        self._clone_location = os.path.join(location, self.name)
        subprocess.run(
            ["git", "clone", "--single-branch", "--branch", self.ref, "--depth", "1", self.url, self._clone_location,],
            check=True,
        )
        return self._clone_location

    def install(self):
        subprocess.run(["pip3", "install", self._clone_location], check=True)

    def test(self, args):
        test_files = self._match_test_patterns()
        return pytest.main(args + test_files)

    def _match_test_patterns(self):
        match_list = []
        for pattern in self._test_match_patterns:
            abs_pattern = os.path.join(self._clone_location, pattern)
            print("matching pattern: ", abs_pattern)
            matches = glob.glob(abs_pattern)
            match_list.extend(matches)

        if not match_list:
            raise ValueError("No matches found for patterns {}".format(self._test_match_patterns))
        return match_list


def run_repo_tests(repo, tempdir, args):
    print("Cloning repo {} to {}...".format(repo.name, tempdir))
    repo.clone(tempdir)

    print("Installing {}...".format(repo.name))
    repo.install()

    print("Testing {}...".format(repo.name))
    return repo.test(args)


if __name__ == "__main__":
    # Args:
    #    tmpdir: The directory in which this script will clone external
    #            repositories and use pytest's tmpdir.
    #    pytest_args: any remaining arguments to this script will be passed
    #                 directly to it's pytest invocations
    _, tmpdir, *pytest_args = sys.argv

    ALL_EXTERNAL_PLUGINS = []

    exit_code = 0
    for plugin in ALL_EXTERNAL_PLUGINS:
        exit_code = run_repo_tests(plugin, tmpdir, pytest_args)
        if exit_code != 0:
            sys.exit(exit_code)