コード例 #1
0
 def setUp(self):
     self.provider = LocalProvider()
     self.provider.add_interface(MockImpl())
     connector = LocalConnector(self.provider)
     stub_config = StubConfigurationFactory.new_std_configuration(connector)
     self.service = Service(stub_config)
     self.operation = Operation(stub_config)
コード例 #2
0
 def test_register_duplicate_interface(self):
     self.local_provider = LocalProvider()
     properties = ProviderConfig()
     properties.cfg = configparser.SafeConfigParser()
     properties.cfg.add_section(Sections.ENDPOINT)
     properties.cfg.set(
         Sections.ENDPOINT, 'local.interfaces',
         'test.vmware.vapi.provider.test_local,' +
         'test.vmware.vapi.provider.test_local')
     self.assertRaises(Exception,
                       self.local_provider.register_by_properties,
                       properties)
コード例 #3
0
    def setUp(self):
        self.api_iface = MockupApiInterface(interface_id)
        self.api_iface_2 = MockupApiInterface(interface_id_2)
        provider = LocalProvider()
        provider.add_interface(self.api_iface)
        provider.add_interface(self.api_iface_2)

        self.provider = InterposerProvider(provider)
コード例 #4
0
 def test_add_duplicate_interface(self):
     mockup_api_interface = MockupApiInterface()
     self.local_provider = LocalProvider()
     self.local_provider.add_interface(mockup_api_interface)
     self.assertRaises(Exception, self.local_provider.add_interface,
                       mockup_api_interface)
コード例 #5
0
 def setUp(self):
     mockup_api_interface = MockupApiInterface()
     self.local_provider = LocalProvider()
     self.local_provider.add_interface(mockup_api_interface)
     connector = LocalConnector(self.local_provider)
     self.introspection = IntrospectableApiProvider(connector)
コード例 #6
0
class TestLocalProvider(unittest.TestCase):
    def setUp(self):
        mockup_api_interface = MockupApiInterface()
        self.local_provider = LocalProvider()
        self.local_provider.add_interface(mockup_api_interface)
        connector = LocalConnector(self.local_provider)
        self.introspection = IntrospectableApiProvider(connector)

    def _test_method_failure(self,
                             operation_id,
                             error,
                             message_id=None,
                             *args):
        ctx = ExecutionContext()
        method_id = method_id_dict[operation_id]
        service_id = method_id.get_interface_identifier().get_name()

        if isinstance(error, ErrorValue):
            expected_error_value = error
        else:
            msg = message_factory.get_message(message_id, *args)
            expected_error_value = make_error_value_from_msgs(error, msg)

        provider = self.local_provider
        method_def = self.introspection.get_method(service_id, operation_id)
        input_value = method_def.get_input_definition().new_value()
        input_value.set_field(param_name, IntegerValue(0))
        method_result = provider.invoke(service_id, operation_id, input_value,
                                        ctx)

        self.assertEquals(None, method_result.output)
        self.assertEquals(expected_error_value, method_result.error)

    def _test_operation_not_found(self, interface_name, method_name, error,
                                  message_id, *args):
        ctx = ExecutionContext()
        expected_msg = message_factory.get_message(message_id, *args)
        expected_error_value = make_error_value_from_msgs(error, expected_msg)

        method_result = self.local_provider.invoke(interface_name, method_name,
                                                   StructValue(), ctx)

        self.assertEquals(None, method_result.output)
        self.assertEquals(expected_error_value, method_result.error)

    def test_add_duplicate_interface(self):
        mockup_api_interface = MockupApiInterface()
        self.local_provider = LocalProvider()
        self.local_provider.add_interface(mockup_api_interface)
        self.assertRaises(Exception, self.local_provider.add_interface,
                          mockup_api_interface)

    def test_register_duplicate_interface(self):
        self.local_provider = LocalProvider()
        properties = ProviderConfig()
        properties.cfg = configparser.SafeConfigParser()
        properties.cfg.add_section(Sections.ENDPOINT)
        properties.cfg.set(
            Sections.ENDPOINT, 'local.interfaces',
            'test.vmware.vapi.provider.test_local,' +
            'test.vmware.vapi.provider.test_local')
        self.assertRaises(Exception,
                          self.local_provider.register_by_properties,
                          properties)

    def test_report_declared_error(self):
        self._test_method_failure(report_declared_error, not_found_error)

    def test_report_undeclared_error(self):
        msg = message_factory.get_message(
            'vapi.method.status.errors.invalid', not_found_error.name,
            str(method_id_dict[report_undeclared_error].get_name()))
        expected_error = make_error_value_from_msgs(internal_server_error_def,
                                                    *([msg, _msg]))
        self._test_method_failure(report_undeclared_error, expected_error)

    def test_raise_python_exception(self):
        self._test_method_failure(raise_python_exception,
                                  internal_server_error_def,
                                  'vapi.method.invoke.exception',
                                  str(RuntimeError()))

    def test_invalid_input(self):
        ctx = ExecutionContext()
        expected_msg = message_factory.get_message('vapi.method.input.invalid')
        expected_error_value = make_error_value_from_msgs(
            invalid_argument_def, expected_msg)

        method_result = self.local_provider.invoke(
            service_id=raise_python_exception_id.get_interface_identifier(
            ).get_name(),
            operation_id=raise_python_exception_id.get_name(),
            input_value=IntegerValue(),
            ctx=ctx)

        self.assertEquals(None, method_result.output)
        self.assertEquals(expected_error_value, method_result.error)

    def test_input_validation_failure(self):
        ctx = ExecutionContext()
        expected_msg0 = message_factory.get_message(
            'vapi.data.structure.field.invalid', 'param', OPERATION_INPUT)
        expected_msg1 = message_factory.get_message(
            'vapi.data.validate.mismatch', 'Integer', 'Structure')
        expected_error_value = make_error_value_from_msgs(
            invalid_argument_def, expected_msg0, expected_msg1)

        service_id = raise_python_exception_id.get_interface_identifier(
        ).get_name()
        operation_id = raise_python_exception_id.get_name()
        method_def = self.introspection.get_method(service_id, operation_id)
        input_value = method_def.get_input_definition().new_value()
        input_value.set_field(param_name, StructValue())
        method_result = self.local_provider.invoke(service_id=service_id,
                                                   operation_id=operation_id,
                                                   input_value=input_value,
                                                   ctx=ctx)

        self.assertEquals(None, method_result.output)
        self.assertEquals(expected_error_value, method_result.error)

    def test_output_validation_failure(self):
        self._test_method_failure(return_invalid_output,
                                  internal_server_error_def,
                                  'vapi.data.validate.mismatch', 'Void',
                                  'Structure')

    def test_missing_interface(self):
        interface_name = 'bogus_interface'
        method_name = 'test_method'

        self._test_operation_not_found(interface_name, method_name,
                                       operation_not_found_def,
                                       'vapi.method.input.invalid.interface',
                                       interface_name)

    def test_missing_method(self):
        interface_name = interface_id.get_name()
        method_name = 'bogus_method'

        self._test_operation_not_found(interface_name, method_name,
                                       operation_not_found_def,
                                       'vapi.method.input.invalid.method',
                                       method_name)

    def test_introspection_operation_get(self):
        ctx = ExecutionContext()
        input_val = StructValue(OPERATION_INPUT)
        input_val.set_field('service_id', StringValue('mockup_interface'))
        input_val.set_field('operation_id', StringValue('mock'))
        actual_output = self.local_provider.invoke(
            'com.vmware.vapi.std.introspection.operation', 'get', input_val,
            ctx)
        expected_output = StructValue(
            name='com.vmware.vapi.std.introspection.operation.info')
        input_def_value = StructValue(
            'com.vmware.vapi.std.introspection.operation.data_definition')
        input_def_value.set_field('fields',
                                  OptionalValue(ListValue(values=[])))
        input_def_value.set_field('element_definition', OptionalValue())
        input_def_value.set_field('type', StringValue('STRUCTURE'))
        input_def_value.set_field('name',
                                  OptionalValue(StringValue(OPERATION_INPUT)))
        expected_output.set_field('input_definition', input_def_value)
        output_def_value = StructValue(
            'com.vmware.vapi.std.introspection.operation.data_definition')
        output_def_value.set_field('fields', OptionalValue())
        output_def_value.set_field('element_definition', OptionalValue())
        output_def_value.set_field('type', StringValue('VOID'))
        output_def_value.set_field('name', OptionalValue())
        expected_output.set_field('output_definition', output_def_value)
        expected_output.set_field('error_definitions', error_values)
        self.assertEqual(actual_output.output, expected_output)

    def test_success(self):
        ctx = ExecutionContext()
        service_id = interface_id.get_name()
        operation_id = mock_definition

        method_def = self.introspection.get_method(service_id, operation_id)
        input_value = method_def.get_input_definition().new_value()
        input_value.set_field(param_name, IntegerValue(10))
        method_result = self.local_provider.invoke(service_id, operation_id,
                                                   input_value, ctx)
        self.assertTrue(method_result.success())
        self.assertEqual(method_result.output, VoidValue())

    def test_success_2(self):
        ctx = ExecutionContext()
        service_id = interface_id.get_name()
        operation_id = mock_definition

        input_value = StructValue(OPERATION_INPUT)
        input_value.set_field(param_name, IntegerValue(10))
        method_result = self.local_provider.invoke(service_id, operation_id,
                                                   input_value, ctx)
        self.assertTrue(method_result.success())
        self.assertEqual(method_result.output, VoidValue())
コード例 #7
0
 def setUp(self):
     """ setup """
     self.to_vapi = JsonRpcDictToVapi
     api_iface = FakeInterface()
     self.provider = LocalProvider()
     self.provider.add_interface(api_iface)
コード例 #8
0
class TestJsonRpc(unittest.TestCase):

    def setUp(self):
        """ setup """
        self.to_vapi = JsonRpcDictToVapi
        api_iface = FakeInterface()
        self.provider = LocalProvider()
        self.provider.add_interface(api_iface)

    def tearDown(self):
        """ tear down """

    def to_json(self, value):
        return json.dumps(value,
                          check_circular=False,
                          separators=(',', ':'),
                          cls=VAPIJsonEncoder)

    def to_vapi_data_value(self, value):
        python_dict = json.loads(value, parse_float=decimal.Decimal)
        return self.to_vapi.data_value(python_dict)

    def to_vapi_method_result(self, value):
        python_dict = json.loads(value, parse_float=decimal.Decimal)
        return self.to_vapi.method_result(python_dict)

    def get_data_definition(self):
        # Get a cover all data definitions
        data_defs = [
            VoidDefinition(),
            IntegerDefinition(),
            DoubleDefinition(),
            StringDefinition(),
            SecretDefinition(),
            BooleanDefinition(),
            BlobDefinition(),
            OpaqueDefinition(),
            OptionalDefinition(IntegerDefinition()),
            ListDefinition(IntegerDefinition()),
            StructDefinition('struct',
                [ ('int', IntegerDefinition()),
                  ('str', StringDefinition()),
                  ('struct', StructDefinition('struct1',
                      [('double', DoubleDefinition()),
                       ('secret', SecretDefinition())])),
                  ('list', ListDefinition(StructDefinition('struct1',
                      [('double', DoubleDefinition()),
                       ('secret', SecretDefinition())]))),
                  ('optional', ListDefinition(StructDefinition('struct1',
                      [('double', DoubleDefinition()),
                       ('secret', SecretDefinition())]))) ]),
            ErrorDefinition('error',
                [ ('int', IntegerDefinition()),
                  ('str', StringDefinition()) ]),
        ]
        return data_defs


    def get_error_value(self):
        error_value = ErrorValue('struct0')
        error_value.set_field('int', IntegerValue(7))
        error_value.set_field('optional', OptionalValue(StringValue("123")))
        error_value.set_field('optional1', OptionalValue())
        return error_value

    def get_struct_value(self):
        struct_value = StructValue('struct0')
        struct_value.set_field('int', IntegerValue(7))
        struct_value.set_field('optional', OptionalValue(StringValue("123")))
        struct_value.set_field('optional1', OptionalValue())
        return struct_value

    def get_data_values(self):
        # Data values
        list_value = ListValue()
        list_value.add_all([IntegerValue(val) for val in range(1,15)])
        data_values = [
            VoidValue(),
            IntegerValue(3),
            DoubleValue(decimal.Decimal('7.2')),
            StringValue('blah'),
            SecretValue(),
            BooleanValue(True),
            BlobValue(b"a blob"),
            BlobValue(b"0\x82\x04\x00"),
            list_value,
            OptionalValue(),
            OptionalValue(IntegerValue(7)),
            StructValue('name'),
            self.get_struct_value(),
            self.get_error_value(),
        ]
        struct_value = StructValue('struct')
        for idx, data_val in enumerate(data_values):
            struct_value.set_field(str(idx), data_val)
        data_values.append(struct_value)
        return data_values

    def test_method_result(self):
        # Method result
        error_value = self.get_error_value()
        method_result = MethodResult(error=error_value)
        self.assertEqual(self.to_vapi_method_result(self.to_json(method_result)).error, method_result.error)

        data_values = self.get_data_values()
        for data_value in data_values:
            method_result = MethodResult(output=data_value)
            self.assertEqual(self.to_vapi_method_result(self.to_json(method_result)).output, method_result.output)

    def test_data_value_conversion(self):
        data_values = self.get_data_values()
        for data_value in data_values:
            json_value = self.to_json(data_value)
            self.assertEqual(self.to_vapi_data_value(json_value),
                             data_value)

        json_value = self.to_json(DoubleValue(17.0))
        self.assertEqual('1.7E1', json_value)
        vapi_value = self.to_vapi_data_value('1.7E1')
        self.assertEqual(DoubleValue(decimal.Decimal('1.7E1')), vapi_value)

    def test_jsonrpc_invalid_params_1(self):
        invalid_json = '{"STRUCTURE": {"vapi.struct": {}}, "bogus": "bogus"}'
        self.assertRaises(JsonRpc20Error, self.to_vapi_data_value, invalid_json)

    def test_jsonrpc_invalid_params_2(self):
        invalid_json = '{"STRUCTURE": {"vapi.struct": {}, "bogus": "bogus"}}'
        self.assertRaises(JsonRpc20Error, self.to_vapi_data_value, invalid_json)

    def test_jsonrpc_invalid_binary_value(self):
        invalid_json = '{"BINARY": "bogus"}'
        self.assertRaises(JsonRpc20Error, self.to_vapi_data_value, invalid_json)

    def test_json_rpc_positive(self):
        requests = [
            # id can be null, number, string, or omitted
            ('{"jsonrpc": "2.0", "method": "subtract", "id": null}', None),
            ('{"jsonrpc": "2.0", "method": "subtract", "id": 3}',
             '{"jsonrpc": "2.0", "result": 0, "id": 3}'),
            ('{"jsonrpc": "2.0", "method": "subtract", "id": "string_id"}',
             '{"jsonrpc": "2.0", "result": 0, "id": "string_id"}'),

            # Accept keyed parameters. Do not accept array parameters
            ('{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
             '{"jsonrpc": "2.0", "result": 19, "id": 3}'),
        ]

        for request_str, response_str in requests:
            request = deserialize_request(request_str)
            self.assertFalse(request.notification)
            if response_str:
                response = deserialize_response(response_str)
                request.validate_response(response)
                request.serialize()

        notifications = [
            '{"jsonrpc": "2.0", "method": "subtract"}',
        ]
        for notification_str in notifications:
            request = deserialize_request(notification_str)
            self.assertTrue(request.notification)
            request.serialize_notification()


    def test_json_rpc_request_negative(self):
        requests = [
            ('', JsonRpc20Error.PARSE_ERROR),
            ('sjlfskfdl', JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz"]',
             JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "method": 1, "params": "bar"}',
             JsonRpc20Error.INVALID_REQUEST),
            ('{"jsonrpc": "2.0", "method": "a_method", "params": "bar"}',
             JsonRpc20Error.INVALID_REQUEST),
        ]

        for request_str, error_code in requests:
            try:
                logging.info("request str: %s", request_str)
                deserialize_request(request_str)
                self.assertTrue(False)
            except JsonRpc20Error as err:
                logging.info("err: %s", str(err))
                self.assertTrue(err.code == error_code)

        # Negative validate test
        requests = [
            # Mismatch version
            ('{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
             '{"version": "1.1", "result": 19, "id": 3}', JsonRpc20Error.INVALID_PARAMS),

            # Mismatch id
            ('{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
             '{"jsonrpc": "2.0", "result": 19, "id": 4}', JsonRpc20Error.INVALID_PARAMS),
            # Mismatch id type
            ('{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}',
             '{"jsonrpc": "2.0", "result": 19, "id": "3"}', JsonRpc20Error.INVALID_PARAMS),

            # Notification should have no response
            ('{"jsonrpc": "2.0", "method": "subtract"}',
             '{"jsonrpc": "2.0", "result": 0}',
             JsonRpc20Error.INVALID_PARAMS),
        ]
        for request_str, response_str, error_code in requests:
            request = deserialize_request(request_str)
            if response_str:
                try:
                    response = deserialize_response(response_str)
                except JsonRpc20Error as err:
                    self.assertTrue(err.code == error_code)
                    continue

                try:
                    request.validate_response(response)
                    self.assertTrue(False)
                except JsonRpc20Error as err:
                    logging.info("err: %s", str(err))
                    self.assertTrue(err.code == error_code)


    def test_json_rpc_response_positive(self):
        err_responses = [
            # message / data is optional
            ('{"jsonrpc": "2.0", "error": {"code": -32600}, "id": null}',
             JsonRpc20Error.INVALID_REQUEST),
            # data is primitive / structured
            ('{"jsonrpc": "2.0", "error": {"code": -32600, "data": "somedata"}, "id": null}',
             JsonRpc20Error.INVALID_REQUEST),
            ('{"jsonrpc": "2.0", "error": {"code": -32600, "data": {"key": "somedata"}}, "id": null}',
             JsonRpc20Error.INVALID_REQUEST),

            ('{"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request."}, "id": null}',
             JsonRpc20Error.INVALID_REQUEST),
            ('{"jsonrpc": "2.0", "error": {"code": -32700, "message": "Parse error."}, "id": null}',
             JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found."}, "id": "1"}',
             JsonRpc20Error.METHOD_NOT_FOUND),
            ('{"jsonrpc": "2.0", "error": {"code": -32602, "message": "Invalid params."}, "id": "1"}',
             JsonRpc20Error.INVALID_PARAMS),
            ('{"jsonrpc": "2.0", "error": {"code": -32603, "message": "Internal error."}, "id": 1}',
             JsonRpc20Error.INTERNAL_ERROR),
        ]
        for response_str, error_code in err_responses:
            response = deserialize_response(response_str)
            self.assertTrue(response.error.code == error_code)
            response.serialize()


    def test_json_rpc_response_negative(self):
        responses = [
            ('', JsonRpc20Error.PARSE_ERROR),
            ('sjlfskfdl', JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "result": "foobar, "error": "bar"}',
             JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "result": "foobar, "error": "bar", "id": null}',
             JsonRpc20Error.PARSE_ERROR),
            ('{"jsonrpc": "2.0", "result": "foobar, "error": {"code": -32603}, "id": null}',
             JsonRpc20Error.PARSE_ERROR),
            ('{"result": 19, "id": 3}', JsonRpc20Error.INVALID_PARAMS),
        ]
        for response_str, error_code in responses:
            try:
                logging.info("response str: %s", response_str)
                deserialize_response(response_str)
                self.assertTrue(False)
            except JsonRpc20Error as err:
                logging.info("err: %s", str(err))
                self.assertTrue(err.code == error_code)

    def test_json_error_factory(self):
        exceptions = [
            (vapi_jsonrpc_error_parse_error, "testing",
             JsonRpc20Error.PARSE_ERROR),
            (vapi_jsonrpc_error_invalid_request, 3,
             JsonRpc20Error.INVALID_REQUEST),
            (vapi_jsonrpc_error_method_not_found, {"a_dict" : 3},
             JsonRpc20Error.METHOD_NOT_FOUND),
            (vapi_jsonrpc_error_invalid_params, None,
             JsonRpc20Error.INVALID_PARAMS),
            (vapi_jsonrpc_error_internal_error, 3.14159,
             JsonRpc20Error.INTERNAL_ERROR),
            (vapi_jsonrpc_error_transport_error, "blah",
             JsonRpc20Error.TRANSPORT_ERROR),
        ]

        for exception_factory, data, error_code in exceptions:
            error = exception_factory(data=data)
            self.assertTrue(error.code == error_code)

    def get_loopback_connector(self, provider):
        protocol_handler = get_protocol_handler(provider)
        rpc_provider = LocalRpcProvider(protocol_handler)
        return get_protocol_connector(rpc_provider)

    def test_json_loopback_positive(self):
        connector = self.get_loopback_connector(self.provider)
        remote = connector.get_api_provider()

        for method_def in [null_method_def, echo_method_def]:
            # invoke_method
            ctx = ExecutionContext()
            params = build_adhoc_data_value(method_def.get_input_definition())
            method_id = echo_method_def.get_identifier().get_name()
            remote_result = remote.invoke(fake_iface_id,
                                          method_id,
                                          params,
                                          ctx)

            local_result = self.provider.invoke(fake_iface_id, method_id, params, ctx)
            if remote_result.success():
                # Validate result output
                method_def.get_output_definition().validate(remote_result.output)
                # Validate direct call
                self.assertEqual(remote_result.output, local_result.output)
            else:
                self.assertTrue(remote_result.error, local_result.error)

    def test_json_loopback_negative(self):
        connector = self.get_loopback_connector(self.provider)
        remote = connector.get_api_provider()
        # Bogus interface / method
        ctx = connector.new_context()
        params = VoidValue()
        result = remote.invoke('bogus.interface', 'bogus', params, ctx)
        self.assertFalse(result.success())
        self.assertTrue(result.error == self.provider.invoke('bogus.interface', 'bogus',
                                                             params, ctx).error)
        logging.error("error: %s", str(result.error))


    # test_json_handle_request_positive should be covered by test_json_loopback_positive
    def test_json_handle_request_negative(self):
        protocol_handler = get_protocol_handler(self.provider)
        rpc_provider = LocalRpcProvider(protocol_handler)
        rpc_provider.connect()

        id_ = 12
        requests = [
            (vapi_jsonrpc_request_factory(method="bogus", params=None, id=id_),
             JsonRpc20Error.METHOD_NOT_FOUND),
            (vapi_jsonrpc_request_factory(method=VAPI_INVOKE,
                                          params={"bogus": 12}, id=id_),
             JsonRpc20Error.INVALID_PARAMS),
        ]

        for request, error_code in requests:
            http_response = rpc_provider.do_request(
                HTTPRequest(method=HTTPMethod.POST, body=request.serialize()))
            response = deserialize_response(http_response.body)
            request.validate_response(response)
            error = response.error
            logging.info("error: %s", error)
            self.assertTrue(error)
            self.assertTrue(error.code == error_code)

    def test_decimal_json_request(self):
        ctx = ExecutionContext()
        template_request = (
            '{"params":{"input":%s,"serviceId":"mock","ctx":{"appCtx":{}},' +
            '"operationId":"mock"},"jsonrpc":' +
            '"2.0","method":"invoke","id":1}'
        )
        template_response = (
            '{"jsonrpc":"2.0","id":1,"result":{"output": %s}}'
        )
        for val, canonical_val in [
                    ('-12.34e4', '-1.234E5'),
                    ('1E-130', '1.0E-130'),
                    ('0.0E-0', '0.0E0'),
                    ('1.2', '1.2E0'),
                    ('1111111.1111100021e-30', '1.1111111111100021E-24'),
                    ('12312423.0', '1.2312423E7'),
                    ('0.000234E-10', '2.34E-14'),
                    ('17', '1.7E1')]:
            decimal_val = decimal.Decimal(val)
            canonical_decimal_val = canonicalize_double(decimal_val)
            data_value = DoubleValue(decimal_val)
            params = {
                'ctx': ctx,
                'serviceId': 'mock',
                'operationId': 'mock',
                'input': data_value
            }
            actual_request = vapi_jsonrpc_request_factory(
                method=VAPI_INVOKE, params=params, id=1).serialize()
            expected_request = template_request % canonical_decimal_val
            self.assertEqual(
                json.loads(actual_request, parse_float=decimal.Decimal),
                json.loads(expected_request, parse_float=decimal.Decimal))
            response_msg = template_response % canonical_val
            response = deserialize_response(response_msg)
            method_result = JsonRpcDictToVapi.method_result(response.result)
            self.assertTrue(method_result.success())
            self.assertTrue(isinstance(method_result.output, DoubleValue))
            self.assertEqual(method_result.output,
                             DoubleValue(decimal.Decimal(canonical_val)))
コード例 #9
0
class TestApiInterfaceSkeleton(unittest.TestCase):

    def setUp(self):
        self.provider = LocalProvider()
        self.provider.add_interface(MockImpl())
        connector = LocalConnector(self.provider)
        stub_config = StubConfigurationFactory.new_std_configuration(connector)
        self.service = Service(stub_config)
        self.operation = Operation(stub_config)

    def test_services(self):
        expected_services = sorted([
            'com.vmware.vapi.std.introspection.service',
            'com.vmware.vapi.std.introspection.provider',
            'mock_interface',
            'com.vmware.vapi.std.introspection.operation'
        ])
        actual_services = sorted(self.service.list())
        self.assertEqual(actual_services, expected_services)

    def test_service_info(self):
        info = self.service.get(id='mock_interface')
        self.assertEqual(info.operations, set([method_name,
                                               task_method_name,
                                               '%s$task' % task_method_name,
                                               application_context_method_name]))

    def test_operation_info(self):
        actual_info = self.operation.get(service_id=interface_name,
                                         operation_id=method_name)
        input_def = Operation.DataDefinition(
            type=Operation.DataDefinition.DataType.STRUCTURE,
            name=OPERATION_INPUT,
            fields={
                'message': Operation.DataDefinition(
                    type=Operation.DataDefinition.DataType.STRING
                ),
                'throw': Operation.DataDefinition(
                    type=Operation.DataDefinition.DataType.BOOLEAN
                )
            }
        )
        output_def = Operation.DataDefinition(
            type=Operation.DataDefinition.DataType.STRING)
        error_defs = [
            make_introspection_error_def('com.vmware.vapi.std.errors.not_found'),
            make_introspection_error_def('com.vmware.vapi.std.errors.unexpected_input'),
            make_introspection_error_def('com.vmware.vapi.std.errors.internal_server_error'),
            make_introspection_error_def('com.vmware.vapi.std.errors.invalid_argument'),
            make_introspection_error_def('com.vmware.vapi.std.errors.operation_not_found'),
        ]
        expected_info = Operation.Info(input_definition=input_def,
                                       output_definition=output_def,
                                       error_definitions=error_defs)
        self.assertEqual(actual_info.input_definition,
                         expected_info.input_definition)
        self.assertEqual(actual_info.output_definition,
                         expected_info.output_definition)
        actual_errors = [error.name for error in actual_info.error_definitions]
        expected_errors = [error.name for error in expected_info.error_definitions]
        self.assertEqual(sorted(actual_errors), sorted(expected_errors))

    def test_invoke(self):
        ctx = ExecutionContext()
        input_ = StructValue(method_name)
        input_.set_field('message', StringValue('hello'))
        input_.set_field('throw', BooleanValue(False))
        actual_method_result = self.provider.invoke(interface_name,
                                                    method_name,
                                                    input_,
                                                    ctx)
        expected_method_result = MethodResult(output=StringValue('hello'))
        self.assertEqual(actual_method_result.output,
                         expected_method_result.output)
        self.assertEqual(actual_method_result.error,
                         expected_method_result.error)

    def test_invoke_long_running(self):
        ctx = ExecutionContext()
        input_ = StructValue(method_name)
        input_.set_field('message', StringValue('hello'))
        input_.set_field('throw', BooleanValue(False))
        actual_method_result = self.provider.invoke(interface_name,
                                                    '%s$task' % task_method_name,
                                                    input_,
                                                    ctx)
        expected_method_result = MethodResult(output=StringValue('hello'))
        try:
            id_split = actual_method_result.output.value.split(':')
            uuid.UUID(id_split[0], version=4)
            uuid.UUID(id_split[1], version=4)
        except ValueError:
            # There's no assertNotRaises so explicitly fail assert
            # in case a ValueError is thrown for invalid uuid.
            self.assertTrue(False)
        self.assertEqual(actual_method_result.error,
                         expected_method_result.error)

    def test_invoke_long_running_sync(self):
        ctx = ExecutionContext()
        input_ = StructValue(method_name)
        input_.set_field('message', StringValue('hello'))
        input_.set_field('throw', BooleanValue(False))
        actual_method_result = self.provider.invoke(interface_name,
                                                    task_method_name,
                                                    input_,
                                                    ctx)
        expected_method_result = MethodResult(output=StringValue('hello'))
        self.assertEqual(actual_method_result.output,
                         expected_method_result.output)
        self.assertEqual(actual_method_result.error,
                         expected_method_result.error)

    def test_invoke_invalid_arg(self):
        ctx = ExecutionContext()
        input_ = StructValue(method_name)
        input_.set_field('message', IntegerValue(10))
        input_.set_field('throw', BooleanValue(False))
        actual_method_result = self.provider.invoke(interface_name,
                                                    method_name,
                                                    input_,
                                                    ctx)
        self.assertFalse(actual_method_result.success())

    def test_invoke_error(self):
        ctx = ExecutionContext()
        input_ = StructValue(method_name)
        input_.set_field('message', IntegerValue(10))
        input_.set_field('throw', BooleanValue(True))
        actual_method_result = self.provider.invoke(interface_name,
                                                    method_name,
                                                    input_,
                                                    ctx)
        self.assertFalse(actual_method_result.success())

    def test_check_for_unknown_fields(self):
        struct_type = StructType(
            'test',
            {
                'name': StringType()
            }
        )
        struct_value = StructValue(
            name='test',
            values={
                'name': StringValue('hello')
            }
        )
        self.assertIsNone(
            ApiInterfaceSkeleton.check_for_unknown_fields(
                struct_type, struct_value))

    def test_check_for_unknown_fields_2(self):
        optional_struct_type = OptionalType(StructType(
            'test',
            {
                'name': StringType()
            }
        ))
        optional_struct_value = OptionalValue(StructValue(
            name='test',
            values={
                'name': StringValue('hello')
            }
        ))
        self.assertIsNone(
            ApiInterfaceSkeleton.check_for_unknown_fields(
                optional_struct_type,
                optional_struct_value))

    def test_check_for_unknown_fields_invalid_1(self):
        struct_type = StructType(
            'test',
            {
                'name': StringType()
            }
        )
        struct_value = StructValue(
            name='test',
            values={
                'name': StringValue('hello'),
                'address': StringValue('hello')
            }
        )
        self.assertIsNotNone(
            ApiInterfaceSkeleton.check_for_unknown_fields(
                struct_type, struct_value))

    def test_check_for_unknown_fields_invalid_2(self):
        info_type = StructType(
            'info',
            {
                'basic': StructType(
                    'basic',
                    {
                        'name': StringType()
                    }
                ),
                'address': StructType(
                    'address',
                    {
                        'city': StringType()
                    }
                ),
            }
        )
        info_value = StructValue(
            name='info',
            values={
                'basic': StructValue(
                    name='basic',
                    values={
                        'name': 'foo',
                        'extra': 'bar' # extra field
                    }
                ),
                'address': StructValue(
                    name='address',
                    values={
                        'city': 'foo'
                    }
                )
            }
        )
        self.assertIsNotNone(
            ApiInterfaceSkeleton.check_for_unknown_fields(
                info_type, info_value))

    def test_check_for_unknown_fields_invalid_3(self):
        list_info_type = ListType(StructType(
            'info',
            {
                'basic': StructType(
                    'basic',
                    {
                        'name': StringType()
                    }
                ),
                'address': StructType(
                    'address',
                    {
                        'city': StringType()
                    }
                ),
            }
        ))
        list_info_value = [
            StructValue(
                name='info',
                values={
                    'basic': StructValue(
                        name='basic',
                        values={
                            'name': 'foo',
                        }
                    ),
                    'address': StructValue(
                        name='address',
                        values={
                            'city': 'foo'
                        }
                    )
                }
            ),
            StructValue(
                name='info',
                values={
                    'basic': StructValue(
                        name='basic',
                        values={
                            'name': 'foo',
                            'extra': 'bar' # extra field in 2nd element of the list
                        }
                    ),
                    'address': StructValue(
                        name='address',
                        values={
                            'city': 'foo'
                        }
                    )
                }
            )
        ]
        self.assertIsNotNone(
            ApiInterfaceSkeleton.check_for_unknown_fields(
                list_info_type, list_info_value))

    def _run_method_in_thread(self, results, index, api_provider, *args):
        results[index] = api_provider.invoke(*args)

    def test_check_application_context(self):
        # Invoke an operation that checks for application context in 10 threads
        input_ = StructValue(application_context_method_name)
        num_threads = 10
        results = [None] * num_threads
        threads = [None] * num_threads
        for i in range(num_threads):
            threads[i] = threading.Thread(
                target=self._run_method_in_thread,
                args=(
                    results, i, self.provider, interface_name,
                    application_context_method_name, input_,
                    ExecutionContext(application_context=ApplicationContext(
                        {
                            'thread_no': str(i)
                        })),))
            threads[i].start()
        for i in range(num_threads):
            threads[i].join()
            method_result = results[i]
            self.assertTrue(method_result.success())
            self.assertTrue(method_result.output.value, str(i))
コード例 #10
0
    def register_by_properties(self, provider_cfg):
        """
        Register a provider using a provider_cfg dictionary

        :type  provider_cfg: :class:`dict`
        :param provider_cfg: Properties dictionary
        """
        self._name = provider_cfg.get_provider_name()
        if not self._name:
            self._name = 'ApiAggregator'

        #
        # We have three providers here:
        #   Aggregator: To aggregate services from local and remote providers
        #   IntrospectionProvider: To serve introspection requests. This has
        #       all the introspection services but it will decide whether to
        #       route the introspection call to LocalProvider or Remote provider
        #       based on where it is located.
        #   LocalProvider: To serve requests for services specified in
        #       'local.interfaces'. This also has introspection services that
        #       only provides introspection for services in this LocalProvider.
        #
        # For non-introspection calls:
        # - If service is in LocalProvider, flow is Aggregator -> LocalProvider
        # - If service is in remote ApiProvider, flow is Aggregator -> Remote
        #        api provider
        #
        # For introspection calls:
        # - For a service in remote ApiProvider, flow is
        # Aggregator -> Introspection services in IntrospectionProvider
        # - For a service in LocalProvider, flow is
        # Aggregator -> Introspection services in IntrospectionProvider
        # - For a service in introspection set of services, flow is
        # Aggregator -> IntrospectionProvider -> Introspection services in
        # LocalProvider (If it is handled by IntrospectionProvider, then we
        # will go into infinite recursive calls)
        #

        # Retrieve the local provider singleton instance to hold all the
        # services present in 'local.interfaces' property of in the properties
        # file. Even if there are no interfaces in local.interfaces, this is
        # required as it would serve introspection requests for introspection
        # api.
        l_provider = local_provider.get_provider()
        self._introspector = AggregatorIntrospector(self._name, l_provider)
        l_provider.register_by_properties(provider_cfg)

        # Create a local provider to hold the introspection services that
        # aggregates introspection information from the local provider and
        # all the remote providers.
        introspection_provider = LocalProvider(load_introspection=False)
        for service in self._introspector.get_introspection_services():
            # Register the introspection service with the local provider
            introspection_provider.add_interface(service)
            # Register the introspection service with this aggregator
            self.register_service(service.get_identifier().get_name(),
                                  introspection_provider)

        # Registering services from local provider
        service_ids = self.get_service_identifiers(l_provider)
        self._local_service_ids = service_ids
        for service_id in service_ids:
            if service_id not in self._introspection_service_names:
                self.register_service(service_id, l_provider)

        # Register the children
        for child in provider_cfg.get_child_providers():
            self._process_child(provider_cfg, child)
コード例 #11
0
 def setUp(self):
     self.filter = Filter1(next_provider=Filter2(
         next_provider=LocalProvider()))