diff --git a/pyproject.toml b/pyproject.toml index dbb549f1..d03d6613 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -149,7 +149,6 @@ addopts = [ "-p", "no:logging", "--tb=short", "--color=yes", - "--tavern-setup-init-logging", ] norecursedirs = [ ".git", diff --git a/tavern/_core/schema/extensions.py b/tavern/_core/schema/extensions.py index 61eee0e5..7a7bfcc4 100644 --- a/tavern/_core/schema/extensions.py +++ b/tavern/_core/schema/extensions.py @@ -1,6 +1,6 @@ import os import re -from typing import Union +from typing import List, Union from pykwalify.types import is_bool, is_float, is_int @@ -133,29 +133,42 @@ def check_usefixtures(value, rule_obj, path) -> bool: return True -def validate_grpc_status_is_valid_or_list_of_names(value, rule_obj, path): +def validate_grpc_status_is_valid_or_list_of_names( + value: Union[List[str], str, int], rule_obj, path +): """Validate GRPC statuses https://github.com/grpc/grpc/blob/master/doc/statuscodes.md""" # pylint: disable=unused-argument - err_msg = "status has to be an valid grpc status name (got {})".format(value) - - if not isinstance(value, list) and not is_grpc_status(value): - raise BadSchemaError(err_msg) + err_msg = ( + "status has to be an valid grpc status code, name, or list (got {})".format( + value + ) + ) - if isinstance(value, list): + if isinstance(value, (str, int)): + if not is_grpc_status(value): + raise BadSchemaError(err_msg) + elif isinstance(value, list): if not all(is_grpc_status(i) for i in value): raise BadSchemaError(err_msg) + else: + raise BadSchemaError(err_msg) return True -def is_grpc_status(value): - value = value.upper() - +def is_grpc_status(value: Union[str, int]): from grpc import StatusCode - for status in StatusCode: - if status.name == value: - return True + if isinstance(value, str): + value = value.upper() + for status in StatusCode: + if status.name == value: + return True + elif isinstance(value, int): + for status in StatusCode: + if status.value[0] == value: + return True + return False diff --git a/tests/unit/test_extensions.py b/tests/unit/test_extensions.py new file mode 100644 index 00000000..24ba0802 --- /dev/null +++ b/tests/unit/test_extensions.py @@ -0,0 +1,21 @@ +import pytest + +from tavern._core import exceptions +from tavern._core.schema.extensions import ( + validate_grpc_status_is_valid_or_list_of_names as validate_grpc, +) + + +class TestGrpcCodes: + @pytest.mark.parametrize("code", ("UNAVAILABLE", "unavailable", "ok", 14, 0)) + def test_validate_grpc_valid_status(self, code): + assert True is validate_grpc(code, None, None) + assert True is validate_grpc([code], None, None) + + @pytest.mark.parametrize("code", (-1, "fo", "J", {"status": "OK"})) + def test_validate_grpc_invalid_status(self, code): + with pytest.raises(exceptions.BadSchemaError): + assert False is validate_grpc(code, None, None) + + with pytest.raises(exceptions.BadSchemaError): + assert False is validate_grpc([code], None, None) diff --git a/tox-integration.ini b/tox-integration.ini index 518eb47f..9a7b7abc 100644 --- a/tox-integration.ini +++ b/tox-integration.ini @@ -36,7 +36,7 @@ commands = ; docker compose build docker compose up --build -d python -m pytest --collect-only - python -m pytest --tavern-global-cfg={toxinidir}/tests/integration/global_cfg.yaml --cov tavern {posargs} + python -m pytest --tavern-global-cfg={toxinidir}/tests/integration/global_cfg.yaml --cov tavern {posargs} --tavern-setup-init-logging generic: py.test --tavern-global-cfg={toxinidir}/tests/integration/global_cfg.yaml -n 3 generic: tavern-ci --stdout . --tavern-global-cfg={toxinidir}/tests/integration/global_cfg.yaml