From fd3f8b64eb67741040fe8e7881193b86f31b3092 Mon Sep 17 00:00:00 2001 From: Tomas <5571676+tomasg2012@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:12:27 -0600 Subject: [PATCH] Added new usecases, test profiles, double reporting, test fix Logic for usecases and test profiles provided for consistent testing. Removed line that doubled all counts at the end of run. Modify requirement unittest to pass. Signed-off-by: Tomas <5571676+tomasg2012@users.noreply.github.com> --- redfish_interop_validator/interop.py | 35 +++++++++++++++++-- redfish_interop_validator/validateResource.py | 5 ++- test-profiles/ChassisType_1.json | 20 +++++++++++ test-profiles/ChassisType_2.json | 18 ++++++++++ test-profiles/ChassisType_3.json | 19 ++++++++++ test-profiles/ChassisType_4.json | 19 ++++++++++ test-profiles/ChassisType_5.json | 19 ++++++++++ test-profiles/ChassisType_6.json | 18 ++++++++++ test-profiles/UseCaseType_ChassisType.json | 23 ++++++++++++ test-profiles/UseCaseType_PortProtocol.json | 23 ++++++++++++ test-profiles/UseCaseType_ProcessorType.json | 30 ++++++++++++++++ tests/interoptests.py | 7 ++-- 12 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 test-profiles/ChassisType_1.json create mode 100644 test-profiles/ChassisType_2.json create mode 100644 test-profiles/ChassisType_3.json create mode 100644 test-profiles/ChassisType_4.json create mode 100644 test-profiles/ChassisType_5.json create mode 100644 test-profiles/ChassisType_6.json create mode 100644 test-profiles/UseCaseType_ChassisType.json create mode 100644 test-profiles/UseCaseType_PortProtocol.json create mode 100644 test-profiles/UseCaseType_ProcessorType.json diff --git a/redfish_interop_validator/interop.py b/redfish_interop_validator/interop.py index 158ff59..cb465ad 100644 --- a/redfish_interop_validator/interop.py +++ b/redfish_interop_validator/interop.py @@ -767,6 +767,15 @@ def checkInteropURI(r_obj, profile_entry): my_id, my_uri = r_obj.jsondata.get('Id'), r_obj.uri return compareRedfishURI(profile_entry, my_uri) +# Expected Type, Key +entry_type_table = { + 'ChassisType': ("Chassis", "ChassisType"), + 'DriveProtocol': ("Drive", "Protocol"), + 'MemoryType': ("Memory", "MemoryType"), + 'PortProtocol': ("Port", "PortProtocol"), + 'ProcessorType': ("Processor", "ProcessorType"), +} + def validateInteropResource(propResourceObj, interop_profile, rf_payload): """ @@ -783,11 +792,12 @@ def validateInteropResource(propResourceObj, interop_profile, rf_payload): for use_case in interop_profile['UseCases']: entry_title = use_case.get("UseCaseTitle", "NoName").replace(' ', '_') entry_type = use_case.get("UseCaseType", "Normal") + my_parent = propResourceObj.parent my_logger.debug('UseCase {} {}'.format(entry_title, entry_type)) # Check if we have a valid UseCase - if 'URIs' not in use_case and 'UseCaseKeyProperty' not in use_case and entry_type != 'AbsentResource': - my_logger.error('UseCase does not have URIs or UseCaseKeyProperty...') + if ('URIs' not in use_case) and ('UseCaseKeyProperty' not in use_case) and (entry_type not in ['AbsentResource'] + list(entry_type_table.keys())): + my_logger.error('UseCase does not have URIs or valid UseCase...') if entry_type == 'AbsentResource': my_status = rf_payload.get('Status') @@ -797,6 +807,27 @@ def validateInteropResource(propResourceObj, interop_profile, rf_payload): use_case_applies = False if 'URIs' in use_case: use_case_applies = use_case_applies and checkInteropURI(propResourceObj, use_case['URIs']) + + elif entry_type in entry_type_table: + target_type_found = False + target_type, entry_key = entry_type_table[entry_type] + entry_comparison, entry_values = use_case['UseCaseComparison'], use_case['UseCaseKeyValues'] + + # Iterate until we find our target type, if not found then use case cannot apply + while my_parent is not None and not target_type_found: + parent_type = getType(my_parent.jsondata.get('@odata.type', 'NoType')) + target_type_found = parent_type == target_type + if not target_type_found: + my_parent = my_parent.parent + + if target_type_found: + target_payload = my_parent.jsondata + target_value = target_payload.get(entry_key) + + _, use_case_applies = checkComparison(target_payload.get(entry_key, REDFISH_ABSENT), entry_comparison, entry_values) + else: + use_case_applies = False + elif 'UseCaseKeyProperty' in use_case: entry_key, entry_comparison, entry_values = use_case['UseCaseKeyProperty'], use_case['UseCaseComparison'], use_case['UseCaseKeyValues'] diff --git a/redfish_interop_validator/validateResource.py b/redfish_interop_validator/validateResource.py index 832f903..95c5bcc 100644 --- a/redfish_interop_validator/validateResource.py +++ b/redfish_interop_validator/validateResource.py @@ -168,7 +168,7 @@ def validateSingleURI(URI, profile, uriName='', expectedType=None, expectedSchem profile_resources = profile_resources.get(SchemaType) try: propMessages, propCounts = interop.validateInteropResource(resource_obj, profile_resources, jsondata) - messages = messages.extend(propMessages) + messages.extend(propMessages) counts.update(propCounts) my_logger.info('{} of {} tests passed.'.format(counts['pass'] + counts['warn'], counts['totaltests'])) except Exception: @@ -312,8 +312,7 @@ def validateURITree(URI, profile, uriName, expectedType=None, expectedSchema=Non allLinks.add(link.rstrip('/')) results.update(linkResults) - counts.update(linkCounts) - + if not linkSuccess: continue diff --git a/test-profiles/ChassisType_1.json b/test-profiles/ChassisType_1.json new file mode 100644 index 0000000..3d50c95 --- /dev/null +++ b/test-profiles/ChassisType_1.json @@ -0,0 +1,20 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType5", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure'. This test should pass.", + "Resources": { + "Thermal": { + "PropertyRequirements": { + "Temperatures": { + "PropertyRequirements": { + "PhysicalContext": { + "Comparison": "AllOf", + "Values": [ "Intake", "CPU" ] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test-profiles/ChassisType_2.json b/test-profiles/ChassisType_2.json new file mode 100644 index 0000000..f4e2ca4 --- /dev/null +++ b/test-profiles/ChassisType_2.json @@ -0,0 +1,18 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType1", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure'. This test should pass (MultiBladeEncl is an Enclosure).", + "Resources": { + "Chassis": { + "PropertyRequirements": { + "ChassisType": { + "Comparison": "AnyOf", + "Values": [ + "Enclosure" + ] + } + } + } + } +} diff --git a/test-profiles/ChassisType_3.json b/test-profiles/ChassisType_3.json new file mode 100644 index 0000000..a5f345d --- /dev/null +++ b/test-profiles/ChassisType_3.json @@ -0,0 +1,19 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType2", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure' or a 'Rack'. This test should pass (MultiBladeEncl is an Enclosure).", + "Resources": { + "Chassis": { + "PropertyRequirements": { + "ChassisType": { + "Comparison": "AnyOf", + "Values": [ + "Enclosure", + "Rack" + ] + } + } + } + } +} diff --git a/test-profiles/ChassisType_4.json b/test-profiles/ChassisType_4.json new file mode 100644 index 0000000..0b1cad5 --- /dev/null +++ b/test-profiles/ChassisType_4.json @@ -0,0 +1,19 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType3", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure' and a 'Rack'. This test should fail (there are no 'Rack' chassis).", + "Resources": { + "Chassis": { + "PropertyRequirements": { + "ChassisType": { + "Comparison": "AllOf", + "Values": [ + "Enclosure", + "Rack" + ] + } + } + } + } +} diff --git a/test-profiles/ChassisType_5.json b/test-profiles/ChassisType_5.json new file mode 100644 index 0000000..ab5bec2 --- /dev/null +++ b/test-profiles/ChassisType_5.json @@ -0,0 +1,19 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType4", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure' and a 'Blade'. This test should pass.", + "Resources": { + "Chassis": { + "PropertyRequirements": { + "ChassisType": { + "Comparison": "AllOf", + "Values": [ + "Enclosure", + "Blade" + ] + } + } + } + } +} diff --git a/test-profiles/ChassisType_6.json b/test-profiles/ChassisType_6.json new file mode 100644 index 0000000..d3f3977 --- /dev/null +++ b/test-profiles/ChassisType_6.json @@ -0,0 +1,18 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "ChassisType5", + "ProfileVersion": "1.0.0", + "Purpose": "Ensures at least one chassis is an 'Enclosure'. This test should pass.", + "Resources": { + "Chassis": { + "PropertyRequirements": { + "ChassisType": { + "Comparison": "AllOf", + "Values": [ + "Enclosure" + ] + } + } + } + } +} diff --git a/test-profiles/UseCaseType_ChassisType.json b/test-profiles/UseCaseType_ChassisType.json new file mode 100644 index 0000000..c1bda91 --- /dev/null +++ b/test-profiles/UseCaseType_ChassisType.json @@ -0,0 +1,23 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "UseCaseType_ChassisType", + "ProfileVersion": "1.0.0", + "Purpose": "Test for UseCaseType 'ChassisType'. Should pass one test for every Sensor in public-rackmount1.", + "Resources": { + "Sensor": { + "UseCases": [ + { + "UseCaseTitle": "Chassis Sensor", + "UseCaseType": "ChassisType", + "UseCaseComparison": "Equal", + "UseCaseKeyValues": [ + "RackMount" + ], + "PropertyRequirements": { + "PhysicalContext": {} + } + } + ] + } + } +} diff --git a/test-profiles/UseCaseType_PortProtocol.json b/test-profiles/UseCaseType_PortProtocol.json new file mode 100644 index 0000000..9b0cc12 --- /dev/null +++ b/test-profiles/UseCaseType_PortProtocol.json @@ -0,0 +1,23 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "UseCaseType_PortProtocol", + "ProfileVersion": "1.0.0", + "Purpose": "Test for UseCaseType 'PortProtocol'. Should pass one test for each PortMetrics in public-acd.", + "Resources": { + "Sensor": { + "UseCases": [ + { + "UseCaseTitle": "Port Metrics", + "UseCaseType": "PortProtocol", + "UseCaseComparison": "Equal", + "UseCaseKeyValues": [ + "RackMount" + ], + "PropertyRequirements": { + "PhysicalContext": {} + } + } + ] + } + } +} diff --git a/test-profiles/UseCaseType_ProcessorType.json b/test-profiles/UseCaseType_ProcessorType.json new file mode 100644 index 0000000..be8d980 --- /dev/null +++ b/test-profiles/UseCaseType_ProcessorType.json @@ -0,0 +1,30 @@ +{ + "SchemaDefinition": "RedfishInteroperabilityProfile.v1_5_0", + "ProfileName": "UseCaseType_PortProtocol", + "ProfileVersion": "1.0.0", + "Purpose": "Test for UseCaseType 'ProcessorType'. Should pass one test for each SubProcessor in public-tower.", + "Resources": { + "Processor": { + "UseCases": [ + { + "UseCaseTitle": "Sub Processor", + "UseCaseType": "ProcessorType", + "UseCaseComparison": "Equal", + "UseCaseKeyValues": [ + "CPU" + ], + "PropertyRequirements": { + "ProcessorType": { + "ReadRequirement": "Mandatory", + "Comparison": "AnyOf", + "Values": [ + "Thread", + "Core" + ] + } + } + } + ] + } + } +} diff --git a/tests/interoptests.py b/tests/interoptests.py index 6e5d471..cd4dc60 100644 --- a/tests/interoptests.py +++ b/tests/interoptests.py @@ -26,10 +26,11 @@ def test_no_test(self): def test_requirement(self): entries = ['Mandatory', 'Recommended', 'Mandatory', 'Recommended'] - vals = ['Ok', riv.REDFISH_ABSENT, riv.REDFISH_ABSENT, 'Ok'] - boolist = [True, True, False, True] + vals = [{}, riv.REDFISH_ABSENT, riv.REDFISH_ABSENT, {}] + boolist = [True, riv.testResultEnum.NA, False, True] for e, v, b in zip(entries, vals, boolist): - self.assertTrue(riv.validateRequirement(e, v)[1] == b, str(e + ' ' + v)) + _msg, result_value = riv.validateRequirement(e, v) + self.assertTrue(result_value == b, str(e + ' ' + str(v))) def test_mincount(self): x = 'x'