Skip to content

Commit 6a9ef8c

Browse files
ganglyujudyjoseph
authored andcommitted
[sonic-cfggen]: Update UT to run yang validation (#9700)
Why I did it Config db schema generated by minigraph should run yang validation. How I did it Modify run_script to add yang validation. How to verify it Run sonic-config-engine unit test. Signed-off-by: Gang Lv [email protected]
1 parent 77ae1e8 commit 6a9ef8c

File tree

4 files changed

+59
-1
lines changed

4 files changed

+59
-1
lines changed

src/sonic-config-engine/tests/common_utils.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
import os
44
import re
55
import sys
6+
import subprocess
7+
import argparse
8+
import shlex
69

710
PY3x = sys.version_info >= (3, 0)
811
PYvX_DIR = "py3" if PY3x else "py2"
912
PYTHON_INTERPRETTER = "python3" if PY3x else "python2"
13+
YANG_MODELS_DIR = "/usr/local/yang-models"
1014

1115
def tuple_to_str(tuplestr):
1216
""" Convert Python tuple '('elem1', 'elem2')' representation into string on the for "elem1|elem2" """
@@ -33,6 +37,52 @@ def liststr_to_dict(liststr):
3337

3438
return list_obj
3539

40+
class YangWrapper(object):
41+
def __init__(self, path=YANG_MODELS_DIR):
42+
"""
43+
sonic_yang only supports python3
44+
"""
45+
if PY3x:
46+
import sonic_yang
47+
self.yang_parser = sonic_yang.SonicYang(path)
48+
self.yang_parser.loadYangModel()
49+
self.test_dir = os.path.dirname(os.path.realpath(__file__))
50+
self.script_file = PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen')
51+
52+
def validate(self, argument):
53+
"""
54+
Raise exception when yang validation failed
55+
"""
56+
if PY3x and "-m" in argument:
57+
import sonic_yang
58+
parser=argparse.ArgumentParser(description="Render configuration file from minigraph data and jinja2 template.")
59+
parser.add_argument("-m", "--minigraph", help="minigraph xml file", nargs='?', const='/etc/sonic/minigraph.xml')
60+
parser.add_argument("-k", "--hwsku", help="HwSKU")
61+
parser.add_argument("-n", "--namespace", help="namespace name", nargs='?', const=None, default=None)
62+
parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None)
63+
parser.add_argument("-S", "--hwsku-config", help="hwsku config file, used with -p and -m or -k", nargs='?', const=None)
64+
args, unknown = parser.parse_known_args(shlex.split(argument))
65+
66+
print('\n Validating yang schema')
67+
cmd = self.script_file + ' -m ' + args.minigraph
68+
if args.hwsku is not None:
69+
cmd += ' -k ' + args.hwsku
70+
if args.hwsku_config is not None:
71+
cmd += ' -S ' + args.hwsku_config
72+
if args.port_config is not None:
73+
cmd += ' -p ' + args.port_config
74+
if args.namespace is not None:
75+
cmd += ' -n ' + args.namespace
76+
cmd += ' --print-data'
77+
output = subprocess.check_output(cmd, shell=True).decode()
78+
try:
79+
self.yang_parser.loadData(configdbJson=json.loads(output))
80+
self.yang_parser.validate_data_tree()
81+
except sonic_yang.SonicYangException as e:
82+
print("yang data generated from %s is not valid: %s"%(args.minigraph, str(e)))
83+
return False
84+
return True
85+
3686
def cmp(file1, file2):
3787
""" compare files """
3888
try:
@@ -43,4 +93,3 @@ def cmp(file1, file2):
4393
return obj1 == obj2
4494
except:
4595
return filecmp.cmp(file1, file2)
46-

src/sonic-config-engine/tests/test_cfggen.py

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
class TestCfgGen(TestCase):
1515

1616
def setUp(self):
17+
self.yang = utils.YangWrapper()
1718
self.test_dir = os.path.dirname(os.path.realpath(__file__))
1819
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen')
1920
self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml')
@@ -50,6 +51,8 @@ def tearDown(self):
5051

5152
def run_script(self, argument, check_stderr=False, verbose=False):
5253
print('\n Running sonic-cfggen ' + argument)
54+
self.assertTrue(self.yang.validate(argument))
55+
5356
if check_stderr:
5457
output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True)
5558
else:

src/sonic-config-engine/tests/test_minigraph_case.py

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
class TestCfgGenCaseInsensitive(TestCase):
1414

1515
def setUp(self):
16+
self.yang = utils.YangWrapper()
1617
self.test_dir = os.path.dirname(os.path.realpath(__file__))
1718
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen')
1819
self.sample_graph = os.path.join(self.test_dir, 'simple-sample-graph-case.xml')
@@ -23,6 +24,8 @@ def setUp(self):
2324

2425
def run_script(self, argument, check_stderr=False):
2526
print('\n Running sonic-cfggen ' + argument)
27+
self.assertTrue(self.yang.validate(argument))
28+
2629
if check_stderr:
2730
output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True)
2831
else:

src/sonic-config-engine/tests/test_multinpu_cfggen.py

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
class TestMultiNpuCfgGen(TestCase):
2121

2222
def setUp(self):
23+
self.yang = utils.YangWrapper()
2324
self.test_dir = os.path.dirname(os.path.realpath(__file__))
2425
self.test_data_dir = os.path.join(self.test_dir, 'multi_npu_data')
2526
self.script_file = utils.PYTHON_INTERPRETTER + ' ' + os.path.join(self.test_dir, '..', 'sonic-cfggen')
@@ -34,6 +35,8 @@ def setUp(self):
3435

3536
def run_script(self, argument, check_stderr=False):
3637
print('\n Running sonic-cfggen ' + argument)
38+
self.assertTrue(self.yang.validate(argument))
39+
3740
if check_stderr:
3841
output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True)
3942
else:

0 commit comments

Comments
 (0)