1
1
# This script is used to
2
2
3
- import yang as ly
3
+ import libyang as ly
4
4
import logging
5
5
import argparse
6
6
import sys
7
7
import ijson
8
8
import json
9
+ import pytest
9
10
#import sonic_yang as sy
10
11
from glob import glob
11
12
from os import listdir
@@ -39,30 +40,27 @@ class Test_yang_models:
39
40
def initTest (self ):
40
41
self .defaultYANGFailure = {
41
42
'Must' : ['Must condition' , 'not satisfied' ],
42
- 'InvalidValue' : ['Invalid value' ], # libyang3: ['Invalid', ' value', 'Data path']
43
- 'LeafRef' : ['Leafref' , 'non-existing' ], #libyang3: [' Invalid leafref', 'no target instance']
43
+ 'InvalidValue' : ['Invalid' , ' value' , 'Data path' ],
44
+ 'LeafRef' : ['Invalid leafref' , 'no target instance' ],
44
45
'When' : ['When condition' , 'not satisfied' ],
45
- 'Pattern' : ['pattern' , 'does not satisfy' ], #libyang3: ['pattern', ' Unsatisfied pattern']
46
- 'Mandatory' : ['required element' , 'Missing' ], #libyang3: [' Mandatory node', 'does not exist']
46
+ 'Pattern' : ['pattern' , 'Unsatisfied pattern' ],
47
+ 'Mandatory' : ['Mandatory node' , 'does not exist' ],
47
48
'Verify' : ['verified' ],
48
- 'Range' : ['does not satisfy' , 'range' ], #libyang3: [' Unsatisfied range']
49
+ 'Range' : ['Unsatisfied range' ],
49
50
'MinElements' : ['Too few' ],
50
51
'MaxElements' : ['Too many' ],
51
- 'UnknownElement' : ['Unknown element ' ],
52
+ 'UnknownElement' : ['not found as a child ' ],
52
53
'None' : [],
53
- # New keys are needed for libyang3's messages which are different. Go
54
- # ahead and add them now with the libyang1 values (which are duplicates
55
- # of the above). This will make migrating to libyang3 easier with less
56
- # code review.
57
- 'Length' : ['does not satisfy' , 'range' ], # libyang3: ['Unsatisfied length']
58
- 'DecimalFractionExceed' : ['Invalid value' ], # libyang3: ['Value', 'exceeds defined number', 'fraction digits']
59
- 'Bounds' : ['Invalid value' ], #libyang3 ['Value', 'out of type', 'min/max bounds'],
60
- 'ListKey' : ['Missing required element' ], #libyang3 ['List instance is missing its key']
61
- 'DateTime' : ['pattern' , 'does not satisfy' ], #libyang3: ['Invalid date-and-time']
62
- 'IPv4' : ['pattern' , 'does not satisfy' ], #libyang3 ['Failed to convert IPv4 address'],
54
+ 'Length' : ['Unsatisfied length' ],
55
+ 'DecimalFractionExceed' : ['Value' , 'exceeds defined number' , 'fraction digits' ],
56
+ 'Bounds' : ['Value' , 'out of type' , 'min/max bounds' ],
57
+ 'ListKey' : ['List instance is missing its key' ],
58
+ 'DateTime' : ['Invalid date-and-time' ],
59
+ 'IPv4' : ['Failed to convert IPv4 address' ],
63
60
}
64
61
65
62
self .ExceptionTests = { }
63
+ self .FailedTests = []
66
64
67
65
for test_file in glob ("./tests/yang_model_tests/tests/*.json" ):
68
66
try :
@@ -122,11 +120,12 @@ def loadYangModel(self, yangDir):
122
120
# load yang modules
123
121
for file in yangFiles :
124
122
log .debug (file )
125
- m = self .ctx .parse_module_path (file , ly .LYS_IN_YANG )
126
- if m is not None :
127
- log .info ("module: {} is loaded successfully" .format (m .name ()))
128
- else :
129
- log .info ("Could not load module: {}" .format (file ))
123
+ with open (file , 'r' ) as f :
124
+ m = self .ctx .parse_module_file (f , "yang" )
125
+ if m is not None :
126
+ log .info ("module: {} is loaded successfully" .format (m .name ()))
127
+ else :
128
+ log .info ("Could not load module: {}" .format (file ))
130
129
131
130
except Exception as e :
132
131
printExceptionDetails ()
@@ -178,26 +177,35 @@ def logStartTest(self, desc):
178
177
"""
179
178
def loadConfigData (self , jInput , verify = None ):
180
179
s = ""
180
+ node = None
181
+ try :
182
+ node = self .ctx .parse_data_mem (jInput , "json" , strict = True , no_state = True , json_string_datatypes = True )
183
+ except Exception as e :
184
+ printExceptionDetails ()
185
+ s = str (e )
186
+ log .info (s )
187
+ return s
188
+
181
189
try :
182
- node = self .ctx .parse_data_mem (jInput , ly .LYD_JSON , \
183
- ly .LYD_OPT_CONFIG | ly .LYD_OPT_STRICT )
184
190
# verify the data tree if asked
185
191
if verify is not None :
186
192
xpath = verify ['xpath' ]
187
193
log .info ("Verify xpath: {}" .format (xpath ))
188
- set = node .find_path (xpath )
189
- for dnode in set . data () :
194
+ nodes = node .find_all (xpath )
195
+ for dnode in nodes :
190
196
if (xpath == dnode .path ()):
191
197
log .info ("Verify dnode: {}" .format (dnode .path ()))
192
- data = dnode .print_mem (ly .LYD_JSON , ly .LYP_WITHSIBLINGS \
193
- | ly .LYP_FORMAT | ly .LYP_WD_ALL )
198
+ data = dnode .print_mem ("json" , with_siblings = True , pretty = True , include_implicit_defaults = True )
194
199
data = json .loads (data )
195
- log .info ("Verify data: {}" .format (data ))
200
+ log .info ("Verify path value {} is {} in {}" .format (verify ['key' ], verify ['value' ], data ))
201
+ assert (verify ['key' ] in data )
196
202
assert (data [verify ['key' ]] == verify ['value' ])
197
203
s = 'verified'
198
204
except Exception as e :
199
- s = str (e )
200
- log .info (s )
205
+ printExceptionDetails ()
206
+
207
+ node .free ()
208
+
201
209
return s
202
210
203
211
"""
@@ -221,9 +229,12 @@ def runExceptionTest(self, test):
221
229
log .info (desc + " Passed\n " )
222
230
return PASS
223
231
else :
224
- raise Exception ("Mismatch {} and {}" .format (eStr , s ))
232
+ errstr = "{}: Mismatch {} and {}" .format (test , eStr , s )
233
+ self .FailedTests .append (errstr )
234
+ raise Exception (errstr )
225
235
except Exception as e :
226
236
printExceptionDetails ()
237
+
227
238
log .info (desc + " Failed\n " )
228
239
return FAIL
229
240
@@ -253,7 +264,9 @@ def runVlanSpecialTest(self, test):
253
264
log .debug (jInput )
254
265
s = self .loadConfigData (json .dumps (jInput ))
255
266
if s != "" :
256
- raise Exception ("{} in not empty" .format (s ))
267
+ errstr = "{}[{}]: {} in not empty" .format (test ,i ,s )
268
+ self .FailedTests .append (errstr )
269
+ raise Exception (errstr )
257
270
return PASS
258
271
except Exception as e :
259
272
printExceptionDetails ()
@@ -282,6 +295,17 @@ def test_run_tests(self):
282
295
ret = FAIL * len (self .tests )
283
296
printExceptionDetails ()
284
297
298
+ if len (self .FailedTests ):
299
+ print ("{} Failures:" .format (len (self .FailedTests )))
300
+ log .error ("{} Failures:" .format (len (self .FailedTests )))
301
+ for x in self .FailedTests :
302
+ print (x )
303
+ log .error (x )
304
+
305
+ if self .ctx :
306
+ self .ctx .destroy ()
307
+ self .ctx = None
308
+
285
309
assert ret == 0
286
310
return
287
311
# End of Class
0 commit comments