Skip to content

Commit 9673baa

Browse files
Refactored names of functions, improved consistency of strings
1 parent 958d962 commit 9673baa

File tree

4 files changed

+85
-81
lines changed

4 files changed

+85
-81
lines changed

nmostesting/IS14Utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def _do_request(self, test, method, url, **kwargs):
5555
if not valid:
5656
raise NMOSTestException(test.FAIL(f"{r} for {method}: {url}"))
5757
try:
58-
self.validate_reference_datatype_schema(test, r.json(), "NcMethodResult", f"{method} :{url} ")
58+
self.reference_datatype_schema_validate(test, r.json(), "NcMethodResult", f"{method} :{url} ")
5959
except ValueError as e:
6060
raise NMOSTestException(test.FAIL(f"Error: {e.args[0]} for {method}: {url}"))
6161
except NMOSTestException as e:

nmostesting/MS05Utils.py

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def query_device_model(self, test):
109109
self.device_model_metadata set on Device Model validation error.
110110
NMOSTestException raised if unable to query Device Model """
111111
if not self.device_model:
112-
self.device_model = self._nc_object_factory(
112+
self.device_model = self.create_device_model(
113113
test,
114114
StandardClassIds.NCBLOCK.value,
115115
self.ROOT_BLOCK_OID,
@@ -302,33 +302,45 @@ def get_datatype_schema(self, test, type_name):
302302

303303
return self.datatype_schemas.get(type_name)
304304

305-
def validate_reference_datatype_schema(self, test, payload, datatype_name, context=""):
305+
def queried_datatype_schema_validate(self, test, payload, datatype_name, context=""):
306+
"""Validate payload against datatype schema queried from Node under Test Class Manager"""
307+
datatype_schema = self.get_datatype_schema(test, datatype_name)
308+
self._validate_schema(test, payload, datatype_schema, f"{context}{datatype_name}")
309+
310+
def reference_datatype_schema_validate(self, test, payload, datatype_name, context=""):
306311
"""Validate payload against reference datatype schema"""
307312
context += f"{datatype_name}: "
308-
self.validate_schema(test, payload, self.reference_datatype_schemas[datatype_name], context)
313+
self._validate_schema(test, payload, self.reference_datatype_schemas[datatype_name],
314+
f"{context}{datatype_name}")
309315

310-
def validate_schema(self, test, payload, schema, context=""):
311-
"""Delegates to validate. Raises NMOSTestExceptions on error"""
316+
def _validate_schema(self, test, payload, schema, context=""):
317+
"""Delegates to jsonschema validate. Raises NMOSTestExceptions on error"""
312318
if not schema:
313-
raise NMOSTestException(test.FAIL("Missing schema. Possible unknown type: " + context))
319+
raise NMOSTestException(test.FAIL(f"Missing schema. Possible unknown type: {context}"))
314320
try:
315321
# Validate the JSON schema is correct
316322
checker = FormatChecker(["ipv4", "ipv6", "uri"])
317323
validate(payload, schema, format_checker=checker)
318324
except ValidationError as e:
319-
raise NMOSTestException(test.FAIL(context + "Schema validation error: " + e.message))
325+
raise NMOSTestException(test.FAIL(f"{context}Schema validation error: {e.message}"))
320326
except SchemaError as e:
321-
raise NMOSTestException(test.FAIL(context + "Schema error: " + e.message))
327+
raise NMOSTestException(test.FAIL(f"{context}Schema error: {e.message}"))
322328

323329
return
324330

325331
def validate_descriptor(self, test, reference, descriptor, context=""):
326332
"""Validate descriptor against reference NcDescriptor. Raises NMOSTestException on error"""
333+
def sort_key(e):
334+
if isinstance(e, NcDescriptor):
335+
return e.name
336+
else:
337+
return e["name"]
338+
327339
non_normative_keys = ["description"]
328340

329341
# Compare disctionaries
330342
if isinstance(reference, dict):
331-
# Remove the json field if present
343+
# NcDescriptor objects have a json field that caches the json used to construct it
332344
reference.pop("json", None)
333345

334346
reference_keys = set(reference.keys())
@@ -338,35 +350,32 @@ def validate_descriptor(self, test, reference, descriptor, context=""):
338350
key_diff = (set(reference_keys) | set(descriptor_keys)) - (set(reference_keys) & set(descriptor_keys))
339351
if len(key_diff) > 0:
340352
error_description = "Missing keys " if set(key_diff) <= set(reference_keys) else "Additional keys "
341-
raise NMOSTestException(test.FAIL(context + error_description + str(key_diff)))
353+
raise NMOSTestException(test.FAIL(f"{context}{error_description}{str(key_diff)}"))
342354
for key in reference_keys:
343-
# Make sure to ignore non normative keys, but not fields that use those keys
344-
if key in non_normative_keys and not isinstance(reference[key], dict):
355+
# Ignore keys that contain non-normative information
356+
if key in non_normative_keys:
345357
continue
346358
self.validate_descriptor(test, reference[key], descriptor[key], context=context + key + "->")
347-
# We can't guarantee ordering of lists, so convert reference and descriptor to dictionaries
359+
# Compare lists
348360
elif isinstance(reference, list):
349361
if len(reference) != len(descriptor):
350-
raise NMOSTestException(test.FAIL(context + "List unexpected length. Expected: "
351-
+ str(len(reference)) + ", actual: " + str(len(descriptor))))
362+
raise NMOSTestException(test.FAIL(f"{context}List unexpected length. Expected: "
363+
f"{str(len(reference))}, actual: {str(len(descriptor))}"))
352364
if len(reference) > 0:
365+
# If comparing lists of objects or dicts then sort by name first.
366+
# Primitive arrays are unsorted as position is assumed to be important e.g. classId
353367
if isinstance(reference[0], (dict, NcDescriptor)):
354-
# Convert to dict and validate
355-
if isinstance(reference[0], NcDescriptor):
356-
references = {item.name: item.__dict__ for item in reference}
357-
else:
358-
references = {item["name"]: item for item in reference}
359-
descriptors = {item["name"]: item for item in descriptor}
360-
self.validate_descriptor(test, references, descriptors, context)
361-
else:
362-
for refvalue, value in zip(reference, descriptor):
363-
self.validate_descriptor(test, refvalue, value, context)
368+
reference.sort(key=sort_key)
369+
descriptor.sort(key=sort_key)
370+
for refvalue, value in zip(reference, descriptor):
371+
self.validate_descriptor(test, refvalue, value, context)
364372
# If the reference is an object then convert to a dict before comparison
365373
elif isinstance(reference, (NcDescriptor, NcElementId)):
366374
self.validate_descriptor(test, reference.__dict__, descriptor, context)
375+
# Compare primitives and primitive arrays directly
367376
elif reference != descriptor:
368-
raise NMOSTestException(test.FAIL(context + "Expected value: "
369-
+ str(reference) + ", actual value: " + str(descriptor)))
377+
raise NMOSTestException(test.FAIL(f"{context}Expected value: "
378+
f"{str(reference)}, actual value: {str(descriptor)}"))
370379
return
371380

372381
def _get_class_manager_datatype_descriptors(self, test, class_manager_oid, role_path):
@@ -376,9 +385,9 @@ def _get_class_manager_datatype_descriptors(self, test, class_manager_oid, role_
376385
if not response:
377386
return None
378387

379-
# Validate descriptors
388+
# Validate descriptors against schema
380389
for r in response:
381-
self.validate_reference_datatype_schema(test, r, NcDatatypeDescriptor.__name__,
390+
self.reference_datatype_schema_validate(test, r, NcDatatypeDescriptor.__name__,
382391
"/".join([str(r) for r in role_path]))
383392

384393
# Create NcDescriptor dictionary from response array
@@ -395,16 +404,16 @@ def _get_class_manager_class_descriptors(self, test, class_manager_oid, role_pat
395404

396405
# Validate descriptors
397406
for r in response:
398-
self.validate_reference_datatype_schema(test, r, NcClassDescriptor.__name__,
407+
self.reference_datatype_schema_validate(test, r, NcClassDescriptor.__name__,
399408
"/".join([str(r) for r in role_path]))
400409

401410
# Create NcClassDescriptor dictionary from response array
402411
def key_lambda(classId): return ".".join(map(str, classId))
403412
descriptors = {key_lambda(r.get("classId")): NcClassDescriptor(r) for r in response}
404413
return descriptors
405414

406-
def _nc_object_factory(self, test, class_id, oid, role, _role_path=None):
407-
"""Create NcObject or NcBlock based on class_id"""
415+
def create_device_model(self, test, class_id, oid, role, _role_path=None):
416+
"""Recursively create Device Model hierarchy"""
408417
# will set self.device_model_error to True if problems encountered
409418
if _role_path is None:
410419
role_path = []
@@ -423,26 +432,25 @@ def _nc_object_factory(self, test, class_id, oid, role, _role_path=None):
423432
oid=oid, role_path=role_path)
424433

425434
if member_descriptors is None:
426-
raise NMOSTestException(test.FAIL("Unable to get members for object: oid={}, role Path={}"
427-
.format(str(oid), str(role_path))))
435+
raise NMOSTestException(test.FAIL("Unable to get members for object: "
436+
f"oid={str(oid)}, role Path={str(role_path)}"))
428437

429438
block_member_descriptors = []
430439
for m in member_descriptors:
431-
self.validate_reference_datatype_schema(test, m, NcBlockMemberDescriptor.__name__,
440+
self.reference_datatype_schema_validate(test, m, NcBlockMemberDescriptor.__name__,
432441
"/".join([str(r) for r in role_path]))
433442
block_member_descriptors.append(NcBlockMemberDescriptor(m))
434443

435444
nc_block = NcBlock(class_id, oid, role, role_path, block_member_descriptors, runtime_constraints)
436445

437446
for m in member_descriptors:
438-
child_object = self._nc_object_factory(test, m["classId"], m["oid"], m["role"], role_path)
447+
child_object = self.create_device_model(test, m["classId"], m["oid"], m["role"], role_path)
439448
if child_object:
440449
nc_block.add_child_object(child_object)
441450

442451
return nc_block
443452
else:
444-
# Check to determine if this is a Class Manager
445-
if len(class_id) > 2 and class_id[0] == 1 and class_id[1] == 3 and class_id[2] == 2:
453+
if self.is_class_manager(class_id):
446454
class_descriptors = self._get_class_manager_class_descriptors(
447455
test, class_manager_oid=oid, role_path=role_path)
448456

@@ -460,7 +468,7 @@ def _nc_object_factory(self, test, class_id, oid, role, _role_path=None):
460468
return NcObject(class_id, oid, role, role_path, runtime_constraints)
461469

462470
except NMOSTestException as e:
463-
raise NMOSTestException(test.FAIL("Error in Device Model " + role + ": " + str(e.args[0].detail)))
471+
raise NMOSTestException(test.FAIL(f"Error in Device Model {role}: {str(e.args[0].detail)}"))
464472

465473
def _get_object_by_class_id(self, test, class_id):
466474
device_model = self.query_device_model(test)
@@ -516,11 +524,15 @@ def is_non_standard_class(self, class_id):
516524
return len([v for v in dropwhile(lambda x: x > 0, class_id)]) > 1
517525

518526
def is_manager(self, class_id):
519-
""" Check class id to determine if this is a manager """
527+
""" Check class id to determine if this is a manager class_id"""
520528
return len(class_id) > 1 and class_id[0] == 1 and class_id[1] == 3
521529

530+
def is_class_manager(self, class_id):
531+
""" Check class id to determine is this is a class manager class_id """
532+
return len(class_id) > 2 and class_id[0] == 1 and class_id[1] == 3 and class_id[2] == 2
533+
522534
def is_block(self, class_id):
523-
""" Check class id to determine if this is a block """
535+
""" Check class id to determine if this is a block class_id"""
524536
return len(class_id) > 1 and class_id[0] == 1 and class_id[1] == 1
525537

526538
def resolve_datatype(self, test, datatype):

0 commit comments

Comments
 (0)