summaryrefslogtreecommitdiff
path: root/tests/external_plugins.py
blob: 84a1abdce5551c56762e3444371882f742ab50be (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
85
86
87
88
89
90
91
92
93
import glob
import os
import pytest
import shutil
import subprocess
import sys
import time


# 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=["tests"]):
        self.name = name
        self.url = url
        self.ref = ref

        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,
                        ])
        return self._clone_location

    def install(self):
        subprocess.run(['pip3', 'install', self._clone_location])

    def test(self, pytest_args):
        test_files = self._match_test_patterns()
        return pytest.main(pytest_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, tmpdir, pytest_args):
    print("Cloning repo {} to {}...".format(repo.name, tmpdir))
    repo.clone(tmpdir)

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

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


if __name__ == "__main__":
    from sys import argv

    # 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 = argv

    ALL_EXTERNAL_PLUGINS = [
        ExternalPluginRepo(
            name='bst-plugins-template',
            url='https://gitlab.com/BuildStream/bst-plugins-template.git',
            ref='master'
        ),
    ]

    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)