mirror of
https://github.com/netbox-community/devicetype-library.git
synced 2024-11-07 09:04:35 +01:00
Combine validation and duplication tests for efficiency
This commit is contained in:
parent
5944c33552
commit
c1f6cecb21
2
.github/workflows/validation.yml
vendored
2
.github/workflows/validation.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.6
|
||||
python-version: 3.8
|
||||
- name: Install dependencies
|
||||
run: pip install -r requirements.txt
|
||||
- name: Lint YAML files
|
||||
|
@ -3,7 +3,7 @@ import json
|
||||
import os
|
||||
import pytest
|
||||
import yaml
|
||||
from jsonschema import validate, RefResolver, Draft4Validator
|
||||
from jsonschema import RefResolver, Draft4Validator
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
|
||||
@ -12,6 +12,18 @@ SCHEMAS = (
|
||||
('module-types', 'moduletype.json'),
|
||||
)
|
||||
|
||||
COMPONENT_TYPES = (
|
||||
'console-ports',
|
||||
'console-server-ports',
|
||||
'power-ports',
|
||||
'power-outlets',
|
||||
'interfaces',
|
||||
'front-ports',
|
||||
'rear-ports',
|
||||
'device-bays',
|
||||
'module-bays',
|
||||
)
|
||||
|
||||
|
||||
def _get_definition_files():
|
||||
"""
|
||||
@ -29,13 +41,14 @@ def _get_definition_files():
|
||||
assert schema, f"Schema definition for {path} is empty!"
|
||||
|
||||
# Map each definition file to its schema
|
||||
for f in glob.glob(f"{path}/*/*", recursive=True):
|
||||
for f in sorted(glob.glob(f"{path}/*/*", recursive=True)):
|
||||
ret.append((f, schema))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
definition_files = _get_definition_files()
|
||||
known_slugs = set()
|
||||
|
||||
|
||||
def test_environment():
|
||||
@ -49,7 +62,7 @@ def test_environment():
|
||||
@pytest.mark.parametrize(('file_path', 'schema'), definition_files)
|
||||
def test_definitions(file_path, schema):
|
||||
"""
|
||||
Validate each definition file using the provided JSON schema.
|
||||
Validate each definition file using the provided JSON schema and check for duplicate entries.
|
||||
"""
|
||||
# Check file extension
|
||||
assert file_path.split('.')[-1] in ('yaml', 'yml'), f"Invalid file extension: {file_path}"
|
||||
@ -64,8 +77,27 @@ def test_definitions(file_path, schema):
|
||||
# Load YAML data from file
|
||||
definition = yaml.load(content, Loader=yaml.SafeLoader)
|
||||
|
||||
# Validate YAML definition against the supplied schema
|
||||
try:
|
||||
resolver = RefResolver(f'file://{os.getcwd()}/schema/devicetype.json', schema)
|
||||
Draft4Validator(schema, resolver=resolver).validate(definition)
|
||||
except ValidationError as e:
|
||||
pytest.fail(f"{file_path} failed validation: {e}", False)
|
||||
|
||||
# Check for duplicate slug
|
||||
if file_path.startswith('device-types/'):
|
||||
slug = definition.get('slug')
|
||||
if slug and slug in known_slugs:
|
||||
pytest.fail(f'{file_path} device type has duplicate slug "{slug}"', False)
|
||||
elif slug:
|
||||
known_slugs.add(slug)
|
||||
|
||||
# Check for duplicate components
|
||||
for component_type in COMPONENT_TYPES:
|
||||
known_names = set()
|
||||
defined_components = definition.get(component_type, [])
|
||||
for idx, component in enumerate(defined_components):
|
||||
name = component.get('name')
|
||||
if name in known_names:
|
||||
pytest.fail(f'Duplicate entry "{name}" in {component_type} list', False)
|
||||
known_names.add(name)
|
||||
|
@ -1,61 +0,0 @@
|
||||
import glob
|
||||
import json
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
KNOWN_MODELS = {}
|
||||
|
||||
def _get_definition_files():
|
||||
"""
|
||||
Return a list of all definition files.
|
||||
"""
|
||||
return [f for f in glob.glob("device-types/*/*", recursive=True)]
|
||||
|
||||
def test_environment():
|
||||
"""
|
||||
Run basic sanity checks on the environment to ensure tests are running correctly.
|
||||
"""
|
||||
# Validate that definition files exist
|
||||
assert _get_definition_files(), "No definition files found!"
|
||||
|
||||
@pytest.mark.parametrize("file_path", _get_definition_files())
|
||||
def test_dupes(file_path):
|
||||
# Check file extension
|
||||
assert file_path.split('.')[-1] in ('yaml', 'yml'), f"Invalid file extension: {file_path}"
|
||||
|
||||
# Read file
|
||||
with open(file_path) as definition_file:
|
||||
content = definition_file.read()
|
||||
|
||||
# Check for trailing newline
|
||||
assert content[-1] == '\n', "Missing trailing newline"
|
||||
|
||||
# Load YAML data
|
||||
definition = yaml.load(content, Loader=yaml.SafeLoader)
|
||||
|
||||
slug = definition.get('slug')
|
||||
|
||||
if KNOWN_MODELS.get(slug, None) is not None:
|
||||
pytest.fail(f"{file_path} is a duplicate device_type for {slug}", False)
|
||||
|
||||
KNOWN_MODELS[slug] = definition.get('model')
|
||||
|
||||
def test_components(type):
|
||||
KNOWN = []
|
||||
components = definition.get(type, None)
|
||||
|
||||
if components is not None:
|
||||
for idx,component in enumerate(components):
|
||||
name = component.get('name')
|
||||
if name in KNOWN:
|
||||
pytest.fail(f'Duplicate {type} "{name}" in {file_path}', False)
|
||||
KNOWN.append(name)
|
||||
|
||||
test_components('interfaces')
|
||||
test_components('device-bays')
|
||||
test_components('front-ports')
|
||||
test_components('rear-ports')
|
||||
test_components('power-ports')
|
||||
test_components('power-outlets')
|
||||
test_components('console-ports')
|
||||
test_components('console-server-ports')
|
Loading…
Reference in New Issue
Block a user