def test_bad_src_id(self): # Deliver a message locally from child2 with the correct auth_id, but # the wrong src_id. log = testlib.LogCapturer() log.start() # Used to ensure the message was dropped rather than routed after the # error is logged. recv = mitogen.core.Receiver(self.router) self.child2_msg.handle = recv.handle self.child2_msg.src_id = self.child1.context_id self.broker.defer(self.router._async_route, self.child2_msg, self.child2_stream) # Wait for IO loop to finish everything above. self.sync_with_broker() # Ensure message wasn't forwarded. self.assertTrue(recv.empty()) # Ensure error was lgoged. expect = 'bad src_id: got %d via' % (self.child1_msg.src_id,) self.assertTrue(expect in log.stop())
def test_forward_to_nonexistent_context(self): nonexistent = mitogen.core.Context(self.router, 123) capture = testlib.LogCapturer() capture.start() self.broker.defer_sync(lambda: self.router.responder.forward_modules( nonexistent, ['mitogen.core'])) s = capture.stop() self.assertTrue('dropping forward of' in s)
def test_earliest_messages_logged(self): log = testlib.LogCapturer() log.start() c1 = self.router.local() c1.shutdown(wait=True) logs = log.stop() self.assertTrue('Python version is' in logs) self.assertTrue('Parent is context 0 (master)' in logs)
def test_siblings_cant_talk(self): self.router.unidirectional = True l1 = self.router.fork() l2 = self.router.fork() logs = testlib.LogCapturer() logs.start() e = self.assertRaises(mitogen.core.CallError, lambda: l2.call(ping_context, l1)) msg = 'mitogen.core.ChannelError: Channel closed by remote end.' self.assertTrue(msg in str(e)) self.assertTrue('routing mode prevents forward of ' in logs.stop())
def test_local_exceeded(self): router = self.klass(broker=self.broker, max_message_size=4096) logs = testlib.LogCapturer() logs.start() # Send message and block for one IO loop, so _async_route can run. router.route(mitogen.core.Message.pickled(' ' * 8192)) router.broker.defer_sync(lambda: None) expect = 'message too large (max 4096 bytes)' self.assertTrue(expect in logs.stop())
def test_remote_exceeded(self): # Ensure new contexts receive a router with the same value. router = self.klass(broker=self.broker, max_message_size=64 * 1024) recv = mitogen.core.Receiver(router) logs = testlib.LogCapturer() logs.start() remote = router.local() remote.call(send_n_sized_reply, recv.to_sender(), 128 * 1024) expect = 'message too large (max %d bytes)' % (64 * 1024, ) self.assertTrue(expect in logs.stop())
def test_constructor_basic(self): listener = self.klass.build_stream(router=self.router) capture = testlib.LogCapturer() capture.start() try: self.assertFalse(mitogen.unix.is_path_dead(listener.protocol.path)) os.unlink(listener.protocol.path) # ensure we catch 0 byte read error log message self.broker.shutdown() self.broker.join() self.broker_shutdown = True finally: capture.stop()
def test_sibling_cannot_activate_service(self): l1 = self.router.local() l2 = self.router.local() l1.call_service(MyService, 'get_id') # force framework activation capture = testlib.LogCapturer() capture.start() try: exc = self.assertRaises(mitogen.core.CallError, lambda: l2.call(call_service_in, l1, MyService2.name(), 'get_id')) finally: capture.stop() msg = mitogen.service.Activator.not_active_msg % (MyService2.name(),) self.assertTrue(msg in exc.args[0])
def test_local_exceeded(self): router = self.klass(broker=self.broker, max_message_size=4096) recv = mitogen.core.Receiver(router) logs = testlib.LogCapturer() logs.start() sem = mitogen.core.Latch() router.route(mitogen.core.Message.pickled(' '*8192)) router.broker.defer(sem.put, ' ') # wlil always run after _async_route sem.get() expect = 'message too large (max 4096 bytes)' self.assertTrue(expect in logs.stop())
def test_siblings_cant_talk(self): self.router.unidirectional = True l1 = self.router.local() l2 = self.router.local() logs = testlib.LogCapturer() logs.start() e = self.assertRaises(mitogen.core.CallError, lambda: l2.call(ping_context, l1)) msg = self.router.unidirectional_msg % ( l2.context_id, l1.context_id, ) self.assertTrue(msg in str(e)) self.assertTrue('routing mode prevents forward of ' in logs.stop())
def test_debug_decoding(self): # ensure filter_debug_logs() decodes the logged string. capture = testlib.LogCapturer() capture.start() try: context = self.docker_ssh( username='******', password='******', ssh_debug_level=3, ) finally: s = capture.stop() expect = "%s: debug1: Reading configuration data" % (context.name, ) self.assertTrue(expect in s)
def test_earliest_messages_logged_via(self): c1 = self.router.local(name='c1') # ensure any c1-related msgs are processed before beginning capture c1.call(ping) log = testlib.LogCapturer() log.start() c2 = self.router.local(via=c1, name='c2', debug=True) c2.shutdown(wait=True) logs = log.stop() self.assertTrue('Python version is' in logs) expect = 'Parent is context %s (%s)' % (c1.context_id, 'parent') self.assertTrue(expect in logs)
def test_sibling_privileged_bad(self): l1 = self.router.local() l1.call_service(MyService, 'get_id') l2 = self.router.local() capture = testlib.LogCapturer() capture.start() try: exc = self.assertRaises(mitogen.core.CallError, lambda: l2.call(call_service_in, l1, MyService.name(), 'privileged_op')) finally: capture.stop() msg = mitogen.service.Invoker.unauthorized_msg % ( u'privileged_op', MyService.name(), ) self.assertTrue(msg in exc.args[0])
def test_local_dead_message(self): # Local router should generate dead message when reply_to is set. router = self.klass(broker=self.broker, max_message_size=4096) logs = testlib.LogCapturer() logs.start() expect = router.too_large_msg % (4096, ) # Try function call. Receiver should be woken by a dead message sent by # router due to message size exceeded. child = router.local() e = self.assertRaises(mitogen.core.ChannelError, lambda: child.call(zlib.crc32, ' ' * 8192)) self.assertEquals(e.args[0], expect) self.assertTrue(expect in logs.stop())
def test_corruption(self): broker = mock.Mock() router = mock.Mock() stream = self.klass(router, 1) junk = mitogen.core.b('x') * stream.HEADER_LEN stream._input_buf = [junk] stream._input_buf_len = len(junk) capture = testlib.LogCapturer() capture.start() ret = stream._receive_one(broker) #self.assertEquals(1, broker.stop_receive.mock_calls) capture.stop() self.assertFalse(ret) self.assertTrue((self.klass.corrupt_msg % (junk, )) in capture.raw())
def test_auth_id_can_talk(self): self.router.unidirectional = True # One stream has auth_id stamped to that of the master, so it should be # treated like a parent. l1 = self.router.fork() l1s = self.router.stream_by_id(l1.context_id) l1s.auth_id = mitogen.context_id l1s.is_privileged = True l2 = self.router.fork() logs = testlib.LogCapturer() logs.start() e = self.assertRaises(mitogen.core.CallError, lambda: l2.call(ping_context, l1)) msg = 'mitogen.core.CallError: Refused by policy.' self.assertTrue(msg in str(e)) self.assertTrue('policy refused message: ' in logs.stop())
def test_siblings_cant_talk(router): l1 = router.local() l2 = router.local() logs = testlib.LogCapturer() logs.start() try: l2.call(ping_context, l1) except mitogen.core.CallError: e = sys.exc_info()[1] msg = mitogen.core.Router.unidirectional_msg % ( l2.context_id, l1.context_id, mitogen.context_id, ) assert msg in str(e) assert 'routing mode prevents forward of ' in logs.stop()
def test_corruption(self): broker = mock.Mock() router = mock.Mock() stream = mock.Mock() protocol = self.klass(router, 1) protocol.stream = stream junk = mitogen.core.b('x') * mitogen.core.Message.HEADER_LEN capture = testlib.LogCapturer() capture.start() protocol.on_receive(broker, junk) capture.stop() self.assertEquals(1, stream.on_disconnect.call_count) expect = self.klass.corrupt_msg % (stream.name, junk) self.assertTrue(expect in capture.raw())
def test_shutdown(self): router = self.klass(self.broker) sem = mitogen.core.Latch() router.add_handler(sem.put) log = testlib.LogCapturer('mitogen') log.start() # Force a crash and ensure it wakes up. self.broker._loop_once = self._naughty self.broker.defer(lambda: None) # sem should have received dead message. self.assertTrue(sem.get().is_dead) # Ensure it was logged. expect = '_broker_main() crashed' self.assertTrue(expect in log.stop())
def test_bad_auth_id(self): # Deliver a message locally from child2, but using child1's stream. log = testlib.LogCapturer() log.start() # Used to ensure the message was dropped rather than routed after the # error is logged. recv = mitogen.core.Receiver(self.router) self.child2_msg.handle = recv.handle self.broker.defer_sync(lambda: self.router._async_route( self.child2_msg, in_stream=self.child1_stream)) # Ensure message wasn't forwarded. self.assertTrue(recv.empty()) # Ensure error was logged. expect = 'bad auth_id: got %r via' % (self.child2_msg.auth_id, ) self.assertTrue(expect in log.stop())
def test_refuse_all(self): # Deliver a message locally from child2 with the correct auth_id, but # the wrong src_id. log = testlib.LogCapturer() log.start() # This guy never gets anything. recv = mitogen.core.Receiver( router=self.router, policy=(lambda msg, stream: False), ) # This guy becomes the reply_to of our refused message. reply_target = mitogen.core.Receiver(self.router) # Send the message. self.router.route( mitogen.core.Message( dst_id=mitogen.context_id, handle=recv.handle, reply_to=reply_target.handle, ) ) # Wait for IO loop. self.sync_with_broker() # Verify log. expect = '%r: policy refused message: ' % (self.router,) self.assertTrue(expect in log.stop()) # Verify message was not delivered. self.assertTrue(recv.empty()) # Verify CallError received by reply_to target. e = self.assertRaises(mitogen.core.CallError, lambda: reply_target.get().unpickle()) self.assertEquals(e[0], self.router.refused_msg)