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
« 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
10import io
11from unittest.mock import Mock, patch
13# Third party libraries
14import pytest
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)
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}
35 assert TotalLuts(LessThan(10)).check(build_result)
36 assert mock_stdout.getvalue() == "Result check passed for Total LUTs: 5 (< 10)\n"
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}
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"
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}
53 assert TotalLuts(GreaterThan(2)).check(build_result)
54 assert mock_stdout.getvalue() == "Result check passed for Total LUTs: 5 (> 2)\n"
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}
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"
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}
71 assert Ramb36(EqualTo(0)).check(build_result)
72 assert TotalLuts(EqualTo(5)).check(build_result)
74 assert mock_stdout.getvalue() == (
75 "Result check passed for RAMB36: 0 (0)\nResult check passed for Total LUTs: 5 (5)\n"
76 )
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}
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"
88def test_size_checker_dsp_blocks_has_two_names():
89 build_result = BuildResult(name="")
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)
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)
100def test_size_checker_aggregated_ramb():
101 build_result = BuildResult(name="")
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)
107 build_result.synthesis_size = {"RAMB18": 5, "RAMB36": 0}
108 assert Ramb(EqualTo(2.5)).check(build_result)
110 build_result.synthesis_size = {"RAMB18": 0, "RAMB36": 20}
111 assert Ramb(EqualTo(20)).check(build_result)
114def test_size_checker_raises_exception_if_synthesis_size_is_not_set():
115 build_result = BuildResult(name="")
116 build_result.synthesis_size = None
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"
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}
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 )
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
140 assert MaximumLogicLevel(EqualTo(5)).check(build_result)
141 assert mock_stdout.getvalue() == "Result check passed for maximum logic level: 5 (5)\n"
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 )
155def test_logic_level_checker_raises_exception_if_logic_level_is_not_set():
156 build_result = BuildResult(name="")
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"