def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", AdditionalPropertiesPatchTest.METADATA) self.discovery_container = DiscoveryContainer()
def setUp(self): metadata_manager = MetadataManager(["qualifier"], ) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", 'netloc', RESOURCE, "#Manager.1.0.0.Manager"))
def test_visited_endpoint(self): discovery_container = DiscoveryContainer() discovery_container.add_resource(ApiResource("http://ip:123/something", None, {}, None)) discovery_container.add_resource = MagicMock() returned_discovery_container, _ = self.api_explorer.discover("http://ip:123/something", None, discovery_container) discovery_container.add_resource.assert_not_called()
class PatchRmmManagerTest(unittest.TestCase): def setUp(self): metadata_manager = MetadataManager(["qualifier"], ) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/v1/Managers/RMC", 'netloc', RESOURCE, "#Manager.1.0.0.Manager")) def test_patch(self): with mock.patch('cts_core.commons.api_caller.ApiCaller.__init__' ) as api_caller_init_mock: api_caller_init_mock.return_value = None with mock.patch( 'cts_core.validation.patch.metadata_patch_validator.MetadataPatchValidator._validate_patchable_property' ) as validate_property: validate_property.return_value = ValidationStatus.PASSED validator = MetadataPatchValidator(self.metadata_container, None, PatchingStrategy2_1()) with StdoutCapture() as output: self.assertEqual( ValidationStatus.PASSED, validator.validate(self.discovery_container))
def setUp(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/v1/Fabrics/1/Endpoints/8", 'netloc', RESOURCE, "#Endpoint.v1_0_0.Endpoint"))
def test_visited_endpoint(self): discovery_container = DiscoveryContainer() discovery_container.add_resource(ApiResource("http://ip:123/something", None, {}, None)) discovery_container.add_resource = MagicMock() returned_discovery_container, _ = self.api_explorer.discover("http://ip:123/something", None, discovery_container) discovery_container.add_resource.assert_not_called()
def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings(METADATA) HardwareCheckList.MetadataConstants = MetadataConstants2_2 self.checklist = HardwareCheckList(dict()) #monkey patch self.checklist._load_metadata = lambda : self.metadata_container
def test_not_found_in_non_empty_discovery_container(self): discovery_container = DiscoveryContainer(metadata_container=self.metadata_container) discovery_container.add_resource(ApiResource("id_1", 'netloc', {'@odata.id': '123', 'Oem': {'Intel_RackScale': {'Location': {'Id': 1, 'ParentId': None} } } }, None)) requirements = [ Requirement("Chassis.Chassis", min=1, max=1) ] preconditions = Preconditions(self.metadata_container, requirements) self.assertEqual(ValidationStatus.FAILED, preconditions.validate(discovery_container))
def test_should_pass_if_entity_type_declared_on_ignore_list(self): metadata_manager = MetadataManager(["qualifier"], ignore_types=["N.R"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_resource_in_discovery_container_after_get_patch_delete(self): with mock.patch('requests.get') as requests_get_mock: resource = {"@odata.id": "odata.id", "something": "irrelevant"} get_response = Mock() get_response.status_code = ReturnCodes.OK get_response.headers = {} get_response.text = json.dumps(resource) requests_get_mock.return_value = get_response discovery_container = DiscoveryContainer() self.api_caller.get_resource("/resource", discovery_container) self.assertEqual(discovery_container["http://{API_ENDPOINT}/resource".format( API_ENDPOINT=API_ENDPOINT)].body, resource) patched_resource = {"@odata.id": "odata.id", "something": "relevant"} get_response.text = json.dumps(patched_resource) with mock.patch('requests.patch') as requests_patch_mock: patch_response = Mock() patch_response.status_code = ReturnCodes.OK patch_response.headers = {} patch_response.text = "{}" requests_patch_mock.return_value = patch_response _, _, _, _ = self.api_caller.patch_resource("/resource", discovery_container) self.assertEqual(discovery_container["http://{API_ENDPOINT}/resource".format( API_ENDPOINT=API_ENDPOINT)].body, patched_resource) with mock.patch('requests.delete') as requests_delete_mock: delete_response = Mock() delete_response.status_code = ReturnCodes.NO_CONTENT delete_response.headers = {} delete_response.text = "" requests_delete_mock.return_value = delete_response _, _, _, _ = self.api_caller.delete_resource("/resource", discovery_container) self.assertNotIn("/resource", discovery_container)
def discover(self, url, expected_odata_type, discovery_container=None, api_endpoint_override=None): """ :type discovery_container: cts_core.discovery.discovery_container.DiscoveryContainer :rtype: (cts_core.discovery.discovery_container.DiscoveryContainer, cts_core.validation.validation_status.ValidationStatus) """ self._status = ValidationStatus.PASSED if getenv('CTS_UNPICKLE', None): self._discovery_container = pickle.load( open(environ['CTS_UNPICKLE'], 'rb')) self._discovery_container.metadata_container = self._metadata_container return self._discovery_container, self._status self._discovery_container = discovery_container if discovery_container is not None \ else DiscoveryContainer(metadata_container=self._metadata_container) self._enqueue_resource(url, expected_odata_type, api_endpoint_override) while self._bfs_queue: self._explore_next_resource() if getenv('CTS_PICKLE', None): # workaroud for 'TypeError: can't pickle instancemethod objects' metadata_container_backup = self._discovery_container.metadata_container self._discovery_container.metadata_container = None # do not pickle metadata container pickle.dump(self._discovery_container, open(environ['CTS_PICKLE'], 'wb')) self._discovery_container.metadata_container = metadata_container_backup return self._discovery_container, self._status
def test_not_found_in_empty_discovery_container(self): discovery_container = DiscoveryContainer(metadata_container=self.metadata_container) requirements = [ Requirement("Chassis.Chassis", min=1, max=1) ] preconditions = Preconditions(self.metadata_container, requirements) self.assertEqual(ValidationStatus.FAILED, preconditions.validate(discovery_container))
def test_fail_when_more_than_max(self): discovery_container = DiscoveryContainer(metadata_container=self.metadata_container) discovery_container.add_resource(ApiResource("id_1", 'netloc', {'@odata.id': '123', '@odata.type' : '#Chassis.v1_0_0.Chassis', 'Oem': {'Intel_RackScale': {'Location': {'Id': 1, 'ParentId': None} } } }, None)) requirements = [ Requirement("Chassis.Chassis", min=0, max=0) ] preconditions = Preconditions(self.metadata_container, requirements) self.assertEqual(ValidationStatus.FAILED, preconditions.validate(discovery_container))
def test_should_pass_with_correct_resource(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def setUp(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/v1/Fabrics/1/Endpoints/8", 'netloc', RESOURCE, "#Endpoint.v1_0_0.Endpoint"))
def test_discovery_from_nested_additional_properties(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> <Property Name="Oem" Type="N.Oem"> </Property> </EntityType> <ComplexType Name="Oem" Abstract="false"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> </ComplexType> <ComplexType Name="Inner" Abstract="false"> <NavigationProperty Name="Link" Type="N.Referenced" ContainsTarget="true"> </NavigationProperty> </ComplexType> <EntityType Name="Referenced" Abstract="false"> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "#N.Outer", "Oem": { "additional_property": { "@odata.type": "#N.Inner", "Link": { "@odata.id": "/this/is/the/link/to/be/discovered" }, } } } referenced = \ { "@odata.id": "referenced.id", "@odata.type": "#N.Referenced", } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings("Unknown", metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch( 'cts_core.discovery.api_explorer.ApiExplorer._get_resource') as get_resource: get_resource.side_effect = [(Link('link', 'netloc'), RequestStatus.SUCCESS, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, referenced, None)] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(2, get_resource.call_count) self.assertNotIn("ERROR::", '\n'.join(output))
def test_to_many_redirects_exception(self): with mock.patch('requests.get') as requests_get_mock: requests_get_mock.side_effect = requests.TooManyRedirects() with StdoutCapture() as output: self.api_caller.get_resource("/resource", DiscoveryContainer()) self.assertIn( "ERROR::Get url=http://1.2.3.4:567/resource Error <class 'requests.exceptions.TooManyRedirects'>:;", output.raw)
def test_url_required_exception(self): with mock.patch('requests.get') as requests_get_mock: requests_get_mock.side_effect = requests.URLRequired() with StdoutCapture() as output: self.api_caller.get_resource("/resource", DiscoveryContainer()) self.assertIn("ERROR::Get url=http://1.2.3.4:567/resource Error <class " "'requests.exceptions.URLRequired'>:", output.raw)
def test_handle_collection_with_typeless_elements_referenced_by_json_pointer( self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <NavigationProperty Name="MyCollection" Type="Collection(ReferencedEntity)" ContainsTarget="true"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </NavigationProperty> </EntityType> <EntityType Name="ReferencedEntity" Abstract="false"> <Property Name="name" Type="Edm.String"/> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "N.Outer", "MyCollection": [ { # implicit odata.type = ReferencedEntity "@odata.id": "/outer#MyCollection/0", "name": "MyName 0" }, { # implicit odata_type = ReferencedEntity "@odata.id": "/outer#MyCollection/1", "name": "MyName 1" } ] } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch('cts_core.commons.api_caller.ApiCaller.get_resource' ) as get_resource: get_resource.side_effect = [(Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None)] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(3, get_resource.call_count) self.assertEqual(0, len(re.findall('ERROR::', ';'.join(output))))
def test_empty_root_resources_when_none_location_has_empty_parentid(self): container = DiscoveryContainer() container.add_resource( ApiResource("id_1", 'netloc', { 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 1, 'ParentId': 2 } } } }, None)) container.add_resource( ApiResource("id_2", 'netloc', { 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 3, 'ParentId': 4 } } } }, None)) self.assertFalse(container.root_resources())
def test_more_than_one_root_resource(self): container = DiscoveryContainer() container.add_resource( ApiResource( "id_1", 'netloc', { '@odata.id': '123', 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 1, 'ParentId': None } } } }, None)) container.add_resource( ApiResource( "id_2", 'netloc', { '@odata.id': '456', 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 3, 'ParentId': None } } } }, None)) root_ids = [r.odata_id for r in container.root_resources()] self.assertEqual(2, len(root_ids)) self.assertIn('123', root_ids) self.assertIn('456', root_ids)
def test_non_empty_root_resources(self): container = DiscoveryContainer() container.add_resource( ApiResource( "id_1", 'netloc', { '@odata.id': '123', 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 1, 'ParentId': None } } } }, None)) container.add_resource( ApiResource("id_2", 'netloc', { 'Oem': { 'Intel_RackScale': { 'Location': { 'Id': 3, 'ParentId': 4 } } } }, None)) root = container.root_resources() self.assertEqual(1, len(root)) self.assertEqual('123', root[0].odata_id)
def test_reference_is_recreated(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {'@odata.id': 'id1', 'Oem': {'Intel_RackScale': {'Location': {'Id': 1, 'ParentId': 2} } } }, None)) container.add_resource(ApiResource("id_2", 'netloc', {'@odata.id': 'id2', 'Oem': {'Intel_RackScale': {'Location': {'Id': 3, 'ParentId': 4} } } }, None)) res = container["id_2"] self.assertTrue(isinstance(res, ApiResourceProxy)) self.assertEquals(res.odata_id, "id2") container.delete_resource("id_2") with StdoutCapture() as output: with self.assertRaises(AttributeError): res.odata_id self.assertIn('ERROR::ApiResources id_2 is no longer valid', output.raw)
def test_empty_service_root(self): with mock.patch('requests.get') as requests_get_mock: requests_get_mock.side_effect = requests.ConnectionError() with StdoutCapture() as output: self.api_caller.get_resource("/redfish/v1", DiscoveryContainer()) self.assertIn( "ERROR::Get url=http://1.2.3.4:567/redfish/v1 Error <class 'requests.exceptions.ConnectionError'>:;", output.raw)
def test_empty_root_resources_when_location_not_specified(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {}, None)) container.add_resource( ApiResource("id_1", 'netloc', {'some_property': 'some_value'}, None)) self.assertFalse(container.root_resources())
def run(self): metadata_manager = MetadataManager(self.configuration) metadata_manager.load_files() metadata_container = metadata_manager.load_metadata_properties() api_explorer = ApiExplorer("/redfish/v1/", "ServiceRoot.ServiceRoot", metadata_container, self.configuration) discovery_container = api_explorer.process_with_resource(DiscoveryContainer()) discovery_container.keys() status = MetadataPatchValidator(metadata_container, self.configuration).validate(discovery_container) self.set_status(status)
def setUp(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer( metadata_container=self.metadata_container) self.validator = HierarchyValidator(self.discovery_container, self.metadata_container, MetadataConstants2_1) self.builder = ResourceBuilder(self.discovery_container)
def test_unexpected_async_post_response(self): with mock.patch('requests.post') as requests_get_mock: response = Mock() response.status_code = ReturnCodes.ACCEPTED response.headers = {} response.text = "{}" requests_get_mock.return_value = response with self.assertRaises(AsyncOperation): self.api_caller.post_resource('odata_id', DiscoveryContainer(), payload={}, wait_if_async=False)
def test_should_fail_bacause_of_unknown_complex_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Reference to unknown type unknown.complex.type', '\n'.join(output))
def test_should_fail_bacause_of_unknown_entity_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn("ERROR::Unknown entity type 'unknown.entity.type'", output.raw)
def test_incorrect_status_code(self): with mock.patch('requests.get') as requests_get_mock: response = Mock() response.status_code = 500 response.headers = {} response.text = "{}" requests_get_mock.return_value = response link, status, status_code, response_body, headers = \ self.api_caller.get_resource("/resource", DiscoveryContainer()) self.assertFalse(status)
def test_should_pass_when_unknown_entity_type_mapped_to_known_one(self): metadata_manager = MetadataManager(["qualifier"], map_types={ "A": "B", "unknown.entity.type": "N.R" }) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_validate_dynamic_properties_at_entity_level(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INCOMPLETE_DYNAMIC_PROPERTY, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn( 'ERROR::Required property resource.id->aaaaaaaa->Obligatory not present in the resource', '\n'.join(output))
class PatchRmmManagerTest(unittest.TestCase): def setUp(self): metadata_manager = MetadataManager(["qualifier"], ) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", 'netloc', RESOURCE, "#Manager.1.0.0.Manager")) def test_patch(self): with mock.patch('cts_core.commons.api_caller.ApiCaller.__init__') as api_caller_init_mock: api_caller_init_mock.return_value = None with mock.patch('cts_core.validation.patch.metadata_patch_validator.MetadataPatchValidator._validate_patchable_property') as validate_property: validate_property.return_value = ValidationStatus.PASSED validator = MetadataPatchValidator(self.metadata_container, None, PatchingStrategy2_1()) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_pass_when_unknown_complex_type_mapped_on_known_type(self): metadata_manager = MetadataManager(["qualifier"], map_types={"A" : "B", "unknown.complex.type" : "N.ObjectWithNumericProperty"}) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_pass_if_entity_type_declared_on_ignore_list_with_asterix(self): metadata_manager = MetadataManager(['qualifier'], ignore_types=["N.*"]) self.metadata_container = metadata_manager.read_metadata_from_strings('Unknown', METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource('/redfish/resource1', 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, '#N.R')) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_pass_if_property_of_incorrect_type_declared_on_ignore_list(self): metadata_manager = MetadataManager(["qualifier"], ignore_types=["N.ObjectWithNumericProperty"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_pass_with_correct_resource(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_fail_if_property_of_incorrect_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Property resource.id->ObjectWithNumber is expected to be json object', '\n'.join(output))
def test_should_fail_bacause_of_unknown_complex_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Reference to unknown type unknown.complex.type', '\n'.join(output))
def test_should_fail_bacause_of_unknown_entity_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn("ERROR::Unknown entity type 'unknown.entity.type'", output.raw)
def test_should_fail_if_non_nullable_property_is_null(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_NULL_ON_NON_NULLABLE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('ERROR::Property resource.id->CapacityGiB cannot be null', '\n'.join(output)) self.assertIn('ERROR::Property resource.id->ObjectWithNumber->Number cannot be null', '\n'.join(output))
def test_should_validate_dynamic_properties_at_entity_level(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INCOMPLETE_DYNAMIC_PROPERTY, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('ERROR::Required property resource.id->aaaaaaaa->Obligatory not present in the resource', '\n'.join(output))
def test_should_suggest_other_names_for_additionals(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) self.assertIn('Schema defines other, not used, but similar properties: [OptionalProperty1, OptionalProperty3]', '\n'.join(output)) self.assertIn( 'Schema defines other, not used, but similar properties: [OptionalPropertyInComplex1, OptionalPropertyInComplex3]', '\n'.join(output))
def test_empty_root_resources_when_none_location_has_empty_parentid(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {'Oem' : {'Intel_RackScale' : {'Location' : {'Id' : 1, 'ParentId' : 2} } } }, None)) container.add_resource(ApiResource("id_2", 'netloc', {'Oem': {'Intel_RackScale': {'Location': {'Id': 3, 'ParentId': 4} } } }, None)) self.assertFalse(container.root_resources())
def test_non_empty_root_resources(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {'@odata.id' : '123', 'Oem': {'Intel_RackScale': {'Location': {'Id': 1, 'ParentId': None} } } }, None)) container.add_resource(ApiResource("id_2", 'netloc', {'Oem': {'Intel_RackScale': {'Location': {'Id': 3, 'ParentId': 4} } } }, None)) root = container.root_resources() self.assertEqual(1, len(root)) self.assertEqual('123', root[0].odata_id)
def test_more_than_one_root_resource(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {'@odata.id': '123', 'Oem': {'Intel_RackScale': {'Location': {'Id': 1, 'ParentId': None} } } }, None)) container.add_resource(ApiResource("id_2", 'netloc', {'@odata.id': '456', 'Oem': {'Intel_RackScale': {'Location': {'Id': 3, 'ParentId': None} } } }, None)) root_ids = [r.odata_id for r in container.root_resources()] self.assertEqual(2, len(root_ids)) self.assertIn('123', root_ids) self.assertIn('456', root_ids)
def test_empty_root_resources_when_location_not_specified(self): container = DiscoveryContainer() container.add_resource(ApiResource("id_1", 'netloc', {}, None)) container.add_resource(ApiResource("id_1", 'netloc', {'some_property' : 'some_value'}, None)) self.assertFalse(container.root_resources())
class AtLeastOneComputeModuleInPodUnitTest(unittest.TestCase): def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) HardwareCheckList.MetadataConstants = MetadataConstants2_1 self.checklist = HardwareCheckList(dict()) #monkey patch self.checklist._load_metadata = lambda : self.metadata_container def test_should_fail_on_empty_pod(self): with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertIn('STATUS::Failed', output) def test_should_fail_when_no_compute_module(self): chassisRack = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Rack1", "@odata.type": "#Chassis.v1_2_0.Chassis", "ChassisType": "Rack", } self.discovery_container.add_resource( ApiResource("/redfish/v1/Chassis/Rack1", 'netloc', chassisRack, "Chassis.v1_2_0.Chassis")) with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertIn('ERROR::Computer System with memory and processors not found', output.raw) self.assertIn('STATUS::Failed', output) def test_should_fail_when_memory_invalid_on_computer_system(self): system = { "@odata.context": "/redfish/v1/$metadata#Systems/Members/$entity", "@odata.id": "/redfish/v1/Systems/s1-2", "@odata.type": "#ComputerSystem.v1_0_0.ComputerSystem", "ProcessorSummary" : { "Count" : 1 }, "MemorySummary": { "TotalSystemMemoryGiB": 0 } } self.discovery_container.add_resource(ApiResource("/redfish/v1/ComputerSystem/1", 'netloc', system, "ComputerSystem.v1_1_0.ComputerSystem")) with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertIn('ERROR::Computer System with memory and processors not found', output.raw) self.assertIn('STATUS::Failed', output) def test_should_fail_when_processors_invalid_on_computer_system(self): system = { "@odata.context": "/redfish/v1/$metadata#Systems/Members/$entity", "@odata.id": "/redfish/v1/Systems/s1-2", "@odata.type": "#ComputerSystem.v1_0_0.ComputerSystem", "ProcessorSummary" : { "Count" : 0 }, "MemorySummary": { "TotalSystemMemoryGiB": 8 } } self.discovery_container.add_resource(ApiResource("/redfish/v1/ComputerSystem/1", 'netloc', system, "ComputerSystem.v1_1_0.ComputerSystem")) with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertIn('ERROR::Computer System with memory and processors not found', output.raw) self.assertIn('STATUS::Failed', output) def test_should_pass_when_compute_module_is_present(self): system = { "@odata.context": "/redfish/v1/$metadata#Systems/Members/$entity", "@odata.id": "/redfish/v1/Systems/s1-2", "@odata.type": "#ComputerSystem.v1_0_0.ComputerSystem", "ProcessorSummary" : { "Count" : 1 }, "MemorySummary": { "TotalSystemMemoryGiB": 8 } } self.discovery_container.add_resource(ApiResource("/redfish/v1/ComputerSystem/1", 'netloc', system, "ComputerSystem.v1_1_0.ComputerSystem")) with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertIn('Found compute module with processors and memory', "".join(output)) self.assertIn('STATUS::Passed', output)
class GetValidateTest(unittest.TestCase): def test_should_pass_with_correct_resource(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_fail_bacause_of_unknown_entity_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn("ERROR::Unknown entity type 'unknown.entity.type'", output.raw) def test_should_pass_when_unknown_entity_type_mapped_to_known_one(self): metadata_manager = MetadataManager(["qualifier"], map_types={"A" : "B", "unknown.entity.type" : "N.R"}) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_fail_bacause_of_unknown_complex_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Reference to unknown type unknown.complex.type', '\n'.join(output)) def test_should_pass_when_unknown_complex_type_mapped_on_known_type(self): metadata_manager = MetadataManager(["qualifier"], map_types={"A" : "B", "unknown.complex.type" : "N.ObjectWithNumericProperty"}) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_fail_if_property_of_incorrect_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Property resource.id->ObjectWithNumber is expected to be json object', '\n'.join(output)) def test_should_pass_if_property_of_incorrect_type_declared_on_ignore_list(self): metadata_manager = MetadataManager(["qualifier"], ignore_types=["N.ObjectWithNumericProperty"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_pass_if_entity_type_declared_on_ignore_list(self): metadata_manager = MetadataManager(["qualifier"], ignore_types=["N.R"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_pass_if_entity_type_declared_on_ignore_list_with_asterix(self): metadata_manager = MetadataManager(['qualifier'], ignore_types=["N.*"]) self.metadata_container = metadata_manager.read_metadata_from_strings('Unknown', METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource('/redfish/resource1', 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, '#N.R')) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) def test_should_fail_if_non_nullable_property_is_null(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_NULL_ON_NON_NULLABLE, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('ERROR::Property resource.id->CapacityGiB cannot be null', '\n'.join(output)) self.assertIn('ERROR::Property resource.id->ObjectWithNumber->Number cannot be null', '\n'.join(output)) def test_should_suggest_other_names_for_additionals(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) self.assertIn('Schema defines other, not used, but similar properties: [OptionalProperty1, OptionalProperty3]', '\n'.join(output)) self.assertIn( 'Schema defines other, not used, but similar properties: [OptionalPropertyInComplex1, OptionalPropertyInComplex3]', '\n'.join(output)) def test_should_validate_dynamic_properties_at_entity_level(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INCOMPLETE_DYNAMIC_PROPERTY, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('ERROR::Required property resource.id->aaaaaaaa->Obligatory not present in the resource', '\n'.join(output)) def test_should_validate_dynamic_properties_at_complex_type_level(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INCOMPLETE_DYNAMIC_PROPERTY_AT_COMPLEX_TYPE_LEVEL, "#N.R")) requirements = [ ] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn( 'ERROR::Required property resource.id->ObjectWithNumber->aaaaaaaa->Obligatory not present in the resource', ';'.join(output)) def test_validate_elements_of_collection_with_elements_referenced_by_out_of_range_json_pointer(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <NavigationProperty Name="MyCollection" Type="Collection(ReferencedEntity)" ContainsTarget="true"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </NavigationProperty> </EntityType> <EntityType Name="ReferencedEntity" Abstract="false"> <Property Name="name" Type="Edm.String"/> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "N.Outer", "MyCollection": [ { "@odata.id": "/outer#MyCollection/0" }, { "@odata.id": "/outer#MyCollection/2" # pointer out of range } ] } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings("Unknown", metadata) discovery_container = DiscoveryContainer() configuration = Configuration(**dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch('cts_core.commons.api_caller.ApiCaller.get_resource') as get_resource: get_resource.side_effect = [(Link('url1', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, Link('url1', 'netloc')), (Link('url2', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, Link('url2', 'netloc')), (Link('url3', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, Link('url3', 'netloc'))] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(3, get_resource.call_count) self.assertIn( 'ERROR::JSON pointer exception while dereferencing /MyCollection/2', ';'.join(output)) requirements = [ ] validator = MetadataGetValidator(metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(discovery_container)) self.assertEqual(0, len(re.findall('ERROR::', ';'.join(output))))
def test_iter_all(self): metadata_manager = MetadataManager(["qualifier"]) discovery_container = DiscoveryContainer( metadata_container=metadata_manager.read_metadata_from_strings("Unknown", self.TEST_METADATA)) chassis1_2 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Rack1", "@odata.type": "#Chassis.v1_2_0.Chassis", "ChassisType": "Rack", } discovery_container.add_resource(ApiResource("/redfish/v1/Chassis/Rack1", 'netloc',chassis1_2, "Chassis.v1_2_0.Chassis")) self.assertEqual(1, len(list(discovery_container.iter_all("Chassis.v1_2_0.Chassis")))) self.assertEqual(1, len(list(discovery_container.iter_all("Chassis.v1_0_0.Chassis")))) self.assertEqual(1, len(list(discovery_container.iter_all("Chassis.Chassis")))) self.assertEqual(1, len(list(discovery_container.iter_all("Resource.v1_0_0.Resource")))) self.assertEqual(1, len(list(discovery_container.iter_all("Resource.Resource")))) chassis1_0 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Module1", "@odata.type": "#Chassis.v1_0_0.Chassis", "ChassisType": "Module", } discovery_container.add_resource(ApiResource("/redfish/v1/Chassis/Module1", 'netloc', chassis1_0, "Chassis.v1_0_0.Chassis")) self.assertEqual(1, len(list(discovery_container.iter_all("Chassis.v1_2_0.Chassis")))) self.assertEqual(2, len(list(discovery_container.iter_all("Chassis.v1_0_0.Chassis")))) self.assertEqual(2, len(list(discovery_container.iter_all("Chassis.Chassis")))) self.assertEqual(2, len(list(discovery_container.iter_all("Resource.v1_0_0.Resource")))) self.assertEqual(2, len(list(discovery_container.iter_all("Resource.Resource"))))
def test_generalized_odata_type(self): discovery_container = DiscoveryContainer(service_root="/redfish/v1") switch_collection = { "@odata.context": "/redfish/v1/$metadata#EthernetSwitchCollection.EthernetSwitchCollection", "@odata.id": "/redfish/v1/EthernetSwitches", "@odata.type": "#EthernetSwitchCollection.EthernetSwitchCollection", "Members": [ { "@odata.id": "/redfish/v1/EthernetSwitches/1" } ], "*****@*****.**": 1 } switch = { "@odata.context": "/redfish/v1/$metadata#EthernetSwitch.EthernetSwitch", "@odata.id": "/redfish/v1/EthernetSwitches/1", "@odata.type": "#EthernetSwitch.v1_0_0.EthernetSwitch", "Ports": { "@odata.id": "redfish/v1/EthernetSwitches/1/Ports" } } switch_port_collection = { "@odata.context": "/redfish/v1/$metadata#EthernetSwitchPortCollection.EthernetSwitchPortCollection", "@odata.id": "/redfish/v1/EthernetSwitches/1/Ports", "@odata.type": "#EthernetSwitchPortCollection.EthernetSwitchPortCollection", "Members": [ { "@odata.id": "/redfish/v1/EthernetSwitches/1/Ports/xyz" }, { "@odata.id": "/redfish/v1/EthernetSwitches/1/Ports/22-grubykot-1" } ], "*****@*****.**": 2 } port1 = { "@odata.context": "/redfish/v1/$metadata#EthernetSwitchPort.EthernetSwitchPort", "@odata.id": "/redfish/v1/EthernetSwitches/1/Ports/xyz", "@odata.type": "#EthernetSwitchPort.v1_0_0.EthernetSwitchPort", "PortId": "kot, ale czyj?" } port2 = { "@odata.context": "/redfish/v1/$metadata#EthernetSwitchPort.EthernetSwitchPort", "@odata.id": "/redfish/v1/EthernetSwitches/1/Ports/22-grubykot-1", "@odata.type": "#EthernetSwitchPort.v1_0_0.EthernetSwitchPort", "PortId": "prezes, ale jakie ma zwierze?" } task_service = { "@odata.context": "/redfish/v1/$metadata#TaskService.TaskService", "@odata.id": "/redfish/v1/TaskService", "@odata.type": "#TaskService.v1_0_0.TaskService", "Tasks": { "@odata.id": "/redfish/v1/TaskService/Tasks" } } task_collection = { "@odata.context": "/redfish/v1/$metadata#TaskCollection.TaskCollection", "@odata.id": "/redfish/v1/TaskService/Tasks", "@odata.type": "#TaskCollection.TaskCollection", "Members": [ { "@odata.id": "/redfish/v1/TaskService/Tasks/first_task" } ], "*****@*****.**": 0, } task = { "@odata.context": "/redfish/v1/$metadata#Task.Task", "@odata.id": "/redfish/v1/TaskService/Tasks/first_task", "@odata.type": "#Task.v1_0_0.Task", "Name": "Task" } discovery_container.add_resource(ApiResource("/redfish/v1/EthernetSwitches", 'netloc', switch_collection, 'EthernetSwitchCollection.v1_0_0.EthernetSwitchCollection')) discovery_container.register_url_pattern('/redfish/v1/EthernetSwitches', "EthernetSwitchCollection.EthernetSwitchCollection") discovery_container.add_resource(ApiResource("/redfish/v1/EthernetSwitches/1", 'netloc', switch, 'EthernetSwitch.v1_0_0.EthernetSwitch')) discovery_container.register_url_pattern('/redfish/v1/EthernetSwitches/1', 'EthernetSwitch.v1_0_0.EthernetSwitch') discovery_container.add_resource(ApiResource("/redfish/v1/EthernetSwitches/1/Ports", 'netloc', switch_port_collection, 'EthernetSwitchPortCollection.EthernetSwitchPortCollection"')) discovery_container.register_url_pattern('/redfish/v1/EthernetSwitches/1/Ports', 'EthernetSwitchPortCollection.EthernetSwitchPortCollection"') discovery_container.add_resource(ApiResource("/redfish/v1/EthernetSwitches/1/Ports/xyz", 'netloc', port1, 'EthernetSwitchPort.v1_0_0.EthernetSwitchPort')) discovery_container.register_url_pattern('/redfish/v1/EthernetSwitches/1/Ports/xyz', 'EthernetSwitchPort.v1_0_0.EthernetSwitchPort') discovery_container.add_resource(ApiResource("/redfish/v1/EthernetSwitches/1/Ports/22-grubykot-1", 'netloc', port2, 'EthernetSwitchPort.v1_0_0.EthernetSwitchPort')) discovery_container.register_url_pattern('/redfish/v1/EthernetSwitches/1/Ports/22-grubykot-1', 'EthernetSwitchPort.v1_0_0.EthernetSwitchPort') discovery_container.add_resource(ApiResource("/redfish/v1/TaskService", 'netloc', task_service, 'TaskService.v1_0_0.TaskService')) discovery_container.register_url_pattern('/redfish/v1/TaskService', 'TaskService.v1_0_0.TaskService') discovery_container.add_resource(ApiResource("/redfish/v1/TaskService/Tasks", 'netloc', task_collection, 'TaskCollection.TaskCollection')) discovery_container.register_url_pattern('/redfish/v1/TaskService/Tasks', 'TaskCollection.TaskCollection') discovery_container.add_resource(ApiResource("/redfish/v1/TaskService/Tasks/first_task", 'netloc', task, 'Task.v1_0_0.Task')) discovery_container.register_url_pattern('/redfish/v1/TaskService/Tasks/first_task', 'Task.v1_0_0.Task') self.assertEqual( discovery_container.get_expected_odata_type_for_url("/redfish/v1/EthernetSwitches/x"), 'EthernetSwitch.v1_0_0.EthernetSwitch') self.assertEqual( discovery_container.get_expected_odata_type_for_url("/redfish/v1/EthernetSwitches/1/Ports/bla/"), 'EthernetSwitchPort.v1_0_0.EthernetSwitchPort') port1_url = '/redfish/v1/EthernetSwitches/1/Ports/xyz' port2_url = '/redfish/v1/EthernetSwitches/1/Ports/22-grubykot-1' task_service_url = "/redfish/v1/TaskService" task_collection_url = "/redfish/v1/TaskService/Tasks" task_url = "/redfish/v1/TaskService/Tasks/first_task" task_generalized_url = "/redfish/v1/TaskService/Tasks/*" self.assertEqual(task_service_url, discovery_container._generalize_url(task_service_url)) self.assertEqual(task_collection_url, discovery_container._generalize_url(task_collection_url)) self.assertEqual(task_generalized_url, discovery_container._generalize_url(task_url)) # test_identical_error_id_for_related_odata_id(self): with StdoutCapture() as output: cts_error('{odata_id:id}', odata_id=port1_url) match = re.search("\[#Id=(?P<id>[0-9a-f]{32})\]", output.raw) self.assertIsNotNone(match) id_1 = match.group('id') with StdoutCapture() as output: cts_error('{odata_id:id}', odata_id=port2_url) match = re.search("\[#Id=(?P<id>[0-9a-f]{32})\]", output.raw) self.assertIsNotNone(match) id_2 = match.group('id') self.assertEqual(id_1, id_2) # test_different_error_ids_for_generalized_and_not_generalized_odata_id(self): with StdoutCapture() as output: cts_error('{odata_id:id}', odata_id=port1_url) match = re.search("\[#Id=(?P<id>[0-9a-f]{32})\]", output.raw) self.assertIsNotNone(match) id_for_generalized = match.group('id') with StdoutCapture() as output: cts_error('odata_id={odata_id}', odata_id=port2_url) match = re.search("\[#Id=(?P<id>[0-9a-f]{32})\]", output.raw) self.assertIsNotNone(match) id_for_not_generalized = match.group('id') self.assertNotEqual(id_for_generalized, id_for_not_generalized)
def test_dataframes(self): metadata_container = MetadataManager(["qualifier"]).\ read_metadata_from_strings("Unknown", self.TEST_METADATA) dc = DiscoveryContainer(service_root="/redfish/v1", metadata_container=metadata_container) chassis1_2_1 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Rack1", "@odata.type": "#Chassis.v1_2_0.Chassis", "ChassisType": "Rack", "SomeValue": 1, } chassis1_2_2 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Rack2", "@odata.type": "#Chassis.v1_2_0.Chassis", "ChassisType": "Rack", "SomeValue": 3, } chassis1_0_1 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Module1", "@odata.type": "#Chassis.v1_0_0.Chassis", "ChassisType": "Module", "SomeValue": 2, } chassis1_0_2 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Module2", "@odata.type": "#Chassis.v1_0_0.Chassis", "ChassisType": "Module", "SomeValue": 4, } dc.add_resource(ApiResource("/redfish/v1/Chassis/Rack1", 'netloc', chassis1_2_1, "Chassis.v1_2_0.Chassis")) dc.add_resource(ApiResource("/redfish/v1/Chassis/Rack2", 'netloc',chassis1_2_2, "Chassis.v1_2_0.Chassis")) dc.add_resource(ApiResource("/redfish/v1/Chassis/Module1", 'netloc',chassis1_0_1, "Chassis.v1_0_0.Chassis")) dc.add_resource(ApiResource("/redfish/v1/Chassis/Module2", 'netloc',chassis1_0_2, "Chassis.v1_0_0.Chassis")) def _some_values(resource_list): return [resource.body["SomeValue"] for _, resource in resource_list] self.assertEqual(2, dc.count_resources("Chassis.v1_2_0.Chassis")) self.assertEqual(2, dc.count_resources("Chassis.v1_2_0.Chassis", any_child_version=True)) self.assertEqual(2, dc.count_resources("Chassis.v1_0_0.Chassis")) self.assertEqual(4, dc.count_resources("Chassis.v1_0_0.Chassis", any_child_version=True)) self.assertEqual(0, dc.count_resources("Chassis.Chassis")) self.assertEqual(4, dc.count_resources("Chassis.Chassis", any_child_version=True)) self.assertEqual([1,2,3,4], _some_values(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[order_by("SomeValue")]))) self.assertEqual(2, len(dc.get_resources("Chassis.v1_2_0.Chassis"))) self.assertEqual(4, len(dc.get_resources("Chassis.Chassis", any_child_version=True))) self.assertEqual([1,2,3], _some_values(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[order_by("SomeValue"), first(3)]))) self.assertEqual([2,1], _some_values(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[order_by("SomeValue", ascending=False), last(2)]))) self.assertEqual([3,4], _some_values(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[order_by("SomeValue"), last(2)]))) self.assertEqual(2, len(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[less("SomeValue", 3)]))) self.assertEqual(3, len(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[less_or_equal("SomeValue", 3)]))) self.assertEqual(1, len(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[equal("SomeValue", 3)]))) self.assertEqual(3, len(dc.get_resources("Chassis.Chassis", any_child_version=True, constraints=[not_equal("SomeValue", 3)]))) self.assertEqual(0, len(dc.get_resources("Chassis.Chassis", any_child_version=False, constraints=[order_by("SomeValue")]))) self.assertEqual(0, len(dc.get_resources("Chassis.v1_2_0.Chassis", any_child_version=False, constraints=[greater("SomeValue", 3)]))) self.assertEqual(1, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[greater("SomeValue", 3)]))) self.assertEqual(2, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[greater_or_equal("SomeValue", 3)]))) self.assertEqual(4, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[from_collection("/redfish/v1/Chassis")]))) chassis1_0_2["@odata.id"] = "/redfish/v1/Chassis2/Module2" dc.add_resource(ApiResource("/redfish/v1/Chassis2/Module2", 'netloc', chassis1_0_2, "Chassis.v1_0_0.Chassis")) self.assertEqual(4, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[from_collection("/redfish/v1/Chassis")]))) self.assertEqual(1, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[from_collection("/redfish/v1/Chassis2")]))) self.assertEqual(2, len(dc.get_resources("Chassis.v1_0_0.Chassis", any_child_version=True, constraints=[urls(["/redfish/v1/Chassis/Rack1", "/redfish/v1/Chassis/Module1"])])))
class AdditionalPropertiesPatchTest(unittest.TestCase): METADATA = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="MyNamespace.v1_0_0"> <EntityType Name="MyEntity"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> <Property Name="Outer" Nullable="false" Type="OuterComplexType"/> </EntityType> <ComplexType Name="OuterComplexType"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> <Property Name="Name" Nullable="false" Type="Edm.String"/> </ComplexType> <ComplexType Name="InnerComplexType"> <Annotation Term="OData.AdditionalProperties" Bool="false"/> <Property Name="Name" Nullable="false" Type="Edm.String"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/> <Annotation Term="IntelRackScale.Nontrivial" String="Ability to write this property value is implementation specific." </Property> <Property Name="NotRequired" type="Edm.String"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/ReadWrite"/> <Annotation Term="IntelRackScale.Nontrivial" String="Ability to write this property value is implementation specific." </Property> </ComplexType> </Schema> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="IntelRackScale"> <Term Name="Nontrivial" Type="Edm.String" AppliesTo="Property"> <Annotation Term="OData.Description" String="The term shall be applied to a property in order to specify nontrivial preconditions, postconditions, side-effects or invariants that need to be satisfied."/> </Term> </Schema> """ def setUp(self): self.discovery_container = DiscoveryContainer() def test_should_not_patch_if_property_annotation_is_non_trivial_and_alternative_implementation_not_known(self): """ when additional property of type 'ComplexType' does have annotation Term Nontriavial should not be patched """ metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings(AdditionalPropertiesPatchTest.METADATA) entity_json = { "@odata.type": "MyNamespace.v1_0_0.MyEntity", "Outer": { "@odata.type": "MyNamespace.v1_0_0.OuterComplexType", "Name": "OuterName", "InnerToValidate": { "@odata.type": "MyNamespace.v1_0_0.InnerComplexType", "Name": "This name property is required" } } } self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", "netloc", entity_json, "#MyNamespace.v1_0_0.MyEntity")) with mock.patch('cts_core.commons.api_caller.ApiCaller.__init__') as api_caller_init_mock: api_caller_init_mock.return_value = None validator = MetadataPatchValidator(metadata_container, None, PatchingStrategy2_2()) # this ValidationStatus.BLOCKED should be not affect final ValidationStatus validator._verify_property = MagicMock(return_value=(ValidationStatus.BLOCKED, None)) validator._restore_property = MagicMock(return_value=ValidationStatus.BLOCKED) validator._patch_property = MagicMock(return_value=(True, True, ValidationStatus.BLOCKED)) with StdoutCapture() as out: self.assertEqual(ValidationStatus.PASSED_WITH_WARNINGS, validator.validate(self.discovery_container)) self.assertIn('WARNING::Skipping non-trivial property Name;', out.raw) def test_patch_nontrivial_boot_property(self): metadata_manager = MetadataManager(["qualifier"]) this_dir = os.path.dirname(os.path.realpath(__file__)) metadata_dir = os.path.join(this_dir, 'metadata') self.assertTrue(metadata_manager.read_metadata_from_dir(metadata_dir)) metadata_container = metadata_manager.metadata_container entity_json ={ "@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem", "@odata.id": "/redfish/v1/Systems/34", "@odata.type": "#ComputerSystem.v1_3_0.ComputerSystem", "Id": "34", "Name": "Computer System", "Description": "Computer System description", "SystemType": "Physical", "AssetTag": "AZaz09[]!@#$%^&*()_+", "Manufacturer": None, "Model": None, "SKU": None, "SerialNumber": None, "PartNumber": None, "UUID": "1d7a1040-05e4-11e6-a108-54ab3a8ec80f", "HostName": None, "Status": { "State": "Enabled", "Health": "OK", "HealthRollup": "OK" }, "IndicatorLED": None, "PowerState": "Off", "BiosVersion": "F20A3A03", "Boot": { "@odata.type": "#ComputerSystem.v1_1_0.Boot", "BootSourceOverrideEnabled": "Disabled", "BootSourceOverrideTarget": "None", "*****@*****.**": [ "Hdd", "Pxe", "None", "RemoteDrive" ], "BootSourceOverrideMode": "Legacy", "*****@*****.**": [ "Legacy", "UEFI" ] }, "ProcessorSummary": { "Count": 2, "Model": "Intel(R) Xeon(R)", "Status": { "State": "Enabled", "Health": "OK", "HealthRollup": "OK" } }, "MemorySummary": { "TotalSystemMemoryGiB": 30.52, "Status": { "State": "Enabled", "Health": "OK", "HealthRollup": "OK" } }, "Processors": { "@odata.id": "/redfish/v1/Systems/34/Processors" }, "EthernetInterfaces": { "@odata.id": "/redfish/v1/Systems/34/EthernetInterfaces" }, "NetworkInterfaces": { "@odata.id": "/redfish/v1/Systems/34/NetworkInterfaces" }, "Storage": { "@odata.id": "/redfish/v1/Systems/34/Storage" }, "Memory": { "@odata.id": "/redfish/v1/Systems/34/Memory" }, "PCIeDevices": [], "PCIeFunctions": [], "TrustedModules": [], "Links": { "@odata.type": "#ComputerSystem.v1_2_0.Links", "Chassis": [ { "@odata.id": "/redfish/v1/Chassis/38" } ], "Endpoints": [], "ManagedBy": [ { "@odata.id": "/redfish/v1/Managers/38" } ], "Oem": {} }, "Actions": { "#ComputerSystem.Reset": { "target": "/redfish/v1/Systems/34/Actions/ComputerSystem.Reset", "*****@*****.**": [ "On", "ForceOff", "GracefulShutdown", "GracefulRestart", "ForceRestart" ] }, "Oem": { "#Intel.Oem.ChangeTPMState": { "target": "/redfish/v1/Systems/34/Actions/Oem/Intel.Oem.ChangeTPMState", "*****@*****.**": [] } } }, "Oem": { "Intel_RackScale": { "@odata.type": "#Intel.Oem.ComputerSystem", "PciDevices": [], "PCIeConnectionId": [], "ProcessorSockets": 2, "MemorySockets": 16, "DiscoveryState": "Basic", "UserModeEnabled": None, "TrustedExecutionTechnologyEnabled": None, "Metrics": { "@odata.id": "/redfish/v1/Systems/34/Metrics" } } } } self.discovery_container.add_resource(ApiResource("/redfish/v1/Systems/34", "https://*****:*****@odata.type": "#Role.v1_0_0.Role", "Description": "Administrator User Role", "OemPrivileges": [ "OemClearLog", "OemPowerControl" ], "@odata.id": "/redfish/v1/AccountService/Roles/Administrator", "@odata.context": "/redfish/v1/$metadata#AccountService/Roles/Administrator/$entity", "AssignedPrivileges": [ "Login", "ConfigureManager", "ConfigureUsers", "ConfigureSelf", "ConfigureComponents" ], "Id": "Administrator", "IsPredefined": True, "Name": "User Role" } role_operator_json = { "@odata.type": "#Role.v1_0_0.Role", "Description": "Operator User Role", "OemPrivileges": [], "@odata.id": "/redfish/v1/AccountService/Roles/Operator", "@odata.context": "/redfish/v1/$metadata#AccountService/Roles/Operator/$entity", "AssignedPrivileges": [ "Login", "ConfigureSelf", "ConfigureComponents" ], "Id": "Operator", "IsPredefined": True, "Name": "User Role" } role_readonly_json = { "@odata.type": "#Role.v1_0_0.Role", "Description": "ReadOnly User Role", "OemPrivileges": [], "@odata.id": "/redfish/v1/AccountService/Roles/ReadOnly", "@odata.context": "/redfish/v1/$metadata#AccountService/Roles/ReadOnly/$entity", "AssignedPrivileges": [ "Login", "ConfigureSelf" ], "Id": "ReadOnly", "IsPredefined": True, "Name": "User Role" } role_custom_json = { "@odata.type": "#Role.v1_0_0.Role", "Description": "Custom User Role", "OemPrivileges": [], "@odata.id": "/redfish/v1/AccountService/Roles/Custom", "@odata.context": "/redfish/v1/$metadata#AccountService/Roles/ReadOnly/$entity", "AssignedPrivileges": [ "Login", "ConfigureSelf" ], "Id": "ReadOnly", "IsPredefined": False, "Name": "Custom Role" } self.discovery_container.add_resource(ApiResource("/redfish/v1/AccountService/Roles/Administrator", "https://localhost:8443", role_administrator_json, "#Role.v1_0_0.Role")) self.discovery_container.add_resource(ApiResource("/redfish/v1/AccountService/Roles/Operator", "https://localhost:8443", role_operator_json, "#Role.v1_0_0.Role")) self.discovery_container.add_resource(ApiResource("/redfish/v1/AccountService/Roles/ReadOnly", "https://localhost:8443", role_readonly_json, "#Role.v1_0_0.Role")) self.discovery_container.add_resource(ApiResource("/redfish/v1/AccountService/Roles/Custom", "https://localhost:8443", role_custom_json, "#Role.v1_0_0.Custom")) with mock.patch('cts_core.commons.api_caller.ApiCaller.__init__') as api_caller_init_mock: api_caller_init_mock.return_value = None validator = MetadataPatchValidator(metadata_container, None, PatchingStrategy2_2()) # this ValidationStatus.BLOCKED should be not affect final ValidationStatus validator._verify_property = MagicMock(return_value=(ValidationStatus.PASSED, None)) validator._restore_property = MagicMock(return_value=ValidationStatus.PASSED) validator._patch_property = MagicMock(return_value=(True, True, ValidationStatus.PASSED)) with mock.patch('cts_core.validation.patch.metadata_patch_validator.MetadataPatchValidator' '._validate_resource') as validate_resource: with StdoutCapture() as out: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container)) self.assertEquals(1, validate_resource.call_count) # only for 'custom' role
class PowerMonitoringUnitTest(unittest.TestCase): def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings(METADATA) HardwareCheckList.MetadataConstants = MetadataConstants2_2 self.checklist = HardwareCheckList(dict()) #monkey patch self.checklist._load_metadata = lambda : self.metadata_container def test_should_fail_on_empty_pod(self): with StdoutCapture() as output: self.checklist.at_least_one_compute_module_in_pod(self.discovery_container) self.assertEqual(ValidationStatus.FAILED, self.checklist.validation_status) def test_should_pass_for_chassis_with_power_zone(self): self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-powerzones", 'netloc', RACK_WITH_POWER_ZONES, "Chassis.v1_1_0.Chassis")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-powerzones/PowerZones", 'netloc', POWER_ZONES, "PowerZoneCollection.PowerZoneCollection")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-powerzones/PowerZones/1", 'netloc',POWER_ZONE_1, "PowerZone.v1_0_0.PowerZone")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-powerzones/Power", 'netloc', POWER_EMPTY, "Power.v1_1_0.Power")) with StdoutCapture() as output: self.checklist.power_monitoring_support(self.discovery_container) self.assertEqual(ValidationStatus.PASSED, self.checklist.validation_status) def test_should_pass_for_chassis_with_power(self): self.discovery_container.add_resource(ApiResource("/redfish/v1/Chassis/rack-with-power", 'netloc', RACK_WITH_POWER, "Chassis.v1_1_0.Chassis")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-power/PowerZones", 'netloc', POWER_ZONES_EMPTY, "PowerZoneCollection.PowerZoneCollection")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-power/Power", 'netloc', POWER_WITH_POWER_CONTROL, "Power.v1_1_0.Power")) self.discovery_container.add_resource(ApiResource( "/redfish/v1/Chassis/rack-with-power/Power/PowerControl/1", 'netloc', POWER_CONTROL_1, "Power.v1_1_0.PowerControl")) with StdoutCapture() as output: self.checklist.power_monitoring_support(self.discovery_container) self.assertEqual(ValidationStatus.PASSED, self.checklist.validation_status)
def setUp(self): self.discovery_container = DiscoveryContainer()