Skip to content

Commit 26fa0ab

Browse files
authored
Skip schema validation on call (#650)
Implements schema validation skipping when running `call`. `skip_schema_validation` is defaulted to `False`, and once set to `True`, will skip schema validation of both request and response. Implements #315.
1 parent c01f634 commit 26fa0ab

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

ocpp/charge_point.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,9 @@ async def _handle_call(self, msg):
361361
pass
362362
return response
363363

364-
async def call(self, payload, suppress=True, unique_id=None):
364+
async def call(
365+
self, payload, suppress=True, unique_id=None, skip_schema_validation=False
366+
):
365367
"""
366368
Send Call message to client and return payload of response.
367369
@@ -382,6 +384,9 @@ async def call(self, payload, suppress=True, unique_id=None):
382384
set to False, an exception will be raised for users to handle this
383385
CallError.
384386
387+
Schema validation can be skipped for the request and the response
388+
for this call by setting `skip_schema_validation` to `True`.
389+
385390
"""
386391
camel_case_payload = snake_to_camel_case(serialize_as_dict(payload))
387392

@@ -400,7 +405,8 @@ async def call(self, payload, suppress=True, unique_id=None):
400405
payload=remove_nones(camel_case_payload),
401406
)
402407

403-
validate_payload(call, self._ocpp_version)
408+
if not skip_schema_validation:
409+
validate_payload(call, self._ocpp_version)
404410

405411
# Use a lock to prevent make sure that only 1 message can be send at a
406412
# a time.
@@ -421,7 +427,7 @@ async def call(self, payload, suppress=True, unique_id=None):
421427
if suppress:
422428
return
423429
raise response.to_exception()
424-
else:
430+
elif not skip_schema_validation:
425431
response.action = call.action
426432
validate_payload(response, self._ocpp_version)
427433

tests/v16/conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from dataclasses import dataclass
12
from unittest.mock import AsyncMock
23

34
import pytest
@@ -50,6 +51,15 @@ def mock_boot_request():
5051
)
5152

5253

54+
@pytest.fixture
55+
def mock_invalid_boot_request():
56+
@dataclass
57+
class BootNotification:
58+
custom_field: str
59+
60+
return BootNotification(custom_field="custom_field")
61+
62+
5363
@pytest.fixture
5464
def mock_base_central_system(base_central_system):
5565
mock_result_call = CallResult(

tests/v16/test_v16_charge_point.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,29 @@ async def test_call_without_unique_id_should_return_a_random_value(
263263
) = mock_base_central_system._get_specific_response.call_args_list[0][0]
264264
# Check the actual unique id is equals to the one internally generated
265265
assert actual_unique_id == expected_unique_id
266+
267+
268+
@pytest.mark.asyncio
269+
async def test_call_skip_schema_validation(
270+
mock_invalid_boot_request, mock_base_central_system
271+
):
272+
"""
273+
Test that schema validation is skipped for an invalid boot notification request.
274+
275+
"""
276+
277+
expected_unique_id = "12345"
278+
# Call the method being tested with an invalid boot notification request
279+
# and a unique_id as a parameter
280+
await mock_base_central_system.call(
281+
mock_invalid_boot_request,
282+
unique_id=expected_unique_id,
283+
skip_schema_validation=True,
284+
)
285+
(
286+
actual_unique_id,
287+
_,
288+
) = mock_base_central_system._get_specific_response.call_args_list[0][0]
289+
290+
# Check the actual unique id is equals to the one passed to the call method
291+
assert actual_unique_id == expected_unique_id

0 commit comments

Comments
 (0)