Coverage for tsfpga/test/test_build_project_list.py: 100%

101 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-02-21 20:51 +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# -------------------------------------------------------------------------------------------------- 

8 

9from unittest.mock import MagicMock 

10 

11import pytest 

12 

13from tsfpga.build_project_list import BuildProjectList 

14from tsfpga.module import BaseModule 

15from tsfpga.system_utils import create_directory 

16from tsfpga.vivado.project import BuildResult, VivadoProject 

17 

18 

19@pytest.fixture 

20def build_project_list_test(): 

21 class TestBuildProjectList: 

22 @staticmethod 

23 def _get_mocks(name, is_netlist_build): 

24 project = MagicMock(spec=VivadoProject) 

25 project.name = name 

26 project.__str__.return_value = f"MockProject {name}" 

27 project.is_netlist_build = is_netlist_build 

28 

29 module = MagicMock(spec=BaseModule) 

30 module.name = name 

31 module.get_build_projects.return_value = [project] 

32 

33 return module, project 

34 

35 def __init__(self): 

36 self.module_one, self.project_one = self._get_mocks("one", False) 

37 self.module_two, self.project_two = self._get_mocks("two", False) 

38 

39 self.module_three, self.project_three = self._get_mocks("three", True) 

40 self.module_four, self.project_four = self._get_mocks("four", True) 

41 

42 self.modules = [self.module_one, self.module_two, self.module_three, self.module_four] 

43 

44 return TestBuildProjectList() 

45 

46 

47def test_can_list_without_error(build_project_list_test): 

48 list_str = str(BuildProjectList(build_project_list_test.modules, project_filters=[])) 

49 assert "one" in list_str 

50 assert "two" in list_str 

51 

52 

53def test_project_filtering(build_project_list_test): 

54 project_list = BuildProjectList(build_project_list_test.modules, project_filters=[]) 

55 assert len(project_list.projects) == 2 

56 assert build_project_list_test.project_one in project_list.projects 

57 assert build_project_list_test.project_two in project_list.projects 

58 

59 project_list = BuildProjectList( 

60 build_project_list_test.modules, project_filters=["apa", "*ne", "three", "four"] 

61 ) 

62 assert len(project_list.projects) == 1 

63 assert build_project_list_test.project_one in project_list.projects 

64 

65 project_list = BuildProjectList( 

66 build_project_list_test.modules, project_filters=["one", "one", "on*"] 

67 ) 

68 assert len(project_list.projects) == 1 

69 assert build_project_list_test.project_one in project_list.projects 

70 

71 project_list = BuildProjectList( 

72 build_project_list_test.modules, project_filters=[], include_netlist_not_top_builds=True 

73 ) 

74 assert len(project_list.projects) == 2 

75 assert build_project_list_test.project_three in project_list.projects 

76 assert build_project_list_test.project_four in project_list.projects 

77 

78 project_list = BuildProjectList( 

79 build_project_list_test.modules, 

80 include_netlist_not_top_builds=True, 

81 project_filters=["apa", "one", "two", "thr*"], 

82 ) 

83 assert len(project_list.projects) == 1 

84 assert build_project_list_test.project_three in project_list.projects 

85 

86 

87def test_create(build_project_list_test, tmp_path): 

88 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one", "two"]) 

89 assert project_list.create( 

90 projects_path=tmp_path / "projects_path", 

91 num_parallel_builds=2, 

92 ip_cache_path=tmp_path / "ip_cache_path", 

93 ) 

94 

95 build_project_list_test.project_one.create.assert_called_once_with( 

96 project_path=tmp_path / "projects_path" / "one" / "project", 

97 ip_cache_path=tmp_path / "ip_cache_path", 

98 ) 

99 

100 build_project_list_test.project_two.create.assert_called_once_with( 

101 project_path=tmp_path / "projects_path" / "two" / "project", 

102 ip_cache_path=tmp_path / "ip_cache_path", 

103 ) 

104 

105 build_project_list_test.project_three.create.assert_not_called() 

106 build_project_list_test.project_four.create.assert_not_called() 

107 

108 

109def test_create_unless_exists(build_project_list_test, tmp_path): 

110 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

111 assert project_list.create_unless_exists( 

112 projects_path=tmp_path / "projects_path", 

113 num_parallel_builds=2, 

114 ip_cache_path=tmp_path / "ip_cache_path", 

115 ) 

116 

117 build_project_list_test.project_one.create.assert_called_once_with( 

118 project_path=tmp_path / "projects_path" / "one" / "project", 

119 ip_cache_path=tmp_path / "ip_cache_path", 

120 ) 

121 

122 # Create project file manually 

123 create_directory(tmp_path / "projects_path" / "one" / "project") 

124 (tmp_path / "projects_path" / "one" / "project" / "one.xpr").write_text("") 

125 

126 assert project_list.create_unless_exists( 

127 projects_path=tmp_path / "projects_path", 

128 num_parallel_builds=2, 

129 ip_cache_path=tmp_path / "ip_cache_path", 

130 ) 

131 

132 # Still only called once after second create_unless_exists() 

133 build_project_list_test.project_one.create.assert_called_once() 

134 

135 build_project_list_test.project_two.create.assert_not_called() 

136 build_project_list_test.project_three.create.assert_not_called() 

137 build_project_list_test.project_four.create.assert_not_called() 

138 

139 

140def test_build(build_project_list_test, tmp_path): 

141 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

142 assert project_list.build( 

143 projects_path=tmp_path / "projects_path", 

144 num_parallel_builds=2, 

145 num_threads_per_build=4, 

146 other_build_argument=True, 

147 ) 

148 

149 build_project_list_test.project_one.build.assert_called_once_with( 

150 project_path=tmp_path / "projects_path" / "one" / "project", 

151 output_path=tmp_path / "projects_path" / "one", 

152 num_threads=4, 

153 other_build_argument=True, 

154 ) 

155 

156 

157def test_build_fail_should_return_false(build_project_list_test, tmp_path): 

158 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

159 build_project_list_test.project_one.build.return_value = MagicMock(spec=BuildResult) 

160 build_project_list_test.project_one.build.return_value.success = False 

161 

162 assert not project_list.build( 

163 projects_path=tmp_path / "projects_path", 

164 num_parallel_builds=2, 

165 num_threads_per_build=4, 

166 other_build_argument=True, 

167 ) 

168 

169 

170def test_build_with_output_path(build_project_list_test, tmp_path): 

171 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

172 assert project_list.build( 

173 projects_path=tmp_path / "projects_path", 

174 num_parallel_builds=2, 

175 num_threads_per_build=4, 

176 output_path=tmp_path / "output_path", 

177 ) 

178 

179 build_project_list_test.project_one.build.assert_called_once_with( 

180 project_path=tmp_path / "projects_path" / "one" / "project", 

181 output_path=tmp_path / "output_path" / "one", 

182 num_threads=4, 

183 ) 

184 

185 

186def test_build_with_collect_artifacts(build_project_list_test, tmp_path): 

187 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

188 collect_artifacts = MagicMock() 

189 assert project_list.build( 

190 projects_path=tmp_path / "projects_path", 

191 num_parallel_builds=2, 

192 num_threads_per_build=4, 

193 collect_artifacts=collect_artifacts, 

194 ) 

195 

196 collect_artifacts.assert_called_once_with( 

197 project=build_project_list_test.project_one, 

198 output_path=tmp_path / "projects_path" / "one", 

199 ) 

200 

201 

202def test_build_with_collect_artifacts_and_output_path(build_project_list_test, tmp_path): 

203 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

204 collect_artifacts = MagicMock() 

205 assert project_list.build( 

206 projects_path=tmp_path / "projects_path", 

207 num_parallel_builds=2, 

208 num_threads_per_build=4, 

209 output_path=tmp_path / "output_path", 

210 collect_artifacts=collect_artifacts, 

211 ) 

212 

213 collect_artifacts.assert_called_once_with( 

214 project=build_project_list_test.project_one, 

215 output_path=tmp_path / "output_path" / "one", 

216 ) 

217 

218 

219def test_build_with_collect_artifacts_return_false_should_fail_build( 

220 build_project_list_test, tmp_path 

221): 

222 project_list = BuildProjectList(build_project_list_test.modules, project_filters=["one"]) 

223 collect_artifacts = MagicMock() 

224 collect_artifacts.return_value = False 

225 assert not project_list.build( 

226 projects_path=tmp_path / "projects_path", 

227 num_parallel_builds=2, 

228 num_threads_per_build=4, 

229 collect_artifacts=collect_artifacts, 

230 ) 

231 

232 

233def test_open(build_project_list_test, tmp_path): 

234 project_list = BuildProjectList( 

235 build_project_list_test.modules, project_filters=[], include_netlist_not_top_builds=True 

236 ) 

237 assert project_list.open(projects_path=tmp_path / "projects_path") 

238 

239 build_project_list_test.project_three.open.assert_called_once_with( 

240 project_path=tmp_path / "projects_path" / "three" / "project" 

241 ) 

242 build_project_list_test.project_four.open.assert_called_once_with( 

243 project_path=tmp_path / "projects_path" / "four" / "project" 

244 ) 

245 build_project_list_test.project_one.open.assert_not_called() 

246 build_project_list_test.project_two.open.assert_not_called()