Coverage for tsfpga/vivado/test/test_ip_cores.py: 100%

93 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-19 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 

9# Standard libraries 

10from unittest.mock import MagicMock, patch 

11 

12# Third party libraries 

13import pytest 

14 

15# First party libraries 

16from tsfpga.ip_core_file import IpCoreFile 

17from tsfpga.module import BaseModule, get_modules 

18from tsfpga.system_utils import create_file, delete 

19from tsfpga.vivado.ip_cores import VivadoIpCores 

20 

21 

22def test_get_ip_core_files_is_called_with_the_correct_arguments(tmp_path): 

23 modules = [MagicMock(spec=BaseModule)] 

24 

25 with patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True): 

26 VivadoIpCores(modules, tmp_path, part_name="test_part") 

27 

28 modules[0].get_ip_core_files.assert_called_once_with(generics={}, part="test_part") 

29 

30 

31def test_system_call_to_vivado_failing_should_raise_exception(tmp_path): 

32 project = VivadoIpCores(modules=[], output_path=tmp_path, part_name="test_part") 

33 

34 with patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) as create: 

35 create.return_value = False 

36 

37 with pytest.raises(AssertionError) as exception_info: 

38 project.create_vivado_project_if_needed() 

39 

40 assert str(exception_info.value) == "Failed to create Vivado IP core project" 

41 

42 

43@pytest.fixture 

44def ip_cores_test(tmp_path): 

45 class IpCoresTest: 

46 def __init__(self): 

47 self.project_folder = tmp_path / "ip_project" 

48 self.modules_folder = tmp_path / "modules" 

49 

50 self.apa_tcl = create_file(self.modules_folder / "apa" / "ip_cores" / "apa.tcl", "apa") 

51 self.hest_tcl = create_file( 

52 self.modules_folder / "hest" / "ip_cores" / "hest.tcl", "hest" 

53 ) 

54 

55 modules = get_modules([self.modules_folder]) 

56 self.vivado_ip_cores = VivadoIpCores(modules, self.project_folder, part_name="-") 

57 

58 # Create initial hash and (empty) compile order file 

59 self.vivado_ip_cores._save_hash() # pylint: disable=protected-access 

60 self.create_compile_order_file() 

61 

62 def create_compile_order_file(self): 

63 create_file(self.vivado_ip_cores.compile_order_file) 

64 

65 return IpCoresTest() 

66 

67 

68# False positive for pytest fixtures 

69# pylint: disable=redefined-outer-name 

70 

71 

72@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

73def test_should_not_recreate(create, ip_cores_test): 

74 assert not ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

75 create.assert_not_called() 

76 

77 

78@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

79def test_should_recreate_if_compile_order_file_is_missing(create, ip_cores_test): 

80 delete(ip_cores_test.vivado_ip_cores.compile_order_file) 

81 assert ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

82 create.assert_called_once() 

83 

84 

85@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

86def test_should_recreate_if_hash_file_is_missing(create, ip_cores_test): 

87 delete(ip_cores_test.vivado_ip_cores._hash_file) # pylint: disable=protected-access 

88 assert ip_cores_test.vivado_ip_cores.create_vivado_project_if_needed() 

89 create.assert_called_once() 

90 

91 

92@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

93def test_should_not_recreate_if_nothing_is_changed(create, ip_cores_test): 

94 # This test shows that the pattern used in the upcoming tests: 

95 # change something -> get modules -> create new VivadoIpCores object 

96 # should not result in a recreate unless we actually change something. 

97 modules = get_modules([ip_cores_test.modules_folder]) 

98 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

99 

100 assert not vivado_ip_cores.create_vivado_project_if_needed() 

101 create.assert_not_called() 

102 

103 

104@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

105def test_should_recreate_if_ip_core_file_is_added(create, ip_cores_test): 

106 create_file(ip_cores_test.modules_folder / "zebra" / "ip_cores" / "zebra.tcl", "zebra") 

107 modules = get_modules([ip_cores_test.modules_folder]) 

108 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

109 

110 assert vivado_ip_cores.create_vivado_project_if_needed() 

111 create.assert_called_once() 

112 

113 

114@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

115def test_should_recreate_if_ip_core_file_is_removed(create, ip_cores_test): 

116 delete(ip_cores_test.hest_tcl) 

117 modules = get_modules([ip_cores_test.modules_folder]) 

118 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

119 

120 assert vivado_ip_cores.create_vivado_project_if_needed() 

121 create.assert_called_once() 

122 

123 

124@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

125def test_should_recreate_if_ip_core_file_is_changed(create, ip_cores_test): 

126 create_file(ip_cores_test.apa_tcl, "blaha blaha") 

127 modules = get_modules([ip_cores_test.modules_folder]) 

128 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

129 

130 assert vivado_ip_cores.create_vivado_project_if_needed() 

131 create.assert_called_once() 

132 

133 

134@patch("tsfpga.vivado.ip_cores.VivadoIpCoreProject.create", autospec=True) 

135def test_ip_core_variables(create, ip_cores_test): 

136 modules = [MagicMock(spec=BaseModule)] 

137 

138 modules[0].get_ip_core_files.return_value = [IpCoreFile(path=ip_cores_test.apa_tcl)] 

139 

140 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

141 

142 assert vivado_ip_cores.create_vivado_project_if_needed() 

143 assert create.call_count == 1 

144 ip_cores_test.create_compile_order_file() 

145 

146 # Should not recreate until we change something 

147 assert not vivado_ip_cores.create_vivado_project_if_needed() 

148 assert create.call_count == 1 

149 

150 # Adding variables should recreate 

151 modules[0].get_ip_core_files.return_value = [ 

152 IpCoreFile(path=ip_cores_test.apa_tcl, zz="123", aa="456") 

153 ] 

154 

155 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

156 

157 assert vivado_ip_cores.create_vivado_project_if_needed() 

158 assert create.call_count == 2 

159 ip_cores_test.create_compile_order_file() 

160 

161 # Changing order of variables should not recreate 

162 modules[0].get_ip_core_files.return_value = [ 

163 IpCoreFile(path=ip_cores_test.apa_tcl, aa="456", zz="123") 

164 ] 

165 

166 vivado_ip_cores = VivadoIpCores(modules, ip_cores_test.project_folder, part_name="-") 

167 

168 assert not vivado_ip_cores.create_vivado_project_if_needed() 

169 assert create.call_count == 2