-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b90524d
commit 3b7d148
Showing
6 changed files
with
426 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
import sys | ||
import warnings | ||
from importlib import import_module | ||
from pathlib import Path | ||
from sys import path | ||
from typing import Generator | ||
from unittest import mock | ||
from re import fullmatch | ||
|
||
import pytest | ||
|
||
# Override global path to load schema from source instead of any installed version. | ||
path.insert(0, str(Path(__file__).parents[3])) | ||
|
||
from pyavd._schema.avdschema import AvdSchema | ||
from pyavd._errors import AvdValidationError | ||
|
||
|
||
# TODO: | ||
# - Test default value with required False. | ||
|
||
TEST_SCHEMA = { | ||
"type": "dict", | ||
"keys": { | ||
"test_value": { | ||
"type": "bool", | ||
"convert_types": ["int", "str"], # Part of meta schema but not implemented in converter | ||
"default": True, | ||
"valid_values": [True], | ||
"dynamic_valid_values": "valid_booleans", # Part of meta schema but not implemented in converter | ||
"required": True, | ||
"description": "Some boolean", | ||
"display_name": "Boolean", | ||
}, | ||
}, | ||
} | ||
|
||
TESTS = [ | ||
# (test_value, expected_errors: tuple, expected_error_messages: tuple) | ||
(True, None, None), # Valid value. No errors. | ||
(False, (AvdValidationError,), ("'Validation Error: test_value': 'False' is not one of [True]",)), # Valid value. Not a valid value. | ||
( | ||
11.0123, | ||
(AvdValidationError,), | ||
("'Validation Error: test_value': Invalid type 'float'. Expected a 'bool'.",) | ||
), # Invalid value. | ||
( | ||
None, | ||
(AvdValidationError,), | ||
("'Validation Error: ': Required key 'test_value' is not set in dict.",) | ||
), # Required is set, so None is not ignored. | ||
("11", None, None), # Converted to True. No errors. | ||
("", (AvdValidationError,), ("'Validation Error: test_value': 'False' is not one of [True]",)), # Converted to False. Not a valid value. | ||
(12, None, None), # Converted to True. No errors. | ||
(0, (AvdValidationError,), ("'Validation Error: test_value': 'False' is not one of [True]",)), # Converted to False. Not a valid value. | ||
] | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def avd_schema() -> AvdSchema: | ||
return AvdSchema(TEST_SCHEMA) | ||
|
||
|
||
@pytest.mark.parametrize(("test_value", "expected_errors", "expected_error_messages"), TESTS) | ||
def test_generated_schema(test_value, expected_errors: tuple | None, expected_error_messages: tuple | None, avd_schema: AvdSchema): | ||
instance ={"test_value": test_value} | ||
list(avd_schema.convert(instance)) | ||
validation_errors = list(avd_schema.validate(instance)) | ||
if expected_errors: | ||
for validation_error in validation_errors: | ||
assert isinstance(validation_error, expected_errors) | ||
assert str(validation_error) in expected_error_messages | ||
|
||
assert len(validation_errors) == len(expected_error_messages) | ||
else: | ||
# No errors expected. | ||
assert not validation_errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
import re | ||
import sys | ||
import warnings | ||
from importlib import import_module | ||
from pathlib import Path | ||
from sys import path | ||
from typing import Generator | ||
from unittest import mock | ||
|
||
import pytest | ||
|
||
# Override global path to load schema from source instead of any installed version. | ||
path.insert(0, str(Path(__file__).parents[3])) | ||
|
||
from pyavd._schema.avdschema import AvdSchema | ||
from pyavd._errors import AvdValidationError | ||
|
||
# TODO: | ||
# - Test default value with required False. | ||
# - Test dynamic keys | ||
|
||
TEST_SCHEMA = { | ||
"type": "dict", | ||
"keys": { | ||
"test_value": { | ||
"type": "dict", | ||
"default": {"pri": 1, "foo": "foo1"}, | ||
"required": True, | ||
"description": "Some string", | ||
"display_name": "String", | ||
"keys": { | ||
"pri": {"type": "int", "convert_types": ["str"]}, | ||
"foo": {"type": "str", "convert_types": ["int"]}, | ||
} | ||
}, | ||
}, | ||
} | ||
|
||
TESTS = [ | ||
# (test_value, expected_errors: tuple, expected_error_messages: tuple) | ||
({"pri": 1, "foo": "foo1"}, None, None), # Valid value. No errors. | ||
({"pri": "1", "foo": 123}, None, None), # Valid value after conversion. No errors. | ||
({}, None, None), # Valid value. No errors. | ||
( | ||
None, | ||
(AvdValidationError,), | ||
("'Validation Error: ': Required key 'test_value' is not set in dict.",), | ||
), # Required is set, so None is not ignored. | ||
( | ||
"a", | ||
(AvdValidationError,), | ||
("'Validation Error: test_value': Invalid type 'str'. Expected a 'dict'.",) | ||
), # Invalid type. | ||
] | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def avd_schema() -> AvdSchema: | ||
return AvdSchema(TEST_SCHEMA) | ||
|
||
|
||
@pytest.mark.parametrize(("test_value", "expected_errors", "expected_error_messages"), TESTS) | ||
def test_generated_schema(test_value, expected_errors: tuple | None, expected_error_messages: tuple | None, avd_schema: AvdSchema): | ||
instance ={"test_value": test_value} | ||
list(avd_schema.convert(instance)) | ||
validation_errors = list(avd_schema.validate(instance)) | ||
if expected_errors: | ||
for validation_error in validation_errors: | ||
assert isinstance(validation_error, expected_errors) | ||
assert str(validation_error) in expected_error_messages | ||
|
||
assert len(validation_errors) == len(expected_error_messages) | ||
else: | ||
# No errors expected. | ||
assert not validation_errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
import sys | ||
import warnings | ||
from importlib import import_module | ||
from pathlib import Path | ||
from sys import path | ||
from typing import Generator | ||
from unittest import mock | ||
|
||
import pytest | ||
|
||
# Override global path to load schema from source instead of any installed version. | ||
path.insert(0, str(Path(__file__).parents[3])) | ||
|
||
from pyavd._schema.avdschema import AvdSchema | ||
from pyavd._errors import AvdValidationError | ||
|
||
# TODO: | ||
# - Test Dynamic valid values. | ||
# - Test default value with required False. | ||
|
||
TEST_SCHEMA = { | ||
"type": "dict", | ||
"keys": { | ||
"test_value": { | ||
"type": "int", | ||
"convert_types": ["bool", "str", "float"], | ||
"default": 11, | ||
"min": 2, | ||
"max": 20, | ||
"valid_values": [0, 11, 22], | ||
"dynamic_valid_values": "valid_values", # Part of meta schema but not implemented in converter | ||
"required": True, | ||
"description": "Some integer", | ||
"display_name": "Integer", | ||
}, | ||
}, | ||
} | ||
|
||
TESTS = [ | ||
# (test_value, expected_errors: tuple, expected_error_messages: tuple) | ||
(11, None, None), # Valid value. No errors. | ||
(False, (AvdValidationError,), ("'Validation Error: test_value': '0' is lower than the allowed minimum of 2.",)), # False is converted to 0 which is valid but below min. | ||
( | ||
True, | ||
(AvdValidationError,), | ||
("'Validation Error: test_value': '1' is lower than the allowed minimum of 2.", "'Validation Error: test_value': '1' is not one of [0, 11, 22]"), | ||
), # True is converted to 1 which is not valid. | ||
("11", None, None), # Converted to 11. No errors. | ||
(11.0123, None, None), # Converted to 11. No errors. | ||
(None, (AvdValidationError,), ("'Validation Error: ': Required key 'test_value' is not set in dict.",)), # Required is set, so None is not ignored. | ||
(12, (AvdValidationError,), ("'Validation Error: test_value': '12' is not one of [0, 11, 22]",)), # Invalid value. | ||
([], (AvdValidationError,), ("'Validation Error: test_value': Invalid type 'list'. Expected a 'int'.",)), # Invalid type. | ||
(0, (AvdValidationError,), ("'Validation Error: test_value': '0' is lower than the allowed minimum of 2.",)), # Valid but below min. | ||
(22, (AvdValidationError,), ("'Validation Error: test_value': '22' is higher than the allowed maximum of 20.",)), # Valid but above max. | ||
] | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def avd_schema() -> AvdSchema: | ||
return AvdSchema(TEST_SCHEMA) | ||
|
||
|
||
@pytest.mark.parametrize(("test_value", "expected_errors", "expected_error_messages"), TESTS) | ||
def test_generated_schema(test_value, expected_errors: tuple | None, expected_error_messages: tuple | None, avd_schema: AvdSchema): | ||
instance ={"test_value": test_value} | ||
list(avd_schema.convert(instance)) | ||
validation_errors = list(avd_schema.validate(instance)) | ||
if expected_errors: | ||
for validation_error in validation_errors: | ||
assert isinstance(validation_error, expected_errors) | ||
assert str(validation_error) in expected_error_messages | ||
|
||
assert len(validation_errors) == len(expected_error_messages) | ||
else: | ||
# No errors expected. | ||
assert not validation_errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
import re | ||
import sys | ||
import warnings | ||
from importlib import import_module | ||
from pathlib import Path | ||
from sys import path | ||
from typing import Generator | ||
from unittest import mock | ||
|
||
import pytest | ||
|
||
# Override global path to load schema from source instead of any installed version. | ||
path.insert(0, str(Path(__file__).parents[3])) | ||
|
||
from pyavd._schema.avdschema import AvdSchema | ||
from pyavd._errors import AvdValidationError | ||
|
||
# TODO: | ||
# - Test default value with required False. | ||
|
||
TEST_SCHEMA = { | ||
"type": "dict", | ||
"keys": { | ||
"test_value": { | ||
"type": "list", | ||
"default": [{"pri": 1, "foo": "foo1"}, {"pri": 2, "foo": "foo2"}, {"pri": 3, "foo": "foo3"}], | ||
"max_length": 3, | ||
"min_length": 1, | ||
"required": True, | ||
"description": "Some string", | ||
"display_name": "String", | ||
"primary_key": "pri", | ||
"unique_keys": ["foo"], | ||
"items": { | ||
"type": "dict", | ||
"keys": { | ||
"pri": {"type": "int", "convert_types": ["str"]}, | ||
"foo": {"type": "str", "convert_types": ["int"]}, | ||
} | ||
} | ||
}, | ||
}, | ||
} | ||
|
||
TESTS = [ | ||
# (test_value, expected_errors: tuple, expected_error_messages: tuple) | ||
([{"pri": 1, "foo": "foo1"}, {"pri": 2, "foo": "foo2"}], None, None), # Valid value. No errors. | ||
([{"pri": "1", "foo": 123}, {"pri": 2, "foo": "234"}], None, None), # Valid value after conversion. No errors. | ||
([{"pri": 1, "foo": "123"}, {"pri": "1", "foo": 123}], (AvdValidationError,), ("'Validation Error: test_value[0].pri': The value '1' is not unique between all list items as required.", "'Validation Error: test_value[1].pri': The value '1' is not unique between all list items as required.", "'Validation Error: test_value[0].foo': The value '123' is not unique between all list items as required.", "'Validation Error: test_value[1].foo': The value '123' is not unique between all list items as required.")), # Collision on both primary_key and unique_keys | ||
( | ||
None, | ||
(AvdValidationError,), | ||
("'Validation Error: ': Required key 'test_value' is not set in dict.",), | ||
), # Required is set, so None is not ignored. | ||
([], (AvdValidationError,), ("'Validation Error: test_value': The value is shorter (0) than the allowed minimum of 1.",)), # Valid but below min length. | ||
([{"pri": 1, "foo": "foo1"}, {"pri": 2, "foo": "foo2"}, {"pri": 3, "foo": "foo3"}, {"pri": 4, "foo": "foo4"}], (AvdValidationError,), ("'Validation Error: test_value': The value is longer (4) than the allowed maximum of 3.",)), # Valid but amove max length. | ||
( | ||
"a", | ||
(AvdValidationError,), | ||
("'Validation Error: test_value': Invalid type 'str'. Expected a 'list'.",) | ||
), # Invalid type. | ||
] | ||
|
||
|
||
@pytest.fixture(scope="module") | ||
def avd_schema() -> AvdSchema: | ||
return AvdSchema(TEST_SCHEMA) | ||
|
||
|
||
@pytest.mark.parametrize(("test_value", "expected_errors", "expected_error_messages"), TESTS) | ||
def test_generated_schema(test_value, expected_errors: tuple | None, expected_error_messages: tuple | None, avd_schema: AvdSchema): | ||
instance ={"test_value": test_value} | ||
list(avd_schema.convert(instance)) | ||
validation_errors = list(avd_schema.validate(instance)) | ||
if expected_errors: | ||
for validation_error in validation_errors: | ||
assert isinstance(validation_error, expected_errors) | ||
assert str(validation_error) in expected_error_messages | ||
|
||
assert len(validation_errors) == len(expected_error_messages) | ||
else: | ||
# No errors expected. | ||
assert not validation_errors |
Oops, something went wrong.