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

98 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-29 20:01 +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://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9# Standard libraries 

10import unittest 

11from unittest.mock import MagicMock 

12 

13# Third party libraries 

14import pytest 

15 

16# First party libraries 

17from tsfpga.build_project_list import BuildProjectList 

18from tsfpga.module import BaseModule 

19from tsfpga.system_utils import create_directory 

20from tsfpga.vivado.project import BuildResult, VivadoProject 

21 

22 

23# pylint: disable=too-many-instance-attributes 

24@pytest.mark.usefixtures("fixture_tmp_path") 

25class TestBuildProjectList(unittest.TestCase): 

26 

27 tmp_path = None 

28 

29 @staticmethod 

30 def _get_mocks(name, is_netlist_build): 

31 project = MagicMock(spec=VivadoProject) 

32 project.name = name 

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

34 project.is_netlist_build = is_netlist_build 

35 

36 module = MagicMock(spec=BaseModule) 

37 module.name = name 

38 module.get_build_projects.return_value = [project] 

39 

40 return module, project 

41 

42 def setUp(self): 

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

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

45 

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

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

48 

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

50 

51 def test_can_list_without_error(self): 

52 list_str = str(BuildProjectList(self.modules)) 

53 assert "one" in list_str 

54 assert "two" in list_str 

55 

56 def test_project_filtering(self): 

57 project_list = BuildProjectList(self.modules) 

58 assert len(project_list.projects) == 2 

59 assert self.project_one in project_list.projects 

60 assert self.project_two in project_list.projects 

61 

62 project_list = BuildProjectList( 

63 self.modules, project_filters=["apa", "*ne", "three", "four"] 

64 ) 

65 assert len(project_list.projects) == 1 

66 assert self.project_one in project_list.projects 

67 

68 project_list = BuildProjectList(self.modules, include_netlist_not_top_builds=True) 

69 assert len(project_list.projects) == 2 

70 assert self.project_three in project_list.projects 

71 assert self.project_four in project_list.projects 

72 

73 project_list = BuildProjectList( 

74 self.modules, 

75 include_netlist_not_top_builds=True, 

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

77 ) 

78 assert len(project_list.projects) == 1 

79 assert self.project_three in project_list.projects 

80 

81 def test_create(self): 

82 project_list = BuildProjectList(self.modules, project_filters=["one", "two"]) 

83 assert project_list.create( 

84 projects_path=self.tmp_path / "projects_path", 

85 num_parallel_builds=2, 

86 ip_cache_path=self.tmp_path / "ip_cache_path", 

87 ) 

88 

89 self.project_one.create.assert_called_once_with( 

90 project_path=self.tmp_path / "projects_path" / "one" / "project", 

91 ip_cache_path=self.tmp_path / "ip_cache_path", 

92 ) 

93 

94 self.project_two.create.assert_called_once_with( 

95 project_path=self.tmp_path / "projects_path" / "two" / "project", 

96 ip_cache_path=self.tmp_path / "ip_cache_path", 

97 ) 

98 

99 self.project_three.create.assert_not_called() 

100 self.project_four.create.assert_not_called() 

101 

102 def test_create_unless_exists(self): 

103 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

104 assert project_list.create_unless_exists( 

105 projects_path=self.tmp_path / "projects_path", 

106 num_parallel_builds=2, 

107 ip_cache_path=self.tmp_path / "ip_cache_path", 

108 ) 

109 

110 self.project_one.create.assert_called_once_with( 

111 project_path=self.tmp_path / "projects_path" / "one" / "project", 

112 ip_cache_path=self.tmp_path / "ip_cache_path", 

113 ) 

114 

115 # Create project file manually 

116 create_directory(self.tmp_path / "projects_path" / "one" / "project") 

117 (self.tmp_path / "projects_path" / "one" / "project" / "one.xpr").write_text("") 

118 

119 assert project_list.create_unless_exists( 

120 projects_path=self.tmp_path / "projects_path", 

121 num_parallel_builds=2, 

122 ip_cache_path=self.tmp_path / "ip_cache_path", 

123 ) 

124 

125 # Still only called once after second create_unless_exists() 

126 self.project_one.create.assert_called_once() 

127 

128 self.project_two.create.assert_not_called() 

129 self.project_three.create.assert_not_called() 

130 self.project_four.create.assert_not_called() 

131 

132 def test_build(self): 

133 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

134 assert project_list.build( 

135 projects_path=self.tmp_path / "projects_path", 

136 num_parallel_builds=2, 

137 num_threads_per_build=4, 

138 other_build_argument=True, 

139 ) 

140 

141 self.project_one.build.assert_called_once_with( 

142 project_path=self.tmp_path / "projects_path" / "one" / "project", 

143 output_path=self.tmp_path / "projects_path" / "one", 

144 num_threads=4, 

145 other_build_argument=True, 

146 ) 

147 

148 def test_build_fail_should_return_false(self): 

149 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

150 self.project_one.build.return_value = MagicMock(spec=BuildResult) 

151 self.project_one.build.return_value.success = False 

152 

153 assert not project_list.build( 

154 projects_path=self.tmp_path / "projects_path", 

155 num_parallel_builds=2, 

156 num_threads_per_build=4, 

157 other_build_argument=True, 

158 ) 

159 

160 def test_build_with_output_path(self): 

161 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

162 assert project_list.build( 

163 projects_path=self.tmp_path / "projects_path", 

164 num_parallel_builds=2, 

165 num_threads_per_build=4, 

166 output_path=self.tmp_path / "output_path", 

167 ) 

168 

169 self.project_one.build.assert_called_once_with( 

170 project_path=self.tmp_path / "projects_path" / "one" / "project", 

171 output_path=self.tmp_path / "output_path" / "one", 

172 num_threads=4, 

173 ) 

174 

175 def test_build_with_collect_artifacts(self): 

176 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

177 collect_artifacts = MagicMock() 

178 assert project_list.build( 

179 projects_path=self.tmp_path / "projects_path", 

180 num_parallel_builds=2, 

181 num_threads_per_build=4, 

182 collect_artifacts=collect_artifacts, 

183 ) 

184 

185 collect_artifacts.assert_called_once_with( 

186 project=self.project_one, 

187 output_path=self.tmp_path / "projects_path" / "one", 

188 ) 

189 

190 def test_build_with_collect_artifacts_and_output_path(self): 

191 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

192 collect_artifacts = MagicMock() 

193 assert project_list.build( 

194 projects_path=self.tmp_path / "projects_path", 

195 num_parallel_builds=2, 

196 num_threads_per_build=4, 

197 output_path=self.tmp_path / "output_path", 

198 collect_artifacts=collect_artifacts, 

199 ) 

200 

201 collect_artifacts.assert_called_once_with( 

202 project=self.project_one, output_path=self.tmp_path / "output_path" / "one" 

203 ) 

204 

205 def test_build_with_collect_artifacts_return_false_should_fail_build(self): 

206 project_list = BuildProjectList(self.modules, project_filters=["one"]) 

207 collect_artifacts = MagicMock() 

208 collect_artifacts.return_value = False 

209 assert not project_list.build( 

210 projects_path=self.tmp_path / "projects_path", 

211 num_parallel_builds=2, 

212 num_threads_per_build=4, 

213 collect_artifacts=collect_artifacts, 

214 ) 

215 

216 def test_open(self): 

217 project_list = BuildProjectList(self.modules, include_netlist_not_top_builds=True) 

218 assert project_list.open(projects_path=self.tmp_path / "projects_path") 

219 

220 self.project_three.open.assert_called_once_with( 

221 project_path=self.tmp_path / "projects_path" / "three" / "project" 

222 ) 

223 self.project_four.open.assert_called_once_with( 

224 project_path=self.tmp_path / "projects_path" / "four" / "project" 

225 ) 

226 self.project_one.open.assert_not_called() 

227 self.project_two.open.assert_not_called()