PROTON-1583: some additional tests
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
index 80ad20c..ff5a5b4 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/TransportImplTest.java
@@ -1707,6 +1707,162 @@
}
@Test
+ public void testTickWithLocalTimeout()
+ {
+ // all-positive
+ doTickWithLocalTimeoutTestImpl(4000, 10000, 14000, 18000, 22000);
+
+ // all-negative
+ doTickWithLocalTimeoutTestImpl(2000, -100000, -98000, -96000, -94000);
+
+ // negative to positive missing 0
+ doTickWithLocalTimeoutTestImpl(500, -950, -450, 50, 550);
+
+ // negative to positive striking 0
+ doTickWithLocalTimeoutTestImpl(3000, -6000, -3000, 1, 3001);
+ }
+
+ private void doTickWithLocalTimeoutTestImpl(int localTimeout, long tick1, long expectedDeadline1, long expectedDeadline2, long expectedDeadline3)
+ {
+ MockTransportImpl transport = new MockTransportImpl();
+ Connection connection = Proton.connection();
+ transport.bind(connection);
+
+ // Set our local idleTimeout
+ transport.setIdleTimeout(localTimeout);
+
+ connection.open();
+ pumpMockTransport(transport);
+
+ assertEquals("should have written data", 1, transport.writes.size());
+ Object sentOpenFrame = transport.writes.get(0);
+ assertNotNull("should have written a non-empty frame", sentOpenFrame);
+ assertTrue("should have written an open frame", sentOpenFrame instanceof Open);
+ assertEquals("should have had an idletimeout value half our actual timeout", UnsignedInteger.valueOf(localTimeout / 2), ((Open)sentOpenFrame).getIdleTimeOut());
+
+ // Receive Protocol header
+ processInput(transport, ByteBuffer.wrap(new byte[] {'A', 'M', 'Q', 'P', 0x00, 0x01, 0x00, 0x00}));
+
+ // Handle the peer transmitting their open, without timeout.
+ Open open = new Open();
+ open.setIdleTimeOut(null);
+ TransportFrame openFrame = new TransportFrame(CHANNEL_ID, open, null);
+ transport.handleFrame(openFrame);
+ pumpMockTransport(transport);
+
+ long deadline = transport.tick(tick1);
+ assertEquals("Unexpected deadline returned", expectedDeadline1, deadline);
+
+ // Wait for less time than the deadline with no data - get the same value
+ long interimTick = tick1 + 10;
+ assertTrue (interimTick < expectedDeadline1);
+ assertEquals("When the deadline hasn't been reached tick() should return the previous deadline", expectedDeadline1, transport.tick(interimTick));
+ assertEquals("When the deadline hasn't been reached tick() shouldn't write data", 1, transport.writes.size());
+
+ // Receive Empty frame to satisfy local deadline
+ processInput(transport, ByteBuffer.wrap(new byte[] {0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00}));
+
+ deadline = transport.tick(expectedDeadline1);
+ assertEquals("When the deadline has been reached expected a new local deadline to be returned", expectedDeadline2, deadline);
+ assertEquals("When the deadline hasn't been reached tick() shouldn't write data", 1, transport.writes.size());
+
+ pumpMockTransport(transport);
+
+ // Receive Empty frame to satisfy local deadline
+ processInput(transport, ByteBuffer.wrap(new byte[] {0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00}));
+
+ deadline = transport.tick(expectedDeadline2);
+ assertEquals("When the deadline has been reached expected a new local deadline to be returned", expectedDeadline3, deadline);
+ assertEquals("When the deadline hasn't been reached tick() shouldn't write data", 1, transport.writes.size());
+
+ pumpMockTransport(transport);
+
+ assertEquals("Connection should be active", EndpointState.ACTIVE, connection.getLocalState());
+ transport.tick(expectedDeadline3); // Wait for the deadline, but don't receive traffic, allow local timeout to expire
+ assertEquals("Calling tick() after the deadline should result in the connection being closed", EndpointState.CLOSED, connection.getLocalState());
+ assertEquals("tick() should have written data", 2, transport.writes.size());
+ assertNotNull("should have written a non-empty frame", transport.writes.get(1));
+ assertTrue("should have written a close frame", transport.writes.get(1) instanceof Close);
+ }
+
+ @Test
+ public void testTickWithRemoteTimeout()
+ {
+ // all-positive
+ doTickWithRemoteTimeoutTestImpl(4000, 10000, 14000, 18000, 22000);
+
+ // all-negative
+ doTickWithRemoteTimeoutTestImpl(2000, -100000, -98000, -96000, -94000);
+
+ // negative to positive missing 0
+ doTickWithRemoteTimeoutTestImpl(500, -950, -450, 50, 550);
+
+ // negative to positive striking 0
+ doTickWithRemoteTimeoutTestImpl(3000, -6000, -3000, 1, 3001);
+ }
+
+ private void doTickWithRemoteTimeoutTestImpl(int remoteTimeoutHalf, long tick1, long expectedDeadline1, long expectedDeadline2, long expectedDeadline3)
+ {
+ MockTransportImpl transport = new MockTransportImpl();
+ Connection connection = Proton.connection();
+ transport.bind(connection);
+
+ connection.open();
+ pumpMockTransport(transport);
+
+ assertEquals("should have written data", 1, transport.writes.size());
+ Object sentOpenFrame = transport.writes.get(0);
+ assertNotNull("should have written a non-empty frame", sentOpenFrame);
+ assertTrue("should have written an open frame", sentOpenFrame instanceof Open);
+ assertNull("should not have had an idletimeout value", ((Open)sentOpenFrame).getIdleTimeOut());
+
+ // Receive Protocol header
+ processInput(transport, ByteBuffer.wrap(new byte[] {'A', 'M', 'Q', 'P', 0x00, 0x01, 0x00, 0x00}));
+
+ // Handle the peer transmitting [half] their timeout. We half it on receipt to avoid spurious timeouts
+ // if they not have transmitted half their actual timeout, as the AMQP spec only says they SHOULD do that.
+ Open open = new Open();
+ open.setIdleTimeOut(new UnsignedInteger(remoteTimeoutHalf * 2));
+ TransportFrame openFrame = new TransportFrame(CHANNEL_ID, open, null);
+ transport.handleFrame(openFrame);
+ pumpMockTransport(transport);
+
+ long deadline = transport.tick(tick1);
+ assertEquals("Unexpected deadline returned", expectedDeadline1, deadline);
+
+ // Wait for less time than the deadline with no data - get the same value
+ long interimTick = tick1 + 10;
+ assertTrue (interimTick < expectedDeadline1);
+ assertEquals("When the deadline hasn't been reached tick() should return the previous deadline", expectedDeadline1, transport.tick(interimTick));
+ assertEquals("When the deadline hasn't been reached tick() shouldn't write data", 1, transport.writes.size());
+
+ deadline = transport.tick(expectedDeadline1);
+ assertEquals("When the deadline has been reached expected a new remote deadline to be returned", expectedDeadline2, deadline);
+ assertEquals("tick() should have written data", 2, transport.writes.size());
+ assertEquals("tick() should have written an empty frame", null, transport.writes.get(1));
+
+ pumpMockTransport(transport);
+
+ // Do some actual work, create real traffic, removing the need to send empty frame to satisfy idle-timeout
+ connection.session().open();
+ pumpMockTransport(transport);
+ assertEquals("session open should have written data", 3, transport.writes.size());
+ Object sentBeginFrame = transport.writes.get(2);
+ assertNotNull("should have written a non-empty frame", sentBeginFrame);
+ assertTrue("session open should have written a Begin frame", sentBeginFrame instanceof Begin);
+
+ deadline = transport.tick(expectedDeadline2);
+ assertEquals("When the deadline has been reached expected a new remote deadline to be returned", expectedDeadline3, deadline);
+ assertEquals("tick() should not have written data as there was actual activity", 3, transport.writes.size());
+
+ pumpMockTransport(transport);
+
+ transport.tick(expectedDeadline3);
+ assertEquals("tick() should have written data", 4, transport.writes.size());
+ assertEquals("tick() should have written an empty frame", null, transport.writes.get(1));
+ }
+
+ @Test
public void testTickWithBothTimeouts()
{
// all-positive
@@ -1747,6 +1903,9 @@
assertNotNull("should have written a non-empty frame", transport.writes.get(0));
assertTrue("should have written an open frame", transport.writes.get(0) instanceof Open);
+ // Receive Protocol header
+ processInput(transport, ByteBuffer.wrap(new byte[] {'A', 'M', 'Q', 'P', 0x00, 0x01, 0x00, 0x00}));
+
// Handle the peer transmitting [half] their timeout. We half it on receipt to avoid spurious timeouts
// if they not have transmitted half their actual timeout, as the AMQP spec only says they SHOULD do that.
Open open = new Open();
@@ -1831,6 +1990,9 @@
assertNotNull("should have written a non-empty frame", transport.writes.get(0));
assertTrue("should have written an open frame", transport.writes.get(0) instanceof Open);
+ // Receive Protocol header
+ processInput(transport, ByteBuffer.wrap(new byte[] {'A', 'M', 'Q', 'P', 0x00, 0x01, 0x00, 0x00}));
+
// Handle the peer transmitting [half] their timeout. We half it on receipt to avoid spurious timeouts
// if they not have transmitted half their actual timeout, as the AMQP spec only says they SHOULD do that.
Open open = new Open();