def test_receive_bad_op(self): class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="no_exist") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with( None, { "status_code": 400, "error_message": "Unknown op name: no_exist", "conv-id": "", "conv-seq": 2, "protocol": "", "performative": "failure", "language": "ion-r2", "encoding": "msgpack", "format": "NoneType", "receiver": ",", "ts": sentinel.ts, "reply-by": "todo", }, )
def test__get_sflow_manager_with_container(self): Container.instance = None c = Container() # ensure an instance e = RPCResponseEndpointUnit(interceptors={}) self.assertEquals(e._get_sflow_manager(), c.sflow_manager) Container.instance = None
def test_recv_bad_kwarg(self): # we try to call simple with the kwarg "not_named" instead of the correct one class FakeMsg(object): def __init__(self): self.not_named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with( None, { "status_code": 500, "error_message": "simple() got an unexpected keyword argument 'not_named'", "conv-id": "", "conv-seq": 2, "protocol": "", "performative": "failure", "language": "ion-r2", "encoding": "msgpack", "format": "NoneType", "receiver": ",", "ts": sentinel.ts, "reply-by": "todo", }, )
def test_recv_bad_kwarg(self): # we try to call simple with the kwarg "not_named" instead of the correct one class FakeMsg(object): def __init__(self): self.not_named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) self._do_listen(e) # test to make sure send got called with our error assert_called_once_with_header(self, ch.send, {'status_code':400, 'error_message':'Argument not_named not present in op signature', 'conv-id': sentinel.conv_id, 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'NoneType', 'receiver': ',', 'msg-rcvd':ANY, 'ts': sentinel.ts})
def test_receive_bad_op(self): class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="no_exist") e.attach_channel(ch) self._do_listen(e) assert_called_once_with_header(self, ch.send, {'status_code':400, 'error_message':'Unknown op name: no_exist', 'conv-id': sentinel.conv_id, 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'list', 'receiver': ',', 'msg-rcvd':ANY, 'ts': sentinel.ts})
def test_receive_bad_op(self): class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="no_exist") e.attach_channel(ch) self._do_listen(e) assert_called_once_with_header( self, ch.send, { 'status_code': 400, 'error_message': 'Unknown op name: no_exist', 'conv-id': sentinel.conv_id, 'conv-seq': 2, 'protocol': '', 'performative': 'failure', 'language': 'ion-r2', 'encoding': 'msgpack', 'format': 'list', 'receiver': ',', 'msg-rcvd': ANY, 'ts': sentinel.ts })
def test_recv_bad_kwarg(self): # we try to call simple with the kwarg "not_named" instead of the correct one class FakeMsg(object): def __init__(self): self.not_named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with(None, {'status_code':500, 'error_message':'simple() got an unexpected keyword argument \'not_named\'', 'conv-id': '', 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'NoneType', 'receiver': ',', 'reply-by': 'todo'})
def test_receive_bad_op(self): class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="no_exist") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with(None, {'status_code':400, 'error_message':'Unknown op name: no_exist', 'conv-id': '', 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'NoneType', 'receiver': ',', 'reply-by': 'todo'})
def test_recv_bad_kwarg(self): # we try to call simple with the kwarg "not_named" instead of the correct one class FakeMsg(object): def __init__(self): self.not_named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) self._do_listen(e) # test to make sure send got called with our error assert_called_once_with_header( self, ch.send, { 'status_code': 400, 'error_message': 'Argument not_named not present in op signature', 'conv-id': sentinel.conv_id, 'conv-seq': 2, 'protocol': '', 'performative': 'failure', 'language': 'ion-r2', 'encoding': 'msgpack', 'format': 'NoneType', 'receiver': ',', 'msg-rcvd': ANY, 'ts': sentinel.ts })
def test__build_sample(self): e = RPCResponseEndpointUnit(interceptors={}) heads = { 'conv-id': sentinel.conv_id, 'ts': '1', 'op': 'remove_femur', 'sender': 'sender', 'receiver': 'getter' } resp_heads = {'sender-service': 'theservice'} samp = e._build_sample(sentinel.name, 200, "Ok", "msg", heads, "response", resp_heads, sentinel.qlen) self.assertEquals( samp, { 'app_name': get_sys_name(), 'op': 'remove_femur', 'attrs': { 'ql': sentinel.qlen, 'pid': sentinel.name }, 'status_descr': "Ok", 'status': '0', 'req_bytes': len('msg'), 'resp_bytes': len('response'), 'uS': 999000, # it's in microseconds! 'initiator': 'sender', 'target': 'theservice' })
def test__message_received_error_in_op(self): # we want to make sure IonExceptions raised in business logic get a response, now that # _message_received sends the responses class FakeMsg(object): pass cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="error_op") e.attach_channel(ch) e.send = Mock() self._do_listen(e) assert_called_once_with_header( self, e.send, { 'status_code': 401, 'error_message': str(sentinel.unauth), 'conv-id': sentinel.conv_id, 'msg-rcvd': ANY, 'conv-seq': 2, 'protocol': '', 'performative': 'failure' })
def test_message_received_dict(self): rout_obj = Mock() e = RPCResponseEndpointUnit(routing_obj=rout_obj) msg_dict = {"iam": "adict"} e.message_received(msg_dict, {"op": "anyop"}) rout_obj.anyop.assert_called_once_with(iam="adict")
def test_message_received_dict(self): rout_obj = Mock() e = RPCResponseEndpointUnit(routing_obj=rout_obj) msg_dict = {'iam': 'adict'} e.message_received(msg_dict, {'op': 'anyop'}) rout_obj.anyop.assert_called_once_with(iam='adict')
def test_message_received_dict(self): rout_obj = Mock() e = RPCResponseEndpointUnit(routing_obj=rout_obj) msg_dict = {'iam':'adict'} e.message_received(msg_dict, {'op':'anyop'}) rout_obj.anyop.assert_called_once_with(iam='adict')
def test__sample_request_exception(self, mocklog): e = RPCResponseEndpointUnit(interceptors={}) e._get_sflow_manager = Mock(return_value=Mock(spec=SFlowManager)) e._get_sflow_manager.return_value.should_sample = True e._build_sample = Mock(side_effect=TestError) e._sample_request(sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers) mocklog.exception.assert_called_once_with("Could not sample, ignoring")
def test_timeout_makes_sflow_sample(self): e = RPCResponseEndpointUnit(interceptors={}) e._sample_request = Mock() self.assertRaises(exception.Timeout, e._send, sentinel.msg, sentinel.headers, timeout=1) e._sample_request.assert_called_once_with(-1, 'Timeout', sentinel.msg, sentinel.headers, '', {})
def test__sample_request_no_sample(self, mocklog): e = RPCResponseEndpointUnit(interceptors={}) e._get_sflow_manager = Mock(return_value=Mock(spec=SFlowManager)) e._get_sflow_manager.return_value.should_sample = False e._get_sample_name = Mock() e._sample_request(sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers) self.assertEquals(mocklog.debug.call_count, 1) self.assertIn("not to sample", mocklog.debug.call_args[0][0])
def test__message_received_interceptor_exception(self): e = RPCResponseEndpointUnit(routing_obj=self) e.send = Mock() e.send.return_value = sentinel.sent with patch('pyon.net.endpoint.ResponseEndpointUnit._message_received', new=Mock(side_effect=exception.IonException)): retval = e._message_received(sentinel.msg, {}) self.assertEquals(retval, sentinel.sent) e.send.assert_called_once_with(None, {'status_code': -1, 'error_message':'', 'conv-id': '', 'conv-seq': 2, 'protocol':''})
def test__message_received_interceptor_exception(self): e = RPCResponseEndpointUnit(routing_obj=self) e.send = Mock() e.send.return_value = sentinel.sent with patch('pyon.net.endpoint.ResponseEndpointUnit._message_received', new=Mock(side_effect=exception.IonException)): retval = e._message_received(sentinel.msg, {}) self.assertEquals(retval, sentinel.sent) e.send.assert_called_once_with(None, {'status_code': -1, 'error_message':'', 'conv-id': '', 'conv-seq': 2, 'protocol':'', 'performative': 'failure'})
def _make_routing_call(self, call, timeout, *op_args, **op_kwargs): if not self._routing_call: return RPCResponseEndpointUnit._make_routing_call( self, call, timeout, *op_args, **op_kwargs) ctx = self._process.get_context( ) # pull onto the locals here, for debuggability with manhole ar = self._routing_call(call, ctx, *op_args, **op_kwargs) res = ar.get() # REMOVED TIMEOUT #try: # res = ar.get(timeout=timeout) #except Timeout: # # # cancel or abort current processing # self._process._process.cancel_or_abort_call(ar) # # raise IonTimeout("Process did not execute in allotted time") # will be returned to caller via messaging # Persistent process state handling if hasattr(self._process, "_proc_state"): if self._process._proc_state_changed: log.debug("Process %s state changed. State=%s", self._process.id, self._process._proc_state) self._process.container.state_repository.put_state( self._process.id, self._process._proc_state) self._process._proc_state_changed = False return res
def _make_routing_call(self, call, *op_args, **op_kwargs): if not self._routing_call: return RPCResponseEndpointUnit._make_routing_call( self, call, *op_args, **op_kwargs) ar = self._routing_call(call, self._process.get_context(), *op_args, **op_kwargs) return ar.get() # @TODO: timeout?
def test_endpoint_receive(self): self._ar = event.AsyncResult() # build a command object to be returned by the mocked channel class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) self._do_listen(e) args = self._ar.get(timeout=10) self.assertEquals(args, ["ein", "zwei"])
def test__message_received_error_in_op(self): # we want to make sure IonExceptions raised in business logic get a response, now that # _message_received sends the responses class FakeMsg(object): pass cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="error_op") e.attach_channel(ch) e.send = Mock() e.spawn_listener() e._recv_greenlet.join() e.send.assert_called_once_with( None, { 'status_code': 401, 'error_message': str(sentinel.unauth), 'conv-id': '', 'conv-seq': 2, 'protocol': '', 'performative': 'failure' })
def _build_header(self, raw_msg, raw_headers): """ Override to direct the calls in _build_header - first the RPCResponse side, then the Process mixin. """ header1 = RPCResponseEndpointUnit._build_header(self, raw_msg, raw_headers) header2 = ProcessEndpointUnitMixin._build_header(self, raw_msg, raw_headers) header1.update(header2) return header1
def test__message_received_interceptor_exception(self): e = RPCResponseEndpointUnit(routing_obj=self) e.send = Mock() e.send.return_value = sentinel.sent with patch( "pyon.net.endpoint.ResponseEndpointUnit._message_received", new=Mock(side_effect=exception.IonException) ): retval = e._message_received(sentinel.msg, {}) self.assertEquals(retval, sentinel.sent) e.send.assert_called_once_with( None, { "status_code": -1, "error_message": "", "conv-id": "", "conv-seq": 2, "protocol": "", "performative": "failure", }, )
def test_receive_bad_op(self): class FakeMsg(object): def __init__(self): self.named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="no_exist") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with(None, {'status_code':400, 'error_message':'Unknown op name: no_exist', 'conv-id': '', 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'NoneType', 'receiver': ',', 'ts': sentinel.ts, 'reply-by': 'todo'})
def test__message_received_error_in_op(self): # we want to make sure IonExceptions raised in business logic get a response, now that # _message_received sends the responses class FakeMsg(object): pass cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="error_op") e.attach_channel(ch) e.send = Mock() e.spawn_listener() e._recv_greenlet.join() e.send.assert_called_once_with( None, { "status_code": 401, "error_message": str(sentinel.unauth), "conv-id": "", "conv-seq": 2, "protocol": "", "performative": "failure", }, )
def test_recv_bad_kwarg(self): # we try to call simple with the kwarg "not_named" instead of the correct one class FakeMsg(object): def __init__(self): self.not_named = ["ein", "zwei"] cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self) ch = self._setup_mock_channel(value=cvalue, op="simple") e.attach_channel(ch) e.spawn_listener() e._recv_greenlet.join() # test to make sure send got called with our error ch.send.assert_called_once_with(None, {'status_code':500, 'error_message':'simple() got an unexpected keyword argument \'not_named\'', 'conv-id': '', 'conv-seq': 2, 'protocol':'', 'performative': 'failure', 'language':'ion-r2', 'encoding':'msgpack', 'format':'NoneType', 'receiver': ',', 'ts': sentinel.ts, 'reply-by': 'todo'})
def test__message_received_error_in_op(self): # we want to make sure IonExceptions raised in business logic get a response, now that # _message_received sends the responses class FakeMsg(object): pass cvalue = FakeMsg() e = RPCResponseEndpointUnit(routing_obj=self, interceptors={}) ch = self._setup_mock_channel(value=cvalue, op="error_op") e.attach_channel(ch) e.send = Mock() self._do_listen(e) assert_called_once_with_header(self, e.send, {'status_code': 401, 'error_message': str(sentinel.unauth), 'conv-id': sentinel.conv_id, 'conv-seq': 2, 'protocol':'', 'performative':'failure'})
def test__build_sample(self): e = RPCResponseEndpointUnit(interceptors={}) heads = {'conv-id': sentinel.conv_id, 'ts': '1', 'op': 'remove_femur', 'sender': 'sender', 'receiver': 'getter'} resp_heads = {'sender-service': 'theservice'} samp = e._build_sample("app_name", 200, "Ok", "msg", heads, "response", resp_heads, sentinel.qlen) self.assertEquals(samp, { 'app_name' : "app_name", 'op' : 'remove_femur', 'attrs' : {'ql':sentinel.qlen}, 'status_descr' : "Ok", 'status' : '0', 'req_bytes' : len('msg'), 'resp_bytes': len('response'), 'uS' : 999000, # it's in microseconds! 'initiator' : 'sender', 'target' : 'theservice' })
def message_received(self, msg, headers): """Hook for checking governance pre-conditions before calling a service operation """ gc = self._routing_obj.container.governance_controller if gc: gc.check_process_operation_preconditions(self._routing_obj, msg, headers) result, response_headers = RPCResponseEndpointUnit.message_received(self, msg, headers) # decorate our response_headers with process-saturation, as we need them to be set in the headers # earlier than send/build_header so the sampling takes notice try: response_headers['process-saturation'] = self._get_process_saturation() except Exception as ex: log.warn("Could not set process-saturation header, ignoring: %s", ex) return result, response_headers
def _message_received(self, msg, headers): """ Message received override. Sets the process' context here to be picked up by subsequent calls out by this service to other services, or replies. """ ###### ###### THIS IS WHERE THE THREAD LOCAL HEADERS CONTEXT IS SET ###### ###### # With the property _routing_call set, as is the case 95% of the time in the Process-level endpoints, # we have to set the call context from the ION process' calling greenlet, as context is greenlet-specific. # This is done in the _make_routing_call override here, passing it the context to be set. # See also IonProcessThread._control_flow. with self._process.push_context(headers): return RPCResponseEndpointUnit._message_received(self, msg, headers)
def message_received(self, msg, headers): #This is the hook for checking governance pre-conditions before calling a service operation #TODO - replace with a process specific interceptor stack of some sort. gc = self._routing_obj.container.governance_controller if gc: gc.check_process_operation_preconditions(self._routing_obj, msg, headers) result, response_headers = RPCResponseEndpointUnit.message_received(self, msg, headers) # decorate our response_headers with process-saturation, as we need them to be set in the headers # earlier than send/build_header so the sampling takes notice try: response_headers['process-saturation'] = self._get_process_saturation() except Exception as ex: log.warn("Could not set process-saturation header, ignoring: %s", ex) return result, response_headers
def _message_received(self, msg, headers): """ Message received override for processes. Sets the process context here to be used for subsequent calls out by this process to other processes, or replies. """ ###### ###### THIS IS WHERE THE THREAD LOCAL HEADERS CONTEXT IS SET ###### ###### # With the property _routing_call set, as is the case 95% of the time in the Process-level endpoints, # we have to set the call context from the ION process' calling greenlet, as context is greenlet-specific. # This is done in the _make_routing_call override here, passing it the context to be set. # See also IonProcessThread._control_flow. with self._process.push_context(headers): return RPCResponseEndpointUnit._message_received(self, msg, headers)
def _make_routing_call(self, call, timeout, *op_args, **op_kwargs): if not self._routing_call: return RPCResponseEndpointUnit._make_routing_call(self, call, timeout, *op_args, **op_kwargs) ctx = self._process.get_context() ar = self._routing_call(call, ctx, *op_args, **op_kwargs) res = ar.get() # REMOVED TIMEOUT #try: # res = ar.get(timeout=timeout) #except Timeout: # # cancel or abort current processing # self._process._process.cancel_or_abort_call(ar) # raise IonTimeout("Process did not execute in allotted time") # will be returned to caller via messaging # Persistent process state handling if hasattr(self._process, "_proc_state"): if self._process._proc_state_changed: log.debug("Process %s state changed. State=%s", self._process.id, self._process._proc_state) self._process._flush_state() return res
def test__sample_request(self): e = RPCResponseEndpointUnit(interceptors={}) e._get_sflow_manager = Mock(return_value=Mock(spec=SFlowManager)) e._get_sflow_manager.return_value.should_sample = True e._build_sample = Mock(return_value={'test':sentinel.test}) e.channel = Mock() e.channel.get_stats = Mock(return_value=(3, 0)) e.channel._recv_queue.qsize = Mock(return_value=3) e._sample_request(sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers) e._get_sflow_manager.assert_called_once_with() e._build_sample.assert_called_once_with(ANY, sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers, 6) e._get_sflow_manager.return_value.transaction.assert_called_once_with(test=sentinel.test)
def test__sample_request(self): e = RPCResponseEndpointUnit(interceptors={}) e._get_sflow_manager = Mock(return_value=Mock(spec=SFlowManager)) e._get_sflow_manager.return_value.should_sample = True e._build_sample = Mock(return_value={'test': sentinel.test}) e.channel = Mock() e.channel.get_stats = Mock(return_value=(3, 0)) e.channel._recv_queue.qsize = Mock(return_value=3) e._sample_request(sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers) e._get_sflow_manager.assert_called_once_with() e._build_sample.assert_called_once_with(ANY, sentinel.status, sentinel.status_descr, sentinel.msg, sentinel.headers, sentinel.response, sentinel.response_headers, 6) e._get_sflow_manager.return_value.transaction.assert_called_once_with( test=sentinel.test)
def __init__(self, process=None, routing_call=None, **kwargs): ProcessEndpointUnitMixin.__init__(self, process=process) RPCResponseEndpointUnit.__init__(self, **kwargs) self._routing_call = routing_call
def test_message_received_unknown_msg_type(self): rout_obj = Mock() e = RPCResponseEndpointUnit(routing_obj=rout_obj) self.assertRaises(exception.BadRequest, e.message_received, 3, {})
def test__get_sflow_manager(self): Container.instance = None e = RPCResponseEndpointUnit(interceptors={}) self.assertIsNone(e._get_sflow_manager())
def test__get_sample_name(self): e = RPCResponseEndpointUnit(interceptors={}) self.assertEquals(e._get_sample_name(), "unknown-rpc-server")
def _make_routing_call(self, call, op_args): if not self._routing_call: return RPCResponseEndpointUnit._make_routing_call(self, call, op_args) ar = self._routing_call(call, op_args, context=self._process.get_context()) return ar.get() # @TODO: timeout?