Coverage for tests/unit_tests/common/test_proto_util.py: 100%
93 statements
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
1# This file is part of the Apio project
2# (C) 2016-present FPGAwars
3# Project authors:
4# * Jesús Arroyo (Jesus89) (2016-2019)
5# * Juan Gonzalez (obijuan) (2019-2024)
6# * The Apio Team (2024-present)
7# License: GPLv2
9"""
10Tests of proto_util.py
11"""
13import pytest
14from tests.conftest import ApioRunner
15from apio.common.proto.stubs.apio_testing_pb2 import MessageA, MessageB
16from apio.common.proto_util import (
17 proto_from_json_dict,
18 proto_to_json_dict,
19 check_is_required,
20 check_not_required,
21)
24def test_proto_from_dict_full(apio_runner: ApioRunner):
25 """Test parsing of a proto from a json dict with all required and
26 optional fields included."""
28 with apio_runner.in_sandbox():
30 json_dict1 = {
31 "field-b1": {
32 "field-a1": "aaa",
33 "field-a2": "bbb",
34 },
35 "field-b2": {
36 "field-a1": "ccc",
37 "field-a2": "ddd",
38 },
39 }
41 # -- Parse proto from json dict and verify
42 proto_msg = proto_from_json_dict(json_dict1, MessageB)
43 assert proto_msg is not None
45 assert proto_msg.field_b1.field_a1 == "aaa"
46 assert proto_msg.field_b1.field_a2 == "bbb"
47 assert proto_msg.field_b2.field_a1 == "ccc"
48 assert proto_msg.field_b2.field_a2 == "ddd"
50 # -- Convert back to json dict and compare.
51 json_dict2 = proto_to_json_dict(proto_msg)
53 assert json_dict2 == json_dict1
56def test_proto_from_dict_minimal(apio_runner: ApioRunner):
57 """Test parsing of a proto from a json dict with only required
58 fields included."""
60 with apio_runner.in_sandbox():
62 json_dict1 = {
63 "field-b1": {
64 "field-a1": "aaa",
65 },
66 }
68 # -- Parse proto from json dict and verify
69 proto_msg = proto_from_json_dict(json_dict1, MessageB)
70 assert proto_msg is not None
72 assert proto_msg.field_b1.field_a1 == "aaa"
74 assert not proto_msg.HasField("field_b2")
75 assert not proto_msg.field_b1.HasField("field_a2")
77 # -- Convert back to json dict and compare.
78 json_dict2 = proto_to_json_dict(proto_msg)
80 assert json_dict2 == json_dict1
83def test_proto_from_dict_missing_field(apio_runner: ApioRunner):
84 """Test parsing of a proto from a json dict with a required
85 field missing."""
87 with apio_runner.in_sandbox():
89 json_dict1 = {
90 "field-b1": {
91 # -- Required field 'field-a1' is missing.
92 "field-a2": "aaa",
93 },
94 }
96 with apio_runner.with_logger() as log:
97 proto_msg = proto_from_json_dict(json_dict1, MessageB)
98 assert proto_msg is None
99 assert "Missing required field 'field-b1.field-a1'" in log.out
102def test_proto_from_dict_unknown_field(apio_runner: ApioRunner):
103 """Test parsing of a proto from a json dict with a an unknown field."""
105 with apio_runner.in_sandbox():
107 json_dict1 = {
108 "field-b1": {"field-a1": "aaa", "no-such-field": "bbb"},
109 }
111 with apio_runner.with_logger() as log:
112 # with pytest.raises(SystemExit) as e:
113 proto_msg = proto_from_json_dict(
114 json_dict1,
115 MessageB,
116 )
117 assert proto_msg is None
118 assert "Unknown field 'no-such-field'" in log.out
121def test_check_is_required(apio_runner: ApioRunner):
122 """Test test_check_is_required()"""
124 with apio_runner.in_sandbox():
126 msg = MessageB(field_b1=MessageA(field_a1="aaa"))
128 # -- Check required fields only (success)
129 check_is_required(msg, "field_b1")
130 check_is_required(msg.field_b1, "field_a1")
131 check_is_required(msg, "field_b1.field_a1")
133 # -- Check with an optional field (failure)
134 with apio_runner.with_logger() as log:
135 with pytest.raises(SystemExit) as e:
136 check_is_required(msg, "field_b1", "field_b2")
138 assert e.value.code == 1
139 assert (
140 "Field 'field_b2' of 'apio.common.proto.MessageB' "
141 "is not required" in log.out
142 )
144 # -- Check with an optional nested field (failure)
145 with apio_runner.with_logger() as log:
146 with pytest.raises(SystemExit) as e:
147 check_is_required(msg, "field_b1", "field_b1.field_a2")
149 assert e.value.code == 1
150 assert (
151 "Field 'field_b1.field_a2' of 'apio.common.proto.MessageB' "
152 "is not required" in log.out
153 )
155 # -- Check with an unknown field (failure)
156 with apio_runner.with_logger() as log:
157 with pytest.raises(SystemExit) as e:
158 check_is_required(msg, "field_b1", "field_xyz")
160 assert e.value.code == 1
161 assert (
162 "Field 'field_xyz' is not a field of protocol buffer "
163 "message 'apio.common.proto.MessageB'" in log.out
164 )
166 # -- Check with an unknown nested field (failure)
167 with apio_runner.with_logger() as log:
168 with pytest.raises(SystemExit) as e:
169 check_is_required(msg, "field_b1", "field_b1.field_xyz")
171 assert e.value.code == 1
172 assert (
173 "Field 'field_b1.field_xyz' is not a field of protocol buffer "
174 "message 'apio.common.proto.MessageB'" in log.out
175 )
178def test_check_not_required(apio_runner: ApioRunner):
179 """Test test_check_not_required()"""
181 with apio_runner.in_sandbox():
183 msg = MessageB(field_b1=MessageA(field_a1="aaa"))
185 # -- Check optional fields only (success)
186 check_not_required(msg, "field_b2")
187 check_not_required(msg, "field_b2.field_a1")
188 check_not_required(msg, "field_b2.field_a2")
189 check_not_required(msg, "field_b1.field_a2")
190 check_not_required(msg.field_b1, "field_a2")
192 # -- Check with required field (failure)
193 with apio_runner.with_logger() as log:
194 with pytest.raises(SystemExit) as e:
195 check_not_required(msg, "field_b2", "field_b1")
197 assert e.value.code == 1
198 assert (
199 "Field 'field_b1' of 'apio.common.proto.MessageB' "
200 "is required" in log.out
201 )
203 # -- Check with an required nested field (failure)
204 with apio_runner.with_logger() as log:
205 with pytest.raises(SystemExit) as e:
206 check_not_required(msg, "field_b2", "field_b1.field_a1")
208 assert e.value.code == 1
209 assert (
210 "Field 'field_b1.field_a1' of 'apio.common.proto.MessageB' "
211 "is required" in log.out
212 )
214 # -- Check with an unknown field (failure)
215 with apio_runner.with_logger() as log:
216 with pytest.raises(SystemExit) as e:
217 check_is_required(msg, "field_b1", "field_xyz")
219 assert e.value.code == 1
220 assert (
221 "Field 'field_xyz' is not a field of protocol buffer "
222 "message 'apio.common.proto.MessageB'" in log.out
223 )
225 # -- Check with an unknown nested field (failure)
226 with apio_runner.with_logger() as log:
227 with pytest.raises(SystemExit) as e:
228 check_is_required(msg, "field_b1", "field_b1.field_xyz")
230 assert e.value.code == 1
231 assert (
232 "Field 'field_b1.field_xyz' is not a field of protocol buffer "
233 "message 'apio.common.proto.MessageB'" in log.out
234 )