summaryrefslogtreecommitdiff
path: root/buildstream/testing/_sourcetests/workspace.py
blob: 5218f8f1ee2a717ddcef25a490c0dafae7ae4a1e (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#
#  Copyright (C) 2018 Codethink Limited
#  Copyright (C) 2019 Bloomberg Finance LP
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#

# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name

import os
import shutil
import pytest

from buildstream import _yaml
from .. import create_repo, ALL_REPO_KINDS
from .. import cli  # pylint: disable=unused-import

# Project directory
TOP_DIR = os.path.dirname(os.path.realpath(__file__))
DATA_DIR = os.path.join(TOP_DIR, 'project')


class WorkspaceCreator():
    def __init__(self, cli, tmpdir, datafiles, project_path=None):
        self.cli = cli
        self.tmpdir = tmpdir
        self.datafiles = datafiles

        if not project_path:
            project_path = str(datafiles)
        else:
            shutil.copytree(str(datafiles), project_path)

        self.project_path = project_path
        self.bin_files_path = os.path.join(project_path, 'files', 'bin-files')

        self.workspace_cmd = os.path.join(self.project_path, 'workspace_cmd')

    def create_workspace_element(self, kind, track, suffix='', workspace_dir=None,
                                 element_attrs=None):
        element_name = 'workspace-test-{}{}.bst'.format(kind, suffix)
        element_path = os.path.join(self.project_path, 'elements')
        if not workspace_dir:
            workspace_dir = os.path.join(self.workspace_cmd, element_name)
            if workspace_dir[-4:] == '.bst':
                workspace_dir = workspace_dir[:-4]

        # Create our repo object of the given source type with
        # the bin files, and then collect the initial ref.
        repo = create_repo(kind, str(self.tmpdir))
        ref = repo.create(self.bin_files_path)
        if track:
            ref = None

        # Write out our test target
        element = {
            'kind': 'import',
            'sources': [
                repo.source_config(ref=ref)
            ]
        }
        if element_attrs:
            element = {**element, **element_attrs}
        _yaml.dump(element,
                   os.path.join(element_path,
                                element_name))
        return element_name, element_path, workspace_dir

    def create_workspace_elements(self, kinds, track, suffixs=None, workspace_dir_usr=None,
                                  element_attrs=None):

        element_tuples = []

        if suffixs is None:
            suffixs = ['', ] * len(kinds)
        else:
            if len(suffixs) != len(kinds):
                raise "terable error"

        for suffix, kind in zip(suffixs, kinds):
            element_name, _, workspace_dir = \
                self.create_workspace_element(kind, track, suffix, workspace_dir_usr,
                                              element_attrs)
            element_tuples.append((element_name, workspace_dir))

        # Assert that there is no reference, a track & fetch is needed
        states = self.cli.get_element_states(self.project_path, [
            e for e, _ in element_tuples
        ])
        if track:
            assert not any(states[e] != 'no reference' for e, _ in element_tuples)
        else:
            assert not any(states[e] != 'fetch needed' for e, _ in element_tuples)

        return element_tuples

    def open_workspaces(self, kinds, track, suffixs=None, workspace_dir=None,
                        element_attrs=None, no_checkout=False):

        element_tuples = self.create_workspace_elements(kinds, track, suffixs, workspace_dir,
                                                        element_attrs)
        os.makedirs(self.workspace_cmd, exist_ok=True)

        # Now open the workspace, this should have the effect of automatically
        # tracking & fetching the source from the repo.
        args = ['workspace', 'open']
        if track:
            args.append('--track')
        if no_checkout:
            args.append('--no-checkout')
        if workspace_dir is not None:
            assert len(element_tuples) == 1, "test logic error"
            _, workspace_dir = element_tuples[0]
            args.extend(['--directory', workspace_dir])

        args.extend([element_name for element_name, workspace_dir_suffix in element_tuples])
        result = self.cli.run(cwd=self.workspace_cmd, project=self.project_path, args=args)

        result.assert_success()

        if not no_checkout:
            # Assert that we are now buildable because the source is now cached.
            states = self.cli.get_element_states(self.project_path, [
                e for e, _ in element_tuples
            ])
            assert not any(states[e] != 'buildable' for e, _ in element_tuples)

            # Check that the executable hello file is found in each workspace
            for _, workspace in element_tuples:
                filename = os.path.join(workspace, 'usr', 'bin', 'hello')
                assert os.path.exists(filename)

        return element_tuples


def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspace_dir=None,
                   project_path=None, element_attrs=None, no_checkout=False):
    workspace_object = WorkspaceCreator(cli, tmpdir, datafiles, project_path)
    workspaces = workspace_object.open_workspaces((kind, ), track, (suffix, ), workspace_dir,
                                                  element_attrs, no_checkout)
    assert len(workspaces) == 1
    element_name, workspace = workspaces[0]
    return element_name, workspace_object.project_path, workspace


@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", ALL_REPO_KINDS)
def test_open(cli, tmpdir, datafiles, kind):
    open_workspace(cli, tmpdir, datafiles, kind, False)