Esempio n. 1
0
        def wrapped_send_request(client, service_name, actions, *args,
                                 **kwargs):
            assert isinstance(
                service_name, six.text_type
            ), 'Called service name "{}" must be unicode'.format(
                service_name, )

            actions_to_send_to_mock = OrderedDict()
            actions_to_send_to_wrapped_client = []
            for i, action_request in enumerate(actions):
                action_name = getattr(action_request, 'action',
                                      None) or action_request['action']
                assert isinstance(
                    action_name, six.text_type
                ), 'Called action name "{}" must be unicode'.format(
                    action_name, )

                if service_name == self.service and action_name == self.action:
                    # If the service AND action name match, we should send the request to our mocked client
                    if not isinstance(action_request, ActionRequest):
                        action_request = ActionRequest(**action_request)
                    actions_to_send_to_mock[i] = action_request
                else:
                    # If the service OR action name DO NOT match, we should delegate the request to the wrapped client
                    actions_to_send_to_wrapped_client.append(action_request)

            request_id = _global_stub_action_request_counter.get_next()

            continue_on_error = kwargs.get('continue_on_error', False)

            if actions_to_send_to_wrapped_client:
                # If any un-stubbed actions need to be sent to the original client, send them
                self._services_with_calls_sent_to_wrapped_client.add(
                    service_name)
                unwrapped_request_id = self._wrapped_client_send_request(
                    client, service_name, actions_to_send_to_wrapped_client,
                    *args, **kwargs)
                if not actions_to_send_to_mock:
                    # If there are no stubbed actions to mock, just return the un-stubbed request ID
                    return unwrapped_request_id

                self._stub_action_responses_to_merge[service_name][
                    unwrapped_request_id] = (
                        request_id,
                        continue_on_error,
                    )

            ordered_actions_for_merging = OrderedDict()
            job_response_transport_exception = None
            job_response = JobResponse()
            for i, action_request in actions_to_send_to_mock.items():
                mock_response = None
                try:
                    mock_response = mock_action(action_request.body or {})
                    if isinstance(mock_response, JobResponse):
                        job_response.errors.extend(mock_response.errors)
                        if mock_response.actions:
                            mock_response = mock_response.actions[0]
                    elif isinstance(mock_response, dict):
                        mock_response = ActionResponse(self.action,
                                                       body=mock_response)
                    elif not isinstance(mock_response, ActionResponse):
                        mock_response = ActionResponse(self.action)
                except ActionError as e:
                    mock_response = ActionResponse(self.action,
                                                   errors=e.errors)
                except JobError as e:
                    job_response.errors.extend(e.errors)
                except (MessageReceiveError, MessageReceiveTimeout) as e:
                    job_response_transport_exception = e

                if mock_response:
                    ordered_actions_for_merging[i] = mock_response
                    job_response.actions.append(mock_response)
                    if not continue_on_error and mock_response.errors:
                        break

                if job_response.errors:
                    break

            if actions_to_send_to_wrapped_client:
                # If the responses will have to be merged by get_all_responses, replace the list with the ordered dict
                job_response.actions = ordered_actions_for_merging

            self._stub_action_responses_outstanding[service_name][
                request_id] = (job_response_transport_exception
                               or job_response)
            return request_id
Esempio n. 2
0
        def wrapped(client, service_name, actions, *args, **kwargs):
            assert isinstance(
                service_name, six.text_type
            ), 'Called service name "{}" must be unicode'.format(
                service_name, )

            requests_to_send_to_mock_client = OrderedDict()
            requests_to_send_to_wrapped_client = []
            for i, action_request in enumerate(actions):
                action_name = getattr(action_request, 'action',
                                      None) or action_request['action']
                assert isinstance(
                    action_name, six.text_type
                ), 'Called action name "{}" must be unicode'.format(
                    action_name, )

                if service_name == self.service and action_name == self.action:
                    # If the service AND action name match, we should send the request to our mocked client
                    if not isinstance(action_request, ActionRequest):
                        action_request = ActionRequest(action_request)
                    requests_to_send_to_mock_client[i] = action_request
                else:
                    # If the service OR action name DO NOT match, we should delegate the request to the wrapped client
                    requests_to_send_to_wrapped_client.append(action_request)

            # Hold off on raising action errors until both mock and real responses are merged
            raise_action_errors = kwargs.get('raise_action_errors', True)
            kwargs['raise_action_errors'] = False
            # Run the real and mocked jobs and merge the results, to simulate a single job
            if requests_to_send_to_wrapped_client:
                job_response = self._wrapped_client_call_actions_method(
                    client, service_name, requests_to_send_to_wrapped_client,
                    *args, **kwargs)
            else:
                job_response = JobResponse()
            for i, action_request in requests_to_send_to_mock_client.items():
                try:
                    mock_response = mock_action(action_request.body or {})
                    if isinstance(mock_response, JobResponse):
                        mock_response = mock_response.actions[0]
                    elif isinstance(mock_response, dict):
                        mock_response = ActionResponse(self.action,
                                                       body=mock_response)
                    elif not isinstance(mock_response, ActionResponse):
                        mock_response = ActionResponse(self.action)
                except ActionError as e:
                    mock_response = ActionResponse(self.action,
                                                   errors=e.errors)
                job_response.actions.insert(i, mock_response)
            if kwargs.get('continue_on_error', False) is False:
                # Simulate the server job halting on the first action error
                first_error_index = -1
                for i, action_result in enumerate(job_response.actions):
                    if action_result.errors:
                        first_error_index = i
                        break
                if first_error_index >= 0:
                    job_response.actions = job_response.actions[:
                                                                first_error_index
                                                                + 1]
            if raise_action_errors:
                error_actions = [
                    action for action in job_response.actions if action.errors
                ]
                if error_actions:
                    raise Client.CallActionError(error_actions)

            return job_response