Esempio n. 1
0
    def __init__(self, skill_configuration):
        # type: (SkillConfiguration) -> None
        """Top level container for Request Dispatcher,
        Persistence Adapter and Api Client.

        :param skill_configuration: Configuration object that holds
            information about different components needed to build the
            skill object.
        :type skill_configuration: SkillConfiguration
        """
        self.persistence_adapter = skill_configuration.persistence_adapter
        self.api_client = skill_configuration.api_client
        self.serializer = DefaultSerializer()
        self.skill_id = skill_configuration.skill_id
        self.custom_user_agent = skill_configuration.custom_user_agent
        self.loaders = skill_configuration.loaders
        self.renderer = skill_configuration.renderer

        self.request_dispatcher = GenericRequestDispatcher(
            options=skill_configuration)

        UserAgentManager.register_component(
            user_agent_info(sdk_version=__version__))
        if skill_configuration.custom_user_agent is not None:
            UserAgentManager.register_component(
                component_name=skill_configuration.custom_user_agent)
Esempio n. 2
0
    def __init__(self, skill_configuration):
        # type: (SkillConfiguration) -> None
        """Top level container for Request Dispatcher,
        Persistence Adapter and Api Client.

        :param skill_configuration: Configuration object that holds
            information about different components needed to build the
            skill object.
        :type skill_configuration: SkillConfiguration
        """
        self.persistence_adapter = skill_configuration.persistence_adapter
        self.api_client = skill_configuration.api_client
        self.serializer = DefaultSerializer()
        self.skill_id = skill_configuration.skill_id
        self.custom_user_agent = skill_configuration.custom_user_agent

        self.request_dispatcher = GenericRequestDispatcher(
            options=skill_configuration)
Esempio n. 3
0
    def test_dispatch_process_handled_exception_when_suitable_exception_handler_registered(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = mock.MagicMock(spec=GenericHandlerAdapter)
        test_adapter.supports.return_value = True
        test_adapter.execute.side_effect = DispatchException(
            "Custom dispatch exception")

        test_exception_handler_1 = mock.MagicMock(
            spec=AbstractExceptionHandler)
        test_exception_handler_1.can_handle.return_value = False
        test_exception_handler_2 = mock.MagicMock(
            spec=AbstractExceptionHandler)
        test_exception_handler_2.can_handle.return_value = True
        test_exception_handler_2.handle.return_value = "Custom exception " \
                                                       "handler response"

        options = RuntimeConfiguration(
            request_mappers=[test_request_mapper],
            handler_adapters=[test_adapter],
            exception_mapper=GenericExceptionMapper(exception_handlers=[
                test_exception_handler_1, test_exception_handler_2
            ]))
        self.test_dispatcher = GenericRequestDispatcher(options=options)

        assert self.test_dispatcher.dispatch(
            handler_input=self.valid_handler_input
        ) == "Custom exception handler response", (
            "Dispatcher didn't handle exception when a suitable exception handler is registered"
        )

        test_exception_handler_1.handle.assert_not_called(), (
            "Incorrect Exception Handler called when handling custom "
            "exception")
        test_exception_handler_2.handle.assert_called_once(), (
            "Suitable exception handler didn't handle custom exception")
Esempio n. 4
0
class CustomSkill(AbstractSkill):
    """Top level container for Request Dispatcher,
    Persistence Adapter and Api Client.

    :param skill_configuration: Configuration object that holds
        information about different components needed to build the
        skill object.
    :type skill_configuration: SkillConfiguration
    """
    def __init__(self, skill_configuration):
        # type: (SkillConfiguration) -> None
        """Top level container for Request Dispatcher,
        Persistence Adapter and Api Client.

        :param skill_configuration: Configuration object that holds
            information about different components needed to build the
            skill object.
        :type skill_configuration: SkillConfiguration
        """
        self.persistence_adapter = skill_configuration.persistence_adapter
        self.api_client = skill_configuration.api_client
        self.serializer = DefaultSerializer()
        self.skill_id = skill_configuration.skill_id
        self.custom_user_agent = skill_configuration.custom_user_agent
        self.loaders = skill_configuration.loaders
        self.renderer = skill_configuration.renderer

        self.request_dispatcher = GenericRequestDispatcher(
            options=skill_configuration)

    def supports(self, request_envelope, context):
        # type: (Dict[str, Any], Any) -> bool
        """Check if request envelope is of the expected skill format.

        :param request_envelope: input instance containing request information.
        :type request_envelope: Dict[str, Any]
        :param context: Context passed during invocation
        :type context: Any
        :return: boolean if this type of request can be handled by this
            skill.
        :rtype: bool
        """
        return 'request' in request_envelope

    def invoke(self, request_envelope, context):
        # type: (RequestEnvelope, Any) -> ResponseEnvelope
        """Invokes the dispatcher, to handle the request envelope and
        return a response envelope.

        :param request_envelope: Request Envelope instance containing
            request information
        :type request_envelope: RequestEnvelope
        :param context: Context passed during invocation
        :type context: Any
        :return: Response Envelope generated by handling the request
        :rtype: ResponseEnvelope
        """
        if (self.skill_id is not None
                and request_envelope.context.system.application.application_id
                != self.skill_id):
            raise AskSdkException("Skill ID Verification failed!!")

        if self.api_client is not None:
            api_token = request_envelope.context.system.api_access_token
            api_endpoint = request_envelope.context.system.api_endpoint
            api_configuration = ApiConfiguration(serializer=self.serializer,
                                                 api_client=self.api_client,
                                                 authorization_value=api_token,
                                                 api_endpoint=api_endpoint)
            factory = ServiceClientFactory(api_configuration=api_configuration)
        else:
            factory = None

        template_factory = TemplateFactory(template_loaders=self.loaders,
                                           template_renderer=self.renderer)

        attributes_manager = AttributesManager(
            request_envelope=request_envelope,
            persistence_adapter=self.persistence_adapter)

        handler_input = HandlerInput(request_envelope=request_envelope,
                                     attributes_manager=attributes_manager,
                                     context=context,
                                     service_client_factory=factory,
                                     template_factory=template_factory)

        response = self.request_dispatcher.dispatch(
            handler_input=handler_input)
        session_attributes = None

        if request_envelope.session is not None:
            session_attributes = (
                handler_input.attributes_manager.session_attributes)

        return ResponseEnvelope(response=response,
                                version=RESPONSE_FORMAT_VERSION,
                                session_attributes=session_attributes,
                                user_agent=user_agent_info(
                                    sdk_version=__version__,
                                    custom_user_agent=self.custom_user_agent))
Esempio n. 5
0
 def setUp(self):
     self.valid_handler_input = mock.Mock()
     self.test_dispatcher = GenericRequestDispatcher(
         options=RuntimeConfiguration(request_mappers=None,
                                      handler_adapters=None))
Esempio n. 6
0
class TestRequestDispatcher(unittest.TestCase):
    def setUp(self):
        self.valid_handler_input = mock.Mock()
        self.test_dispatcher = GenericRequestDispatcher(
            options=RuntimeConfiguration(request_mappers=None,
                                         handler_adapters=None))

    def test_handler_input_with_no_chains_in_request_mapper(self):
        with self.assertRaises(DispatchException) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Unable to find a suitable request handler" in str(
            exc.exception
        ), ("Dispatcher didn't throw Dispatch Exception when no chains are "
            "registered in request mappers")

    def test_handler_input_with_unsupported_chains_in_request_mapper(self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = False
        test_request_handler_chain = mock.MagicMock(
            spec=GenericRequestHandlerChain)
        test_request_handler_chain.request_handler = test_request_handler
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        self.test_dispatcher.request_mappers = [test_request_mapper]
        with self.assertRaises(DispatchException) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Unable to find a suitable request handler" in str(
            exc.exception), (
                "Dispatcher didn't throw Dispatch Exception when no suitable "
                "chains are registered in "
                "request mappers")

    def test_handler_input_with_supported_chain_in_mapper_no_adapters(self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler_chain = mock.MagicMock(
            spec=GenericRequestHandlerChain)
        test_request_handler_chain.request_handler = test_request_handler
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        self.test_dispatcher.request_mappers = [test_request_mapper]
        with self.assertRaises(DispatchException) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Unable to find a suitable request adapter" in str(
            exc.exception
        ), ("Dispatcher didn't throw Dispatch Exception when no adapters are "
            "registered in "
            "dispatcher")

    def test_handler_input_with_supported_chain_in_mapper_and_unsupported_adapter(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler_chain = mock.MagicMock(
            spec=GenericRequestHandlerChain)
        test_request_handler_chain.request_handler = test_request_handler
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])
        test_adapter = mock.MagicMock(spec=GenericHandlerAdapter)
        test_adapter.supports.return_value = False

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]
        with self.assertRaises(DispatchException) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Unable to find a suitable request adapter" in str(
            exc.exception), (
                "Dispatcher didn't throw Dispatch Exception when no suitable "
                "adapters are registered in "
                "dispatcher")

    def test_handler_input_successful_execution_with_supported_chain_and_supported_adapter(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]

        assert self.test_dispatcher.dispatch(
            handler_input=self.valid_handler_input) == "Test Response", (
                "Dispatcher dispatch method return invalid response when "
                "supported handler chain and "
                "supported handler adapter are found")

        test_request_handler.handle.assert_called_once_with(
            self.valid_handler_input), (
                "Dispatcher dispatch method called handle on Request Handler "
                "more than once")

    def test_handler_input_successful_local_request_interceptors_execution(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_interceptor_1 = mock.MagicMock(spec=AbstractRequestInterceptor)
        test_interceptor_2 = mock.MagicMock(spec=AbstractRequestInterceptor)

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler,
            request_interceptors=[test_interceptor_1, test_interceptor_2])
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]

        self.test_dispatcher.dispatch(handler_input=self.valid_handler_input)

        test_interceptor_1.process.assert_called_once_with(
            handler_input=self.valid_handler_input), (
                "Dispatcher dispatch method didn't process local request "
                "interceptors before calling request handler "
                "handle")
        test_interceptor_2.process.assert_called_once_with(
            handler_input=self.valid_handler_input), (
                "Dispatcher dispatch method didn't process local request "
                "interceptors before calling request handler "
                "handle")

    def test_handler_input_successful_global_request_interceptors_execution(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_interceptor_1 = mock.MagicMock(spec=AbstractRequestInterceptor)
        test_interceptor_2 = mock.MagicMock(spec=AbstractRequestInterceptor)

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]
        self.test_dispatcher.request_interceptors = [
            test_interceptor_1, test_interceptor_2
        ]

        self.test_dispatcher.dispatch(handler_input=self.valid_handler_input)

        test_interceptor_1.process.assert_called_once_with(
            handler_input=self.valid_handler_input), (
                "Dispatcher dispatch method didn't process global request "
                "interceptors before calling dispatch request")
        test_interceptor_2.process.assert_called_once_with(
            handler_input=self.valid_handler_input), (
                "Dispatcher dispatch method didn't process global request "
                "interceptors before calling dispatch request")

    def test_handler_input_unsuccessful_global_request_interceptors_execution(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_interceptor_1 = mock.MagicMock(
            spec=AbstractRequestInterceptor)
        test_request_interceptor_1.process.side_effect = ValueError(
            "Test exception")
        test_request_interceptor_2 = mock.MagicMock(
            spec=AbstractRequestInterceptor)
        test_response_interceptor_1 = mock.MagicMock(
            spec=AbstractResponseInterceptor)

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]
        self.test_dispatcher.request_interceptors = [
            test_request_interceptor_1, test_request_interceptor_2
        ]
        self.test_dispatcher.response_interceptors = [
            test_response_interceptor_1
        ]

        with self.assertRaises(ValueError) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Test exception" in str(exc.exception), (
            "Dispatcher didn't throw exception raised by global request "
            "interceptor")

        test_request_interceptor_1.process.assert_called_once_with(
            handler_input=self.valid_handler_input), (
                "Dispatcher dispatch method didn't process global request "
                "interceptors before calling dispatch request")
        test_request_interceptor_2.process.assert_not_called(), (
            "Dispatcher dispatch method processed remaining global "
            "request interceptors when one of them threw "
            "exception")
        test_request_handler.assert_not_called(), (
            "Dispatcher dispatch method processed request handler 'handle' "
            "method when one of the global request "
            "interceptors threw exception")
        test_response_interceptor_1.process.assert_not_called(), (
            "Dispatcher dispatch method processed global response "
            "interceptors when one of the global request "
            "interceptors threw exception")

    def test_handler_input_successful_local_response_interceptors_execution(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_response = mock.MagicMock(spec=TestDispatchOutput)
        test_response_before_interceptor = test_response
        test_request_handler.handle.return_value = test_response

        test_interceptor_1 = mock.MagicMock(spec=AbstractResponseInterceptor)
        test_response.interceptor = "Interceptor 1"
        test_response_from_interceptor_1 = test_response
        test_interceptor_1.process.return_value = test_response

        test_interceptor_2 = mock.MagicMock(spec=AbstractResponseInterceptor)
        test_response.interceptor = "Interceptor 2"
        test_response_from_interceptor_2 = test_response
        test_interceptor_2.process.return_value = test_response

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler,
            response_interceptors=[test_interceptor_1, test_interceptor_2])
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]

        assert self.test_dispatcher.dispatch(
            handler_input=self.valid_handler_input
        ) == test_response_from_interceptor_2, (
            "Dispatcher dispatch method returned invalid response after "
            "processing response through "
            "local response interceptors")

        test_interceptor_1.process.assert_called_once_with(
            handler_input=self.valid_handler_input,
            response=test_response_before_interceptor), (
                "Dispatcher dispatch method didn't process local response "
                "interceptors after calling request handler "
                "handle")

        test_interceptor_2.process.assert_called_once_with(
            handler_input=self.valid_handler_input,
            response=test_response_from_interceptor_1), (
                "Dispatcher dispatch method didn't process local response "
                "interceptors after calling request handler "
                "handle")

    def test_handler_input_successful_global_response_interceptors_execution(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_response = mock.MagicMock(spec=TestDispatchOutput)
        test_response_before_interceptor = test_response
        test_request_handler.handle.return_value = test_response

        test_interceptor_1 = mock.MagicMock(spec=AbstractResponseInterceptor)
        test_response.interceptor = "Interceptor 1"
        test_response_from_interceptor_1 = test_response
        test_interceptor_1.process.return_value = test_response

        test_interceptor_2 = mock.MagicMock(spec=AbstractResponseInterceptor)
        test_response.interceptor = "Interceptor 2"
        test_response_from_interceptor_2 = test_response
        test_interceptor_2.process.return_value = test_response

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = GenericHandlerAdapter()

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]
        self.test_dispatcher.response_interceptors = [
            test_interceptor_1, test_interceptor_2
        ]

        assert self.test_dispatcher.dispatch(
            handler_input=self.valid_handler_input
        ) == test_response_from_interceptor_2, (
            "Dispatcher dispatch method returned invalid response after "
            "processing response through "
            "global response interceptors")

        test_interceptor_1.process.assert_called_once_with(
            handler_input=self.valid_handler_input,
            response=test_response_before_interceptor), (
                "Dispatcher dispatch method didn't process global request "
                "interceptors after calling dispatch request")

        test_interceptor_2.process.assert_called_once_with(
            handler_input=self.valid_handler_input,
            response=test_response_from_interceptor_1), (
                "Dispatcher dispatch method didn't process global request "
                "interceptors after calling dispatch request")

    def test_dispatch_raise_low_level_exception_when_exception_handler_not_registered(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = mock.MagicMock(spec=GenericHandlerAdapter)
        test_adapter.supports.return_value = True
        test_adapter.execute.side_effect = Exception(
            "Test low level Exception")

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]

        with self.assertRaises(Exception) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Test low level Exception" in str(exc.exception), (
            "Dispatcher didn't throw low level exception when request "
            "dispatch throws exception and "
            "no exception handler is registered")

    def test_dispatch_raise_low_level_exception_when_no_suitable_exception_handler_registered(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = mock.MagicMock(spec=GenericHandlerAdapter)
        test_adapter.supports.return_value = True
        test_adapter.execute.side_effect = Exception(
            "Test low level Exception")

        test_exception_handler = mock.MagicMock(spec=AbstractExceptionHandler)
        test_exception_handler.can_handle.return_value = False
        test_exception_mapper = GenericExceptionMapper(
            exception_handlers=[test_exception_handler])

        self.test_dispatcher.request_mappers = [test_request_mapper]
        self.test_dispatcher.handler_adapters = [test_adapter]
        self.test_dispatcher.exception_mapper = test_exception_mapper

        with self.assertRaises(Exception) as exc:
            self.test_dispatcher.dispatch(
                handler_input=self.valid_handler_input)

        assert "Test low level Exception" in str(exc.exception), (
            "Dispatcher didn't throw low level exception when request "
            "dispatch throws exception and "
            "no suitable exception handler is registered")

    def test_dispatch_process_handled_exception_when_suitable_exception_handler_registered(
            self):
        test_request_handler = mock.MagicMock(spec=AbstractRequestHandler)
        test_request_handler.can_handle.return_value = True
        test_request_handler.handle.return_value = "Test Response"

        test_request_handler_chain = GenericRequestHandlerChain(
            request_handler=test_request_handler)
        test_request_mapper = GenericRequestMapper(
            request_handler_chains=[test_request_handler_chain])

        test_adapter = mock.MagicMock(spec=GenericHandlerAdapter)
        test_adapter.supports.return_value = True
        test_adapter.execute.side_effect = DispatchException(
            "Custom dispatch exception")

        test_exception_handler_1 = mock.MagicMock(
            spec=AbstractExceptionHandler)
        test_exception_handler_1.can_handle.return_value = False
        test_exception_handler_2 = mock.MagicMock(
            spec=AbstractExceptionHandler)
        test_exception_handler_2.can_handle.return_value = True
        test_exception_handler_2.handle.return_value = "Custom exception " \
                                                       "handler response"

        options = RuntimeConfiguration(
            request_mappers=[test_request_mapper],
            handler_adapters=[test_adapter],
            exception_mapper=GenericExceptionMapper(exception_handlers=[
                test_exception_handler_1, test_exception_handler_2
            ]))
        self.test_dispatcher = GenericRequestDispatcher(options=options)

        assert self.test_dispatcher.dispatch(
            handler_input=self.valid_handler_input
        ) == "Custom exception handler response", (
            "Dispatcher didn't handle exception when a suitable exception handler is registered"
        )

        test_exception_handler_1.handle.assert_not_called(), (
            "Incorrect Exception Handler called when handling custom "
            "exception")
        test_exception_handler_2.handle.assert_called_once(), (
            "Suitable exception handler didn't handle custom exception")