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

88 statements  

« 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# -------------------------------------------------------------------------------------------------- 

8 

9# Standard libraries 

10import io 

11from unittest.mock import Mock, patch 

12 

13# Third party libraries 

14import pytest 

15 

16# First party libraries 

17from tsfpga.vivado.build_result import BuildResult 

18from tsfpga.vivado.build_result_checker import ( 

19 DspBlocks, 

20 EqualTo, 

21 GreaterThan, 

22 LessThan, 

23 MaximumLogicLevel, 

24 Ramb, 

25 Ramb36, 

26 TotalLuts, 

27) 

28 

29 

30@patch("sys.stdout", new_callable=io.StringIO) 

31def test_size_checker_less_than_pass(mock_stdout): 

32 build_result = BuildResult(name="") 

33 build_result.synthesis_size = {"Total LUTs": 5} 

34 

35 assert TotalLuts(LessThan(10)).check(build_result) 

36 assert mock_stdout.getvalue() == "Result check passed for Total LUTs: 5 (< 10)\n" 

37 

38 

39@patch("sys.stdout", new_callable=io.StringIO) 

40def test_size_checker_less_than_fail(mock_stdout): 

41 build_result = BuildResult(name="") 

42 build_result.synthesis_size = {"Total LUTs": 5} 

43 

44 assert not TotalLuts(LessThan(5)).check(build_result) 

45 assert mock_stdout.getvalue() == "Result check failed for Total LUTs. Got 5, expected < 5.\n" 

46 

47 

48@patch("sys.stdout", new_callable=io.StringIO) 

49def test_size_checker_greater_than_pass(mock_stdout): 

50 build_result = BuildResult(name="") 

51 build_result.synthesis_size = {"Total LUTs": 5} 

52 

53 assert TotalLuts(GreaterThan(2)).check(build_result) 

54 assert mock_stdout.getvalue() == "Result check passed for Total LUTs: 5 (> 2)\n" 

55 

56 

57@patch("sys.stdout", new_callable=io.StringIO) 

58def test_size_checker_greater_than_fail(mock_stdout): 

59 build_result = BuildResult(name="") 

60 build_result.synthesis_size = {"Total LUTs": 5} 

61 

62 assert not TotalLuts(GreaterThan(5)).check(build_result) 

63 assert mock_stdout.getvalue() == "Result check failed for Total LUTs. Got 5, expected > 5.\n" 

64 

65 

66@patch("sys.stdout", new_callable=io.StringIO) 

67def test_size_checker_equal_to_pass(mock_stdout): 

68 build_result = BuildResult(name="") 

69 build_result.synthesis_size = {"RAMB36": 0, "Total LUTs": 5} 

70 

71 assert Ramb36(EqualTo(0)).check(build_result) 

72 assert TotalLuts(EqualTo(5)).check(build_result) 

73 

74 assert mock_stdout.getvalue() == ( 

75 "Result check passed for RAMB36: 0 (0)\nResult check passed for Total LUTs: 5 (5)\n" 

76 ) 

77 

78 

79@patch("sys.stdout", new_callable=io.StringIO) 

80def test_size_checker_equal_to_fail(mock_stdout): 

81 build_result = BuildResult(name="") 

82 build_result.synthesis_size = {"Total LUTs": 5} 

83 

84 assert not TotalLuts(EqualTo(50)).check(build_result) 

85 assert mock_stdout.getvalue() == "Result check failed for Total LUTs. Got 5, expected 50.\n" 

86 

87 

88def test_size_checker_dsp_blocks_has_two_names(): 

89 build_result = BuildResult(name="") 

90 

91 build_result.synthesis_size = {"DSP Blocks": 5} 

92 assert DspBlocks(EqualTo(5)).check(build_result) 

93 assert not DspBlocks(EqualTo(2)).check(build_result) 

94 

95 build_result.synthesis_size = {"DSP48 Blocks": 7} 

96 assert DspBlocks(EqualTo(7)).check(build_result) 

97 assert not DspBlocks(EqualTo(2)).check(build_result) 

98 

99 

100def test_size_checker_aggregated_ramb(): 

101 build_result = BuildResult(name="") 

102 

103 build_result.synthesis_size = {"RAMB18": 5, "RAMB36": 20} 

104 assert Ramb(EqualTo(22.5)).check(build_result) 

105 assert not Ramb(EqualTo(22)).check(build_result) 

106 

107 build_result.synthesis_size = {"RAMB18": 5, "RAMB36": 0} 

108 assert Ramb(EqualTo(2.5)).check(build_result) 

109 

110 build_result.synthesis_size = {"RAMB18": 0, "RAMB36": 20} 

111 assert Ramb(EqualTo(20)).check(build_result) 

112 

113 

114def test_size_checker_raises_exception_if_synthesis_size_is_not_set(): 

115 build_result = BuildResult(name="") 

116 build_result.synthesis_size = None 

117 

118 with pytest.raises(ValueError) as exception_info: 

119 assert Ramb36(EqualTo(0)).check(build_result) 

120 assert str(exception_info.value) == "Should only call after successful synthesis" 

121 

122 

123def test_size_checker_raises_exception_if_synthesis_size_does_not_have_requested_resource(): 

124 build_result = BuildResult(name="") 

125 build_result.synthesis_size = {"Total LUTs": 5} 

126 

127 with pytest.raises(ValueError) as exception_info: 

128 assert Ramb36(EqualTo(0)).check(build_result) 

129 assert ( 

130 str(exception_info.value) 

131 == 'Synthesis result size does not contain the requested resource: "RAMB36"' 

132 ) 

133 

134 

135@patch("sys.stdout", new_callable=io.StringIO) 

136def test_logic_level_checker_equal_to_pass(mock_stdout): 

137 build_result = Mock(spec=BuildResult) 

138 build_result.maximum_logic_level = 5 

139 

140 assert MaximumLogicLevel(EqualTo(5)).check(build_result) 

141 assert mock_stdout.getvalue() == "Result check passed for maximum logic level: 5 (5)\n" 

142 

143 

144@patch("sys.stdout", new_callable=io.StringIO) 

145def test_logic_level_checker_less_than_fail(mock_stdout): 

146 build_result = Mock(spec=BuildResult) 

147 build_result.maximum_logic_level = 11 

148 assert not MaximumLogicLevel(LessThan(7)).check(build_result) 

149 assert ( 

150 mock_stdout.getvalue() 

151 == "Result check failed for maximum logic level. Got 11, expected < 7.\n" 

152 ) 

153 

154 

155def test_logic_level_checker_raises_exception_if_logic_level_is_not_set(): 

156 build_result = BuildResult(name="") 

157 

158 with pytest.raises(ValueError) as exception_info: 

159 MaximumLogicLevel(LessThan(7)).check(build_result) 

160 assert str(exception_info.value) == "Should only call after successful synthesis"