Files
oopt-gnpy/tests/test_yang_validation.py
Jan Kundrát ddbb9b5af7 YANG: Test conversion of equipment + settings + topology into YANG
Change-Id: I9cd5915417d3a667cfec63b0cf2220df9973ee6e
2021-06-06 12:22:51 +02:00

82 lines
3.1 KiB
Python

# SPDX-License-Identifier: BSD-3-Clause
#
# Tests for YANG models of GNPy
#
# Copyright (C) 2020 Telecom Infra Project and GNPy contributors
# see LICENSE.md for a list of contributors
#
from gnpy.tools.json_io import load_equipment, load_network
from gnpy.yang import external_path, model_path
from gnpy.yang.io import create_datamodel, save_to_json
from pathlib import Path
from typing import List
import pytest
import subprocess
import json
SRC_ROOT = Path(__file__).parent.parent
def _get_basename(filename: Path) -> str:
try:
return filename.name
except AttributeError:
return filename
@pytest.mark.parametrize("yang_model", external_path().glob('*.yang'), ids=_get_basename)
def test_lint_external_yang(yang_model):
'''Run a basic linter on all third-party models'''
_validate_yang_model(yang_model, [])
@pytest.mark.parametrize("yang_model", model_path().glob('*.yang'), ids=_get_basename)
def test_lint_gnpy_yang(yang_model):
'''Run a linter on GNPy's YANG models'''
_validate_yang_model(yang_model, ('--canonical', '--strict', '--lint'))
def _validate_yang_model(filename: Path, options: List[str]):
'''Run actual validation'''
# I would have loved to use pyang programatically from here, but it seems that the API is really designed
# around that interactive use case where code just expects an OptParser as a part of the library context,
# etc.
# Given that I'm only interested in a simple pass/fail scenario, let's just invoke the linter as a standalone
# process and check if it screams.
proc = subprocess.run(
('pyang', '-p', ':'.join((str(external_path()), str(model_path()))), *options, filename),
stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, universal_newlines=True)
assert proc.stderr == ''
assert proc.stdout == ''
@pytest.fixture
def _yangson_datamodel():
return create_datamodel
@pytest.mark.parametrize("filename", (Path(__file__).parent / 'yang').glob('*.json'), ids=_get_basename)
def test_validate_yang_data(_yangson_datamodel, filename: Path):
'''Validate a JSON file against our YANG models'''
dm = _yangson_datamodel()
with open(filename, 'r') as f:
raw_json = json.load(f)
data = dm.from_raw(raw_json)
data.validate()
@pytest.mark.parametrize("expected_file, equipment_file, topology_file", (
("edfa_example.json", "gnpy/example-data/eqpt_config.json", "gnpy/example-data/edfa_example_network.json"),
("Sweden_OpenROADM_example.json", "gnpy/example-data/eqpt_config_openroadm.json", "gnpy/example-data/Sweden_OpenROADM_example_network.json"),
))
def test_conversion_to_yang(expected_file, equipment_file, topology_file):
'''Conversion from legacy JSON to self-contained YANG data'''
equipment = load_equipment(SRC_ROOT / equipment_file)
network = load_network(SRC_ROOT / topology_file, equipment)
data = save_to_json(equipment, network)
serialized = json.dumps(data, indent=2) + '\n' # files were generated via print(), hence a newline
expected = open(SRC_ROOT / 'tests' / 'yang' / 'converted' / expected_file, mode='rb').read().decode('utf-8')
assert serialized == expected