def sanitize_configuration(cls, can_run, configuration): test_case_configuration = Configuration() for parameter in cls.CONFIGURATION_PARAMETERS: configuration_param_value = getattr(configuration, parameter.name) if configuration_param_value is None and parameter.is_required: cts_error("Required configuration parameter {name} not defined", name=parameter.name) can_run = False if configuration_param_value is None and parameter.default_value is not None: configuration_param_value = parameter.default_value test_case_configuration.update_configuration(**{parameter.name: configuration_param_value}) return can_run, test_case_configuration
def test_basic_auth_given(self): configuration = Configuration(**dict(User=USER, Password=PASSWORD, ApiEndpoint=API_ENDPOINT)) params, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertIn("auth", kwargs) self.assertEqual(kwargs["auth"], (USER, PASSWORD))
def test_certs_given(self): configuration = Configuration(**dict(CertificateCertFile=CERT_FILE, CertificateKeyFile=CERT_KEY, ApiEndpoint=API_ENDPOINT)) params, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertIn("cert", kwargs) self.assertEqual(kwargs["cert"], (CERT_FILE, CERT_KEY))
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_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 load(self, metadata_ref, qualifiers): if os.path.isfile(metadata_ref): metadata_manager = MetadataManager(qualifiers) configuration = get_configuration_from_file(metadata_ref) if configuration is None: return None if metadata_manager.download_metadata( Configuration(**configuration)): return metadata_manager.metadata_container return None
def test_discovery_error_if_unexpected_additional_properties(self): """ Entity type used in this test does not accept additional properties. As a result, ApiExplorer is expected to raise an error about unexpected 'additional_property' property. ApiExplorer validate """ metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <Property Name="@odata.id" Type="Edm.String"/> <Property Name="@odata.type" Type="Edm.String"/> <Property Name="expected" Type="Edm.Int64"/> <Annotation Term="OData.AdditionalProperties" Bool="false"/> </EntityType> </Schema> """ resource = \ { "@odata.id": "id", "@odata.type": "N.Outer", "expected": 10, "additional_property": 1 } 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) ] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(1, get_resource.call_count) self.assertIn("unexpected properties: [additional_property]", '\n'.join(output))
def test_follow_references_when_loading_remote_matadata(self): configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) manager = MetadataManager([]) with StdoutCapture() as output: with patch("cts_core.commons.api_caller.ApiCaller.get_xml" ) as get_xml: get_xml.side_effect = [ (None, RequestStatus.SUCCESS, 200, METADATA_ROOT, None), (None, RequestStatus.SUCCESS, 200, METADATA_ROOT, None) ] manager.download_metadata(configuration) arguments = [arg[0][0] for arg in get_xml.call_args_list] self.assertGreater( len([a for a in arguments if "Org.OData.Core.V1.xml" in a]), 0) self.assertEqual(-1, output.raw.find("ERROR::"))
def test_discovery_can_handle_null_navigation_property(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <NavigationProperty Name="Link" Type="N.Referenced" ContainsTarget="true"> </NavigationProperty> </EntityType> <EntityType Name="Referenced" Abstract="false"> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "#N.Outer", "Link": { "@odata.id": None }, } 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) ] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(1, get_resource.call_count) self.assertNotIn("ERROR::", '\n'.join(output))
def test_password_given_user_not(self): configuration = Configuration(**dict(Password=PASSWORD, ApiEndpoint=API_ENDPOINT)) params, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertNotIn("auth", kwargs)
def test_key_given_cert_not(self): configuration = Configuration(**dict(CertificateKeyFile=CERT_KEY, ApiEndpoint=API_ENDPOINT)) params, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertNotIn("cert", kwargs)
def test_ssl_default(self): configuration = Configuration(**dict(ApiEndpoint=API_ENDPOINT)) url, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertEqual(url, Link("http://%s%s" % (API_ENDPOINT, RESOURCE), API_ENDPOINT))
def test_handle_complex_types_with_dynamic_property_patterns(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <Property Name="inner" Type="N.TypeWithDynamics"/> </EntityType> <ComplexType Name="TypeWithDynamics" Abstract="false"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> <Annotation Term="Redfish.DynamicPropertyPatterns"> <Collection> <Record> <PropertyValue Property="Pattern" String="[a-z0-9]+"/> <PropertyValue Property="Type" String="N.Referenced"/> </Record> <Record> <PropertyValue Property="Pattern" String="[A-Z0-9]+"/> <PropertyValue Property="Type" String="Edm.String"/> </Record> </Collection> </Annotation> </ComplexType> <ComplexType Name="Referenced" Abstract="false"> <Property Name="name" Type="Edm.String"/> </ComplexType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "N.Outer", "inner": { "additional1": { "name": "additional#1" }, "additional2": { "name": "additional#2" }, "ADDITIONAL3": "ADDITIONAL3", "ADDITIONAL4": "ADDITIONAL4", "SiMpLeTyPeIsOk": 22, "CoMpLeXInVaLiD": {"x": 1} } } 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('https://{API_ENDPOINT}/outer'.format( API_ENDPOINT=API_ENDPOINT), 'netloc'), RequestStatus.SUCCESS, resource, None)] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(1, get_resource.call_count) self.assertEqual(1, len(re.findall('ERROR::', ';'.join(output)))) self.assertIn( 'ERROR::url=https://1.2.3.4:567/outer#inner.CoMpLeXInVaLiD: @odata.type not found in complex additional property;', ';'.join(output))
def test_basic_auth_not_given(self): configuration = Configuration(**dict(ApiEndpoint=API_ENDPOINT)) params, kwargs = ApiCaller(configuration)._build_request(RESOURCE) self.assertNotIn("auth", kwargs)
def setUp(self): configuration = Configuration(**dict(ApiEndpoint=API_ENDPOINT)) self.api_caller = ApiCaller(configuration)
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))))