Coverage for hdl_registers/generator/html/test/test_register_html_generator.py: 100%
84 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 20:50 +0000
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-01 20:50 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the hdl-registers project, an HDL register generator fast enough to run
5# in real time.
6# https://hdl-registers.com
7# https://github.com/hdl-registers/hdl-registers
8# --------------------------------------------------------------------------------------------------
10# Third party libraries
11import pytest
12from tsfpga.system_utils import read_file
14# First party libraries
15from hdl_registers import HDL_REGISTERS_TESTS
16from hdl_registers.generator.html.constant_table import HtmlConstantTableGenerator
17from hdl_registers.generator.html.page import HtmlPageGenerator
18from hdl_registers.generator.html.register_table import HtmlRegisterTableGenerator
19from hdl_registers.parser.toml import from_toml
22class HtmlTest:
23 def __init__(self, tmp_path):
24 self.tmp_path = tmp_path
25 self.register_list = from_toml(
26 name="caesar", toml_file=HDL_REGISTERS_TESTS / "regs_test.toml"
27 )
29 def create_html_page(self):
30 html = read_file(HtmlPageGenerator(self.register_list, self.tmp_path).create())
31 return html
33 @staticmethod
34 # pylint: disable=too-many-arguments
35 def check_register(name, index, address, mode, default_value, description, html):
36 expected = f"""
37 <tr>
38 <td><strong>{name}</strong></td>
39 <td>{index}</td>
40 <td>{address}</td>
41 <td>{mode}</td>
42 <td>{default_value}</td>
43 <td>{description}</td>
44 </tr>
45"""
46 assert expected in html, f"{expected}\n\n{html}"
48 @staticmethod
49 def check_field(name, index, default_value, html, description=None):
50 expected = f"""
51 <tr>
52 <td> <em>{name}</em></td>
53 <td> {index}</td>
54 <td></td>
55 <td></td>
56 <td>{default_value}</td>
57"""
58 if description:
59 expected += f"""\
60 <td>
61 {description}
62 </td>
63"""
65 assert expected in html, f"{expected}\n\n{html}"
67 @staticmethod
68 def check_register_array(name, length, iterator_range, description, html):
69 expected = f"""
70 <tr>
71 <td class="array_header" colspan=5>
72 Register array <strong>{name}</strong>, repeated {length} times.
73 Iterator <i>{iterator_range}.</i>
74 </td>
75 <td class="array_header">{description}</td>
76 </tr>
77"""
78 assert expected in html, f"{expected}\n\n{html}"
80 @staticmethod
81 def check_constant(name, value, html):
82 expected = f"""
83 <tr>
84 <td><strong>{name}</strong></td>
85 <td>{value}</td>
86"""
87 assert expected in html, f"{expected}\n\n{html}"
90@pytest.fixture
91def html_test(tmp_path):
92 return HtmlTest(tmp_path=tmp_path)
95# False positive for pytest fixtures
96# pylint: disable=redefined-outer-name
99def test_registers(html_test):
100 """
101 Test that all registers show up in the HTML with correct attributes.
102 """
103 html = html_test.create_html_page()
105 html_test.check_register(
106 name="config",
107 index=0,
108 address="0x0000",
109 mode="Read, Write",
110 default_value="0x14846",
111 description="A plain <strong>dummy</strong> register.",
112 html=html,
113 )
115 html_test.check_register_array(
116 name="dummies",
117 length=3,
118 iterator_range="i ∈ [0, 2]",
119 description="An <strong>array</strong> with some dummy regs",
120 html=html,
121 )
123 html_test.check_register(
124 name="first",
125 index="7 + i × 2",
126 address="0x001C + i × 0x0008",
127 mode="Read, Write",
128 default_value="0x5880",
129 description="The first register in the array.",
130 html=html,
131 )
133 html_test.check_register(
134 name="second",
135 index="8 + i × 2",
136 address="0x0020 + i × 0x0008",
137 mode="Read",
138 default_value="0xC7",
139 description="The second register in the array.",
140 html=html,
141 )
144def test_register_fields(html_test):
145 """
146 Test that all bits show up in the HTML with correct attributes.
147 """
148 html = html_test.create_html_page()
150 # Fields in plain register
151 html_test.check_field(
152 name="plain_bit_a",
153 index="0",
154 default_value="0b0",
155 description="Bit A",
156 html=html,
157 )
158 html_test.check_field(
159 name="plain_bit_vector",
160 index="4:1",
161 default_value="0b0011",
162 description="Bit <strong>vector</strong>",
163 html=html,
164 )
165 html_test.check_field(
166 name="plain_integer",
167 index="12:5",
168 default_value="66",
169 html=html,
170 )
171 html_test.check_field(
172 name="plain_enumeration",
173 index="15:13",
174 default_value="third",
175 html=html,
176 )
177 html_test.check_field(
178 name="plain_bit_b",
179 index="16",
180 default_value="0b1",
181 description="Bit B",
182 html=html,
183 )
185 # Fields in register array
186 html_test.check_field(
187 name="array_bit_a",
188 index="7",
189 default_value="0b1",
190 description="Array register bit A",
191 html=html,
192 )
193 html_test.check_field(
194 name="array_bit_b",
195 index="8",
196 default_value="0b0",
197 description="Array register bit B",
198 html=html,
199 )
200 html_test.check_field(
201 name="array_bit_vector",
202 index="13:9",
203 default_value="0b01100",
204 description="Array register bit vector",
205 html=html,
206 )
209def test_registers_and_constants(html_test):
210 """
211 Test that all constant show up in the HTML with correct attributes.
212 Should only appear if there are actually any constants set.
213 """
214 constants_text = "The following constants are part of the register interface"
216 html = html_test.create_html_page()
218 # Check that registers are there
219 assert "Registers" in html, html
220 assert "dummies" in html, html
222 # Check that constants are there
223 assert constants_text in html, html
224 html_test.check_constant(name="data_width", value=24, html=html)
225 html_test.check_constant(name="decrement", value=-8, html=html)
226 html_test.check_constant(name="enabled", value="True", html=html)
227 html_test.check_constant(name="disabled", value="False", html=html)
228 html_test.check_constant(name="rate", value="3.5", html=html)
229 html_test.check_constant(name="paragraph", value='"hello there :)"', html=html)
231 # Test again with no constants
232 html_test.register_list.constants = []
233 html = html_test.create_html_page()
235 # Registers should still be there
236 assert "Registers" in html, html
237 assert "dummies" in html, html
239 # But no constants
240 assert constants_text not in html, html
243def test_constants_and_no_registers(html_test):
244 html_test.register_list.register_objects = []
246 html = html_test.create_html_page()
248 assert "This module does not have any registers" in html, html
249 assert "dummies" not in html, html
251 assert "<h2>Constants</h2>" in html, html
252 html_test.check_constant(name="data_width", value=24, html=html)
253 html_test.check_constant(name="decrement", value=-8, html=html)
256def test_register_table_is_empty_string_if_no_registers_are_available(html_test):
257 html_test.register_list.register_objects = []
259 html = read_file(
260 HtmlRegisterTableGenerator(html_test.register_list, html_test.tmp_path).create()
261 )
262 assert html == "", html
265def test_constant_table_is_empty_string_if_no_constants_are_available(html_test):
266 html_test.register_list.constants = []
268 html = read_file(
269 HtmlConstantTableGenerator(html_test.register_list, html_test.tmp_path).create()
270 )
271 assert html == "", html