def test_should_patch_complex_type_level_additional_typed_property(self):
        """
        when additional property of type 'ComplexType' does have odata.type specified
         we can validate it
        """
        EntityJson = {
            "@odata.id": "odata.id",
            "@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",
                                                          EntityJson, "#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(self.metadata_container, None, PatchingStrategy2_1())
            validator._patch_and_verify_property = MagicMock(return_value= (ValidationStatus.PASSED, "new_value"))
            validator._restore_property = MagicMock(return_value=ValidationStatus.PASSED)


            with StdoutCapture() as output:
                self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
            self.assertGreater(validator._patch_and_verify_property.call_count, 0)
    def test_should_not_patch_complex_type_level_additional_property_without_odatatype(self):
        """
        when additional property of type 'ComplexType' does not have odata.type specified
         we cannot validate it
        """
        EntityJson = {
            "@odata.type": "MyNamespace.v1_0_0.MyEntity",
            "Outer" : {
                "@odata.type": "MyNamespace.v1_0_0.OuterComplexType",
                "Name" : "OuterName",
                "InnerToNotValidate" : {
                    #odatatype intentionally skipped
                    "foo" : "bar"
                }
            }
        }

        self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", "netloc",
                                              EntityJson, "#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(self.metadata_container, None, PatchingStrategy2_1())
            validator._patch_and_verify_property = MagicMock(return_value=ValidationStatus.PASSED)

            with StdoutCapture() as output:
                self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))

            validator._patch_and_verify_property.assert_not_called()
    def test_should_pass_and_not_patch_write_entity(self):
        ENTITYJSON = {
            "@odata.type": "MyNamespace.v1_0_0.MyEntity",
            "Outer": {
                "@odata.type": "MyNamespace.v1_0_0.OuterComplexType",
                "Name": "OuterName",
                "InnerToValidate": {
                    "@odata.type": "MyNamespace.v1_0_0.SecondInnerComplexType",
                    "Name": "This name property is required"
                }
            }
        }

        self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", "netloc", ENTITYJSON,
                                                          "#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(self.metadata_container, None, PatchingStrategy2_1())

            # return of _verify_property should not block test if OData.Permission is Write
            validator._verify_property = MagicMock(return_value=(ValidationStatus.BLOCKED, None))

            validator._patch_property = MagicMock(return_value=(True, True, ValidationStatus.PASSED))
            validator._restore_property = MagicMock(return_value=ValidationStatus.PASSED)

            with StdoutCapture():
                self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
            # _verify_property should not be called if OData.Permission is Write
            self.assertEqual(validator._verify_property.call_count, 0)
    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 run(self):
        print "TEST_CASE::API crawling"
        api_explorer = ApiExplorer(self.metadata_container, self.configuration)

        discovery_container, status = api_explorer.discover(
            MetadataConstants.SERVICE_ROOT_URI, MetadataConstants.SERVICE_ROOT)
        print "STATUS::{status}".format(status=status)

        validator = MetadataPatchValidator(self.metadata_container,
                                           self.configuration,
                                           PatchingStrategy2_1(),
                                           RequiredTypes_Storage_2_1)
        validator.validate(discovery_container)
    def run(self):
        if self.metadata_container is None:
            return

        print "TEST_CASE::API crawling"
        api_explorer = ApiExplorer(self.metadata_container, self.configuration)

        discovery_container, status = api_explorer.discover(MetadataConstants.SERVICE_ROOT_URI,
                                                            MetadataConstants.SERVICE_ROOT)
        print "STATUS::{status}".format(status=status)

        validator = MetadataPatchValidator(self.metadata_container, self.configuration,
                                           PatchingStrategy2_4(), RequiredTypes_PODM_2_4,
                                           skip_list=self.configuration.IgnoredElements)
        validator.validate(discovery_container)
        performance_status = self._measuring_request_responses(api_explorer)
        print("STATUS::{status}".format(status=performance_status))
    def run(self):
        if self.metadata_container is None:
            return

        print "TEST_CASE::API crawling"
        api_explorer = ApiExplorer(self.metadata_container, self.configuration)

        discovery_container, status = api_explorer.discover(
            MetadataConstants.SERVICE_ROOT_URI, MetadataConstants.SERVICE_ROOT)
        print "STATUS::{status}".format(status=status)

        requirements = [
            Requirement(MetadataConstants.SERVICE_ROOT, min=1, max=1)
        ]
        validator = MetadataPatchValidator(self.metadata_container,
                                           self.configuration,
                                           PatchingStrategy2_1(), requirements)
        validator.validate(discovery_container)
示例#8
0
    def test_should_patch_complex_type_level_additional_typed_property(self):
        """
        when additional property of type 'ComplexType' does have odata.type specified
         we can validate it
        """
        EntityJson = {
            "@odata.id": "odata.id",
            "@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", EntityJson,
                        "#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(self.metadata_container, None,
                                               PatchingStrategy2_1())
            validator._patch_and_verify_property = MagicMock(
                return_value=(ValidationStatus.PASSED, "new_value"))
            validator._restore_property = MagicMock(
                return_value=ValidationStatus.PASSED)

            with StdoutCapture() as output:
                self.assertEqual(ValidationStatus.PASSED,
                                 validator.validate(self.discovery_container))
            self.assertGreater(validator._patch_and_verify_property.call_count,
                               0)
    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)
示例#10
0
    def test_should_not_patch_complex_type_level_additional_property_without_odatatype(
            self):
        """
        when additional property of type 'ComplexType' does not have odata.type specified
         we cannot validate it
        """
        EntityJson = {
            "@odata.type": "MyNamespace.v1_0_0.MyEntity",
            "Outer": {
                "@odata.type": "MyNamespace.v1_0_0.OuterComplexType",
                "Name": "OuterName",
                "InnerToNotValidate": {
                    #odatatype intentionally skipped
                    "foo": "bar"
                }
            }
        }

        self.discovery_container.add_resource(
            ApiResource("/redfish/v1/Managers/RMC", "netloc", EntityJson,
                        "#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(self.metadata_container, None,
                                               PatchingStrategy2_1())
            validator._patch_and_verify_property = MagicMock(
                return_value=ValidationStatus.PASSED)

            with StdoutCapture() as output:
                self.assertEqual(ValidationStatus.PASSED,
                                 validator.validate(self.discovery_container))

            validator._patch_and_verify_property.assert_not_called()
    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)
示例#12
0
    def test_should_pass_and_not_patch_write_entity(self):
        ENTITYJSON = {
            "@odata.type": "MyNamespace.v1_0_0.MyEntity",
            "Outer": {
                "@odata.type": "MyNamespace.v1_0_0.OuterComplexType",
                "Name": "OuterName",
                "InnerToValidate": {
                    "@odata.type": "MyNamespace.v1_0_0.SecondInnerComplexType",
                    "Name": "This name property is required"
                }
            }
        }

        self.discovery_container.add_resource(
            ApiResource("/redfish/v1/Managers/RMC", "netloc", ENTITYJSON,
                        "#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(self.metadata_container, None,
                                               PatchingStrategy2_1())

            # return of _verify_property should not block test if OData.Permission is Write
            validator._verify_property = MagicMock(
                return_value=(ValidationStatus.BLOCKED, None))

            validator._patch_property = MagicMock(
                return_value=(True, True, ValidationStatus.PASSED))
            validator._restore_property = MagicMock(
                return_value=ValidationStatus.PASSED)

            with StdoutCapture():
                self.assertEqual(ValidationStatus.PASSED,
                                 validator.validate(self.discovery_container))
            # _verify_property should not be called if OData.Permission is Write
            self.assertEqual(validator._verify_property.call_count, 0)
    def test_patch_nontrivial_roles(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

        role_administrator_json = {
            "@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
    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://localhost:8443",
                        entity_json, "#ComputerSystem.v1_3_0.ComputerSystem"))

        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.commons.api_caller.ApiCaller.patch_resource'
            ) as api_caller_patch_resource:
                api_caller_patch_resource.return_value = (
                    RequestStatus.SUCCESS, 200, None, None)
                with mock.patch(
                        'cts_core.commons.api_caller.ApiCaller.get_resource'
                ) as api_caller_get_resource:
                    api_caller_get_resource.return_value = (Link(
                        "/redfish/v1/Systems/34",
                        "https://localhost:8443"), RequestStatus.SUCCESS, 200,
                                                            entity_json, None)

                    with StdoutCapture() as out:
                        self.assertEqual(
                            ValidationStatus.PASSED,
                            validator.validate(self.discovery_container))

                    self.assertNotIn('WARNING::Skipping non-trivial property',
                                     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://localhost:8443",
                                                          entity_json, "#ComputerSystem.v1_3_0.ComputerSystem"))

        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.commons.api_caller.ApiCaller.patch_resource') as api_caller_patch_resource:
                api_caller_patch_resource.return_value = (RequestStatus.SUCCESS, 200, None, None)
                with mock.patch('cts_core.commons.api_caller.ApiCaller.get_resource') as api_caller_get_resource:
                    api_caller_get_resource.return_value = (Link("/redfish/v1/Systems/34", "https://localhost:8443"),
                                                            RequestStatus.SUCCESS,
                                                            200,
                                                            entity_json,
                                                            None)

                    with StdoutCapture() as out:
                        self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))

                    self.assertNotIn('WARNING::Skipping non-trivial property', out.raw)
    def test_patch_nontrivial_roles(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

        role_administrator_json = {
            "@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