class TestRedirectionService(ScalyrTestCase): """Tests both the RedirectorServer and the RedirectorClient communicating together. """ def setUp(self): self._client_sys = FakeSys() self._server_sys = FakeSys() self._fake_clock = scalyr_util.FakeClock() self._client_channel = FakeClientChannel(self._fake_clock) self._server_channel = FakeServerChannel(self._client_channel) self._client = RedirectorClient(self._client_channel, sys_impl=self._client_sys, fake_clock=self._fake_clock) self._server = RedirectorServer(self._server_channel, sys_impl=self._server_sys) self._client.start() self._server.start() def test_end_to_end(self): self._server_sys.stdout.write('Test full') self._server.stop() self._client.stop()
class TestRedirectorClient(ScalyrTestCase): """Test the RedirectorClient by faking out the client channel and also the clock. """ def setUp(self): self._fake_sys = FakeSys() # Since the client is an actual other thread that blocks waiting for input from the server, we have to # simulate the time using a fake clock. That will allow us to wait up the client thread from time to time. self._fake_clock = scalyr_util.FakeClock() # The fake channel allows us to insert bytes being sent by the server. self._client_channel = FakeClientChannel(self._fake_clock) self._client = RedirectorClient(self._client_channel, sys_impl=self._fake_sys, fake_clock=self._fake_clock) self._client.start() # Wait until the client thread begins to block for the initial accept from the server. self._fake_clock.block_until_n_waiting_threads(1) def tearDown(self): if self._client is not None: self._client.stop(wait_on_join=False) self._fake_clock.advance_time(set_to=59.0) self._client.join() def test_receiving_str(self): # Simulate accepting the connection. self._accept_client_connection() self._send_to_client(0, 'Testing') # Wait until have bytes written to stdout by the client thread. self._fake_sys.stdout.wait_for_bytes(1.0) self.assertEquals(self._fake_sys.stdout.last_write, 'Testing') def test_receiving_unicode(self): self._accept_client_connection() self._send_to_client(0, u'caf\xe9') self._fake_sys.stdout.wait_for_bytes(1.0) self.assertEquals(self._fake_sys.stdout.last_write, u'caf\xe9') def test_connection_timeout(self): # We advance the time past 60 seconds which is the connection time out. self._fake_clock.advance_time(set_to=61.0) got_it = False try: # Even though we have not called stop on the thread or the server hasn't closed the connection, # we should still see the client thread terminate because of the exception it raises. self._client.join() except RedirectorError: got_it = True self._client = None self.assertTrue(got_it) def test_close_from_server(self): self._accept_client_connection() self._send_to_client(-1, '') # Even though we haven't called stop on the client thread, it should still end because the server sent # the signal to stop/close. self._client.join() self._client = None def test_stopped_during_connection(self): self._client.stop(wait_on_join=False) # We have wake all threads so the client thread will notice its thread has been stopped. self._fake_clock.wake_all_threads() self._client.join() self._client = None def test_stopped_during_reading(self): self._accept_client_connection() self._client.stop(wait_on_join=False) # We have wake all threads so the client thread will notice its thread has been stopped. self._fake_clock.wake_all_threads() self._client.join() self._client = None def _accept_client_connection(self): self._client_channel.simulate_server_connect() def _send_to_client(self, stream_id, content): encoded_content = unicode(content).encode('utf-8') code = len(encoded_content) * 2 + stream_id self._client_channel.simulate_server_write(struct.pack('i', code) + encoded_content)
class TestRedirectorClient(ScalyrTestCase): """Test the RedirectorClient by faking out the client channel and also the clock.""" def setUp(self): super(TestRedirectorClient, self).setUp() self._fake_sys = FakeSys() # Since the client is an actual other thread that blocks waiting for input from the server, we have to # simulate the time using a fake clock. That will allow us to wait up the client thread from time to time. self._fake_clock = scalyr_util.FakeClock() # The fake channel allows us to insert bytes being sent by the server. self._client_channel = FakeClientChannel(self._fake_clock) self._client = RedirectorClient(self._client_channel, sys_impl=self._fake_sys, fake_clock=self._fake_clock) self._client.start() # Wait until the client thread begins to block for the initial accept from the server. self._fake_clock.block_until_n_waiting_threads(1) def tearDown(self): if self._client is not None: self._client.stop(wait_on_join=False) self._fake_clock.advance_time(set_to=59.0) self._client.join() def test_receiving_bytes(self): # Simulate accepting the connection. self._accept_client_connection() self._send_to_client(0, "Testing") # Wait until have bytes written to stdout by the client thread. self._fake_sys.stdout.wait_for_bytes(1.0) self.assertEquals(self._fake_sys.stdout.last_write, "Testing") def test_receiving_unicode(self): self._accept_client_connection() self._send_to_client(0, "caf\xe9") self._fake_sys.stdout.wait_for_bytes(1.0) self.assertEquals(self._fake_sys.stdout.last_write, "caf\xe9") def test_connection_timeout(self): # We advance the time past 60 seconds which is the connection time out. self._fake_clock.advance_time(set_to=61.0) got_it = False try: # Even though we have not called stop on the thread or the server hasn't closed the connection, # we should still see the client thread terminate because of the exception it raises. self._client.join() except RedirectorError: got_it = True self._client = None self.assertTrue(got_it) def test_close_from_server(self): self._accept_client_connection() self._send_to_client(-1, "") # Even though we haven't called stop on the client thread, it should still end because the server sent # the signal to stop/close. self._client.join() self._client = None def test_stopped_during_connection(self): self._client.stop(wait_on_join=False) # We have wake all threads so the client thread will notice its thread has been stopped. self._fake_clock.wake_all_threads() self._client.join() self._client = None def test_stopped_during_reading(self): self._accept_client_connection() self._client.stop(wait_on_join=False) # We have wake all threads so the client thread will notice its thread has been stopped. self._fake_clock.wake_all_threads() self._client.join() self._client = None def _accept_client_connection(self): self._client_channel.simulate_server_connect() def _send_to_client(self, stream_id, content): if type(content) is six.text_type: encoded_content = six.text_type(content).encode("utf-8") else: encoded_content = content code = len(encoded_content) * 2 + stream_id # 2->TODO struct.pack|unpack in python < 2.7.7 does not allow unicode format string. self._client_channel.simulate_server_write( compat.struct_pack_unicode("i", code) + encoded_content)