def test_read_write_flow_control(self): # Test the read and write flow control of a stream transport. transport = MockTransport() protocol = StreamProtocol() transport.start(protocol) protocol.stream.buffer.set_buffer_limits(100) transport.set_write_buffer_limits(50) def reader(): while True: buf = protocol.stream.read(20) if not buf: break protocol.stream.write(buf) fib = gruvi.spawn(reader) buf = b'x' * 20 interrupted = 0 for i in range(100): protocol.data_received(buf) if transport._reading: continue interrupted += 1 self.assertGreater(protocol.stream.buffer.get_buffer_size(), 0) # Switch to the reader() fiber which will fill up the transport # write buffer. gruvi.sleep(0) # The transport write buffer should be full but the protocol read # buffer should still contain something. self.assertGreater(protocol.stream.buffer.get_buffer_size(), 0) self.assertFalse(transport._can_write.is_set()) # Drain write buffer and resume writing transport.drain() self.assertGreater(interrupted, 30) fib.cancel() gruvi.sleep(0)
def test_read_write_flow_control(self): # Send a lot of messages filling up the protocol read buffer. transport = MockTransport() protocol = DbusProtocol(self.store_and_echo_messages, server_side=True) transport.start(protocol) protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n') auth = protocol._authenticator self.assertTrue(auth.authenticationSucceeded()) message = txdbus.MethodCallMessage('/org/freedesktop/DBus', 'Hello', interface='org.freedesktop.DBus', destination='org.freedesktop.DBus') protocol.data_received(message.rawMessage) gruvi.sleep(0) self.assertTrue(protocol._name_acquired.is_set()) interrupted = 0 message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface', signature='s', body=['x'*100]) msglen = len(message.rawMessage) protocol.max_queue_size = 10 transport.drain() transport.set_write_buffer_limits(7*msglen) for i in range(100): # Fill up protocol message queue protocol.data_received(message.rawMessage) if transport._reading: continue interrupted += 1 self.assertEqual(protocol._queue.qsize(), 10) # Run the dispatcher to fill up the transport write buffer gruvi.sleep(0) # Now the write buffer is full and the read buffer still contains # some entries because it is larger. self.assertGreater(protocol._queue.qsize(), 0) self.assertFalse(transport._can_write.is_set()) transport.drain() # Should be interrupted > 10 times. The write buffer is the limiting factor # not the read buffer. self.assertGreater(interrupted, 10)