Coverage for tsfpga/vivado/test/test_build_result_checker.py: 100%
76 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-06 20:51 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-06 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# --------------------------------------------------------------------------------------------------
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 LessThan,
22 MaximumLogicLevel,
23 Ramb,
24 Ramb36,
25 TotalLuts,
26)
29@patch("sys.stdout", new_callable=io.StringIO)
30def test_size_checker_less_than_pass(mock_stdout):
31 build_result = BuildResult(name="")
32 build_result.synthesis_size = {"Total LUTs": 5}
34 assert TotalLuts(LessThan(10)).check(build_result)
35 assert mock_stdout.getvalue() == "Result check passed for Total LUTs: 5 (< 10)\n"
38@patch("sys.stdout", new_callable=io.StringIO)
39def test_size_checker_less_than_fail(mock_stdout):
40 build_result = BuildResult(name="")
41 build_result.synthesis_size = {"Total LUTs": 5}
43 assert not TotalLuts(LessThan(5)).check(build_result)
44 assert mock_stdout.getvalue() == "Result check failed for Total LUTs. Got 5, expected < 5.\n"
47@patch("sys.stdout", new_callable=io.StringIO)
48def test_size_checker_equal_to_pass(mock_stdout):
49 build_result = BuildResult(name="")
50 build_result.synthesis_size = {"RAMB36": 0, "Total LUTs": 5}
52 assert Ramb36(EqualTo(0)).check(build_result)
53 assert TotalLuts(EqualTo(5)).check(build_result)
55 assert mock_stdout.getvalue() == (
56 "Result check passed for RAMB36: 0 (0)\nResult check passed for Total LUTs: 5 (5)\n"
57 )
60@patch("sys.stdout", new_callable=io.StringIO)
61def test_size_checker_equal_to_fail(mock_stdout):
62 build_result = BuildResult(name="")
63 build_result.synthesis_size = {"Total LUTs": 5}
65 assert not TotalLuts(EqualTo(50)).check(build_result)
66 assert mock_stdout.getvalue() == "Result check failed for Total LUTs. Got 5, expected 50.\n"
69def test_size_checker_dsp_blocks_has_two_names():
70 build_result = BuildResult(name="")
72 build_result.synthesis_size = {"DSP Blocks": 5}
73 assert DspBlocks(EqualTo(5)).check(build_result)
74 assert not DspBlocks(EqualTo(2)).check(build_result)
76 build_result.synthesis_size = {"DSP48 Blocks": 7}
77 assert DspBlocks(EqualTo(7)).check(build_result)
78 assert not DspBlocks(EqualTo(2)).check(build_result)
81def test_size_checker_aggregated_ramb():
82 build_result = BuildResult(name="")
84 build_result.synthesis_size = {"RAMB18": 5, "RAMB36": 20}
85 assert Ramb(EqualTo(22.5)).check(build_result)
86 assert not Ramb(EqualTo(22)).check(build_result)
88 build_result.synthesis_size = {"RAMB18": 5, "RAMB36": 0}
89 assert Ramb(EqualTo(2.5)).check(build_result)
91 build_result.synthesis_size = {"RAMB18": 0, "RAMB36": 20}
92 assert Ramb(EqualTo(20)).check(build_result)
95def test_size_checker_raises_exception_if_synthesis_size_is_not_set():
96 build_result = BuildResult(name="")
97 build_result.synthesis_size = None
99 with pytest.raises(ValueError) as exception_info:
100 assert Ramb36(EqualTo(0)).check(build_result)
101 assert str(exception_info.value) == "Should only call after successful synthesis"
104def test_size_checker_raises_exception_if_synthesis_size_does_not_have_requested_resource():
105 build_result = BuildResult(name="")
106 build_result.synthesis_size = {"Total LUTs": 5}
108 with pytest.raises(ValueError) as exception_info:
109 assert Ramb36(EqualTo(0)).check(build_result)
110 assert (
111 str(exception_info.value)
112 == 'Synthesis result size does not contain the requested resource: "RAMB36"'
113 )
116@patch("sys.stdout", new_callable=io.StringIO)
117def test_logic_level_checker_equal_to_pass(mock_stdout):
118 build_result = Mock(spec=BuildResult)
119 build_result.maximum_logic_level = 5
121 assert MaximumLogicLevel(EqualTo(5)).check(build_result)
122 assert mock_stdout.getvalue() == "Result check passed for maximum logic level: 5 (5)\n"
125@patch("sys.stdout", new_callable=io.StringIO)
126def test_logic_level_checker_less_than_fail(mock_stdout):
127 build_result = Mock(spec=BuildResult)
128 build_result.maximum_logic_level = 11
129 assert not MaximumLogicLevel(LessThan(7)).check(build_result)
130 assert (
131 mock_stdout.getvalue()
132 == "Result check failed for maximum logic level. Got 11, expected < 7.\n"
133 )
136def test_logic_level_checker_raises_exception_if_logic_level_is_not_set():
137 build_result = BuildResult(name="")
139 with pytest.raises(ValueError) as exception_info:
140 MaximumLogicLevel(LessThan(7)).check(build_result)
141 assert str(exception_info.value) == "Should only call after successful synthesis"