Coverage for tsfpga/test/test_build_project_list.py: 100%
101 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 20:52 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 20:52 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project, a project platform for modern FPGA development.
5# https://tsfpga.com
6# https://github.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
9# Standard libraries
10from unittest.mock import MagicMock
12# Third party libraries
13import pytest
15# First party libraries
16from tsfpga.build_project_list import BuildProjectList
17from tsfpga.module import BaseModule
18from tsfpga.system_utils import create_directory
19from tsfpga.vivado.project import BuildResult, VivadoProject
22@pytest.fixture
23def build_project_list_test():
24 # pylint: disable=too-many-instance-attributes
25 class TestBuildProjectList:
26 @staticmethod
27 def _get_mocks(name, is_netlist_build):
28 project = MagicMock(spec=VivadoProject)
29 project.name = name
30 project.__str__.return_value = f"MockProject {name}"
31 project.is_netlist_build = is_netlist_build
33 module = MagicMock(spec=BaseModule)
34 module.name = name
35 module.get_build_projects.return_value = [project]
37 return module, project
39 def __init__(self):
40 self.module_one, self.project_one = self._get_mocks("one", False)
41 self.module_two, self.project_two = self._get_mocks("two", False)
43 self.module_three, self.project_three = self._get_mocks("three", True)
44 self.module_four, self.project_four = self._get_mocks("four", True)
46 self.modules = [self.module_one, self.module_two, self.module_three, self.module_four]
48 return TestBuildProjectList()
51# False positive for pytest fixtures
52# pylint: disable=redefined-outer-name
55def test_can_list_without_error(build_project_list_test):
56 list_str = str(BuildProjectList(build_project_list_test.modules, project_filters=[]))
57 assert "one" in list_str
58 assert "two" in list_str
61def test_project_filtering(build_project_list_test):
62 project_list = BuildProjectList(build_project_list_test.modules, project_filters=[])
63 assert len(project_list.projects) == 2
64 assert build_project_list_test.project_one in project_list.projects
65 assert build_project_list_test.project_two in project_list.projects
67 project_list = BuildProjectList(
68 build_project_list_test.modules, project_filters=["apa", "*ne", "three", "four"]
69 )
70 assert len(project_list.projects) == 1
71 assert build_project_list_test.project_one in project_list.projects
73 project_list = BuildProjectList(
74 build_project_list_test.modules, project_filters=["one", "one", "on*"]
75 )
76 assert len(project_list.projects) == 1
77 assert build_project_list_test.project_one in project_list.projects
79 project_list = BuildProjectList(
80 build_project_list_test.modules, project_filters=[], include_netlist_not_top_builds=True
81 )
82 assert len(project_list.projects) == 2
83 assert build_project_list_test.project_three in project_list.projects
84 assert build_project_list_test.project_four in project_list.projects
86 project_list = BuildProjectList(
87 build_project_list_test.modules,
88 include_netlist_not_top_builds=True,
89 project_filters=["apa", "one", "two", "thr*"],
90 )
91 assert len(project_list.projects) == 1
92 assert build_project_list_test.project_three in project_list.projects
95def test_create(build_project_list_test, tmp_path):
96 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one", "two"])
97 assert project_list.create(
98 projects_path=tmp_path / "projects_path",
99 num_parallel_builds=2,
100 ip_cache_path=tmp_path / "ip_cache_path",
101 )
103 build_project_list_test.project_one.create.assert_called_once_with(
104 project_path=tmp_path / "projects_path" / "one" / "project",
105 ip_cache_path=tmp_path / "ip_cache_path",
106 )
108 build_project_list_test.project_two.create.assert_called_once_with(
109 project_path=tmp_path / "projects_path" / "two" / "project",
110 ip_cache_path=tmp_path / "ip_cache_path",
111 )
113 build_project_list_test.project_three.create.assert_not_called()
114 build_project_list_test.project_four.create.assert_not_called()
117def test_create_unless_exists(build_project_list_test, tmp_path):
118 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
119 assert project_list.create_unless_exists(
120 projects_path=tmp_path / "projects_path",
121 num_parallel_builds=2,
122 ip_cache_path=tmp_path / "ip_cache_path",
123 )
125 build_project_list_test.project_one.create.assert_called_once_with(
126 project_path=tmp_path / "projects_path" / "one" / "project",
127 ip_cache_path=tmp_path / "ip_cache_path",
128 )
130 # Create project file manually
131 create_directory(tmp_path / "projects_path" / "one" / "project")
132 (tmp_path / "projects_path" / "one" / "project" / "one.xpr").write_text("")
134 assert project_list.create_unless_exists(
135 projects_path=tmp_path / "projects_path",
136 num_parallel_builds=2,
137 ip_cache_path=tmp_path / "ip_cache_path",
138 )
140 # Still only called once after second create_unless_exists()
141 build_project_list_test.project_one.create.assert_called_once()
143 build_project_list_test.project_two.create.assert_not_called()
144 build_project_list_test.project_three.create.assert_not_called()
145 build_project_list_test.project_four.create.assert_not_called()
148def test_build(build_project_list_test, tmp_path):
149 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
150 assert project_list.build(
151 projects_path=tmp_path / "projects_path",
152 num_parallel_builds=2,
153 num_threads_per_build=4,
154 other_build_argument=True,
155 )
157 build_project_list_test.project_one.build.assert_called_once_with(
158 project_path=tmp_path / "projects_path" / "one" / "project",
159 output_path=tmp_path / "projects_path" / "one",
160 num_threads=4,
161 other_build_argument=True,
162 )
165def test_build_fail_should_return_false(build_project_list_test, tmp_path):
166 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
167 build_project_list_test.project_one.build.return_value = MagicMock(spec=BuildResult)
168 build_project_list_test.project_one.build.return_value.success = False
170 assert not project_list.build(
171 projects_path=tmp_path / "projects_path",
172 num_parallel_builds=2,
173 num_threads_per_build=4,
174 other_build_argument=True,
175 )
178def test_build_with_output_path(build_project_list_test, tmp_path):
179 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
180 assert project_list.build(
181 projects_path=tmp_path / "projects_path",
182 num_parallel_builds=2,
183 num_threads_per_build=4,
184 output_path=tmp_path / "output_path",
185 )
187 build_project_list_test.project_one.build.assert_called_once_with(
188 project_path=tmp_path / "projects_path" / "one" / "project",
189 output_path=tmp_path / "output_path" / "one",
190 num_threads=4,
191 )
194def test_build_with_collect_artifacts(build_project_list_test, tmp_path):
195 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
196 collect_artifacts = MagicMock()
197 assert project_list.build(
198 projects_path=tmp_path / "projects_path",
199 num_parallel_builds=2,
200 num_threads_per_build=4,
201 collect_artifacts=collect_artifacts,
202 )
204 collect_artifacts.assert_called_once_with(
205 project=build_project_list_test.project_one,
206 output_path=tmp_path / "projects_path" / "one",
207 )
210def test_build_with_collect_artifacts_and_output_path(build_project_list_test, tmp_path):
211 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
212 collect_artifacts = MagicMock()
213 assert project_list.build(
214 projects_path=tmp_path / "projects_path",
215 num_parallel_builds=2,
216 num_threads_per_build=4,
217 output_path=tmp_path / "output_path",
218 collect_artifacts=collect_artifacts,
219 )
221 collect_artifacts.assert_called_once_with(
222 project=build_project_list_test.project_one,
223 output_path=tmp_path / "output_path" / "one",
224 )
227def test_build_with_collect_artifacts_return_false_should_fail_build(
228 build_project_list_test, tmp_path
229):
230 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"])
231 collect_artifacts = MagicMock()
232 collect_artifacts.return_value = False
233 assert not project_list.build(
234 projects_path=tmp_path / "projects_path",
235 num_parallel_builds=2,
236 num_threads_per_build=4,
237 collect_artifacts=collect_artifacts,
238 )
241def test_open(build_project_list_test, tmp_path):
242 project_list = BuildProjectList(
243 build_project_list_test.modules, project_filters=[], include_netlist_not_top_builds=True
244 )
245 assert project_list.open(projects_path=tmp_path / "projects_path")
247 build_project_list_test.project_three.open.assert_called_once_with(
248 project_path=tmp_path / "projects_path" / "three" / "project"
249 )
250 build_project_list_test.project_four.open.assert_called_once_with(
251 project_path=tmp_path / "projects_path" / "four" / "project"
252 )
253 build_project_list_test.project_one.open.assert_not_called()
254 build_project_list_test.project_two.open.assert_not_called()