def test_auth_long_line(self): # An authentication line should not exceed the maximum line size. transport = MockTransport() protocol = DbusProtocol(True, None, 'foo') protocol.max_line_size = 5 transport.start(protocol) self.assertFalse(transport.closed) protocol.data_received(b'\0AUTH ANONYMOUS\r\n') self.assertIsInstance(protocol._error, DbusError) self.assertTrue(transport.closed)
def test_auth_missing_creds_byte(self): # The first thing a client should send to the server is a '\0' byte. If # not, the server should close the connection. transport = MockTransport() protocol = DbusProtocol(True, None) transport.start(protocol) self.assertFalse(transport.closed) protocol.data_received(b'\1') self.assertIsInstance(protocol._error, DbusError) self.assertTrue(transport.closed)
def test_auth_non_ascii(self): # After the '\0' byte, an authentiction phase happens. The # authentication protocol is line based and all lines should be ascii. transport = MockTransport() protocol = DbusProtocol(True, None) transport.start(protocol) self.assertFalse(transport.closed) protocol.data_received(b'\0\xff\r\n') self.assertIsInstance(protocol._error, DbusError) self.assertTrue(transport.closed)
def test_missing_hello(self): # After authentication, the first message should be a "Hello". # Otherwise, the server should close the connection. transport = MockTransport() protocol = DbusProtocol(True, self.store_messages, 'foo') transport.start(protocol) protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n') message = txdbus.MethodCallMessage('/my/path', 'Method') auth = protocol._authenticator self.assertTrue(auth.authenticationSucceeded()) protocol.data_received(message.rawMessage) self.assertIsInstance(protocol._error, DbusError) self.assertTrue(transport.closed)
def test_auth_ok(self): # Test anonymous authenication. Ensure that the server GUID is # correctly sent back. transport = MockTransport() protocol = DbusProtocol(True, None, 'foo') transport.start(protocol) protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n') buf = transport.buffer.getvalue() self.assertTrue(buf.startswith(b'OK foo')) auth = protocol._authenticator self.assertTrue(auth.authenticationSucceeded()) self.assertTrue(auth.getGUID(), 'foo') self.assertFalse(transport.closed)
def test_send_message_too_large(self): # Send a message that exceeds the maximum message size. The connection # should be closed. transport = MockTransport() protocol = DbusProtocol(True, self.store_messages, 'foo') transport.start(protocol) protocol.data_received(b'\0AUTH ANONYMOUS\r\nBEGIN\r\n') 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) # Send a signal with a size equal to the high-water mark. This should work. message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface', signature='s', body=['x'*100]) msglen = len(message.rawMessage) self.assertGreater(msglen, 100) protocol.set_read_buffer_limits(msglen) protocol.data_received(message.rawMessage) gruvi.sleep(0) self.assertIsNone(protocol._error) self.assertFalse(transport.closed) self.assertEqual(len(self.messages), 1) # Now send a signal with a size larger than the high-water mark. This should fail. message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface', signature='s', body=['x'*100]) msglen = len(message.rawMessage) protocol.set_read_buffer_limits(msglen-1) protocol.data_received(message.rawMessage) gruvi.sleep(0) self.assertIsInstance(protocol._error, DbusError) self.assertTrue(transport.closed) self.assertEqual(len(self.messages), 1)
def test_send_message_incremental(self): # Send a message byte by byte. The protocol should be able process it. transport = MockTransport() protocol = DbusProtocol(True, self.store_messages, 'foo') transport.start(protocol) authexchange = b'\0AUTH ANONYMOUS\r\nBEGIN\r\n' for i in range(len(authexchange)): protocol.data_received(authexchange[i:i+1]) auth = protocol._authenticator self.assertTrue(auth.authenticationSucceeded()) message = txdbus.MethodCallMessage('/org/freedesktop/DBus', 'Hello', interface='org.freedesktop.DBus', destination='org.freedesktop.DBus') for i in range(len(message.rawMessage)): protocol.data_received(message.rawMessage[i:i+1]) gruvi.sleep(0) self.assertIsNone(protocol._error) self.assertFalse(transport.closed) self.assertEqual(len(self.messages), 0) message = txdbus.MethodCallMessage('/my/path', 'Method') for i in range(len(message.rawMessage)): protocol.data_received(message.rawMessage[i:i+1]) gruvi.sleep(0) self.assertIsNone(protocol._error) self.assertFalse(transport.closed) self.assertEqual(len(self.messages), 1) self.assertEqual(self.messages[0].path, '/my/path') self.assertEqual(self.messages[0].member, 'Method') self.assertEqual(self.protocols, [protocol])
def test_send_message(self): # After the "Hello" message, it should be possible to send other # messages. transport = MockTransport() protocol = DbusProtocol(True, self.store_messages, 'foo') 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.assertIsNone(protocol._error) self.assertFalse(transport.closed) self.assertTrue(protocol._name_acquired) self.assertEqual(len(self.messages), 0) message = txdbus.MethodCallMessage('/my/path', 'Method') protocol.data_received(message.rawMessage) gruvi.sleep(0) self.assertIsNone(protocol._error) self.assertFalse(transport.closed) self.assertEqual(len(self.messages), 1) self.assertEqual(self.messages[0].path, '/my/path') self.assertEqual(self.messages[0].member, 'Method') self.assertEqual(self.protocols, [protocol])
def test_read_write_flow_control(self): # Send a lot of messages filling up the protocol read buffer. transport = MockTransport() protocol = DbusProtocol(True, self.store_and_echo_messages) 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) interrupted = 0 message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface', signature='s', body=['x'*100]) msglen = len(message.rawMessage) protocol.set_read_buffer_limits(10*msglen) transport.buffer.seek(0) transport.buffer.truncate() transport.set_write_buffer_limits(7*msglen) for i in range(100): # Fill up protocol read buffer message = txdbus.SignalMessage('/my/path', 'Signal', 'my.iface', signature='s', body=['x'*100]) protocol.data_received(message.rawMessage) if protocol._reading: continue interrupted += 1 self.assertGreater(protocol._queue.qsize(), 0) # 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.assertTrue(protocol._reading) self.assertGreater(protocol._queue.qsize(), 0) self.assertFalse(protocol._may_write.is_set()) # Drain write buffer and resume writing transport.buffer.seek(0) transport.buffer.truncate() protocol.resume_writing() # Should be interrupted > 10 times. The write buffer is the limiting factor # not the read buffer. self.assertGreater(interrupted, 10)