From ef0e76c732c6edadb784ba2625781c0f011c50b5 Mon Sep 17 00:00:00 2001 From: chrjohn Date: Sat, 24 Feb 2018 23:39:59 +0100 Subject: [PATCH 1/2] - added logic to unregister Session to Session.close() method - changed some tests to use try-with-resources on Session - changed Connector implementations to clean up used Sessions on stop - changed AbstractSocketInitiator to clean up internal map of initiators on stop --- .../src/main/java/quickfix/Session.java | 26 +- .../main/java/quickfix/SocketAcceptor.java | 3 +- .../main/java/quickfix/SocketInitiator.java | 3 +- .../java/quickfix/ThreadedSocketAcceptor.java | 3 +- .../quickfix/ThreadedSocketInitiator.java | 3 +- .../java/quickfix/mina/SessionConnector.java | 9 + .../initiator/AbstractSocketInitiator.java | 8 +- .../jmx/mbean/session/SessionAdminTest.java | 11 +- .../quickfix/DefaultSessionFactoryTest.java | 58 +- .../src/test/java/quickfix/FileLogTest.java | 17 +- .../src/test/java/quickfix/JdbcLogTest.java | 19 +- .../SessionDisconnectConcurrentlyTest.java | 79 +- .../java/quickfix/SessionDisconnectTest.java | 41 +- .../test/java/quickfix/SessionResetTest.java | 107 +- .../src/test/java/quickfix/SessionTest.java | 2207 ++++++++--------- .../java/quickfix/SocketAcceptorTest.java | 115 +- .../java/quickfix/SocketInitiatorTest.java | 8 +- .../quickfix/mina/SessionConnectorTest.java | 72 +- ...adPerSessionEventHandlingStrategyTest.java | 242 +- .../mina/acceptor/AcceptorIoHandlerTest.java | 172 +- .../DynamicAcceptorSessionProviderTest.java | 79 +- 21 files changed, 1713 insertions(+), 1569 deletions(-) diff --git a/quickfixj-core/src/main/java/quickfix/Session.java b/quickfixj-core/src/main/java/quickfix/Session.java index d4d099a19f..23f7665cac 100644 --- a/quickfixj-core/src/main/java/quickfix/Session.java +++ b/quickfixj-core/src/main/java/quickfix/Session.java @@ -676,15 +676,23 @@ static void registerSession(Session session) { sessions.put(session.getSessionID(), session); } - static void unregisterSessions(List sessionIds) { + static void unregisterSessions(List sessionIds, boolean doClose) { for (final SessionID sessionId : sessionIds) { - final Session session = sessions.remove(sessionId); - if (session != null) { - try { + unregisterSession(sessionId, doClose); + } + } + + static void unregisterSession(SessionID sessionId, boolean doClose) { + final Session session = sessions.get(sessionId); + if (session != null) { + try { + if (doClose) { session.close(); - } catch (final IOException e) { - LOG.error("Failed to close session resources", e); } + } catch (final IOException e) { + LOG.error("Failed to close session resources", e); + } finally { + sessions.remove(sessionId); } } } @@ -2911,13 +2919,15 @@ public boolean isAllowedForSession(InetAddress remoteInetAddress) { } /** - * Closes session resources. This is for internal use and should typically - * not be called by an user application. + * Closes session resources and unregisters session. This is for internal + * use and should typically not be called by an user application. */ @Override public void close() throws IOException { closeIfCloseable(getLog()); closeIfCloseable(getStore()); + // clean up session just in case close() was not called from Session.unregisterSession() + unregisterSession(this.sessionID, false); } private void closeIfCloseable(Object resource) throws IOException { diff --git a/quickfixj-core/src/main/java/quickfix/SocketAcceptor.java b/quickfixj-core/src/main/java/quickfix/SocketAcceptor.java index c8dfc5edfd..0d3e43ac36 100644 --- a/quickfixj-core/src/main/java/quickfix/SocketAcceptor.java +++ b/quickfixj-core/src/main/java/quickfix/SocketAcceptor.java @@ -107,7 +107,8 @@ public void stop(boolean forceDisconnect) { stopSessionTimer(); } finally { eventHandlingStrategy.stopHandlingMessages(); - Session.unregisterSessions(getSessions()); + Session.unregisterSessions(getSessions(), true); + clearConnectorSessions(); isStarted = Boolean.FALSE; } } diff --git a/quickfixj-core/src/main/java/quickfix/SocketInitiator.java b/quickfixj-core/src/main/java/quickfix/SocketInitiator.java index 71d5931ce3..ff6d0dee38 100644 --- a/quickfixj-core/src/main/java/quickfix/SocketInitiator.java +++ b/quickfixj-core/src/main/java/quickfix/SocketInitiator.java @@ -96,7 +96,8 @@ public void stop(boolean forceDisconnect) { stopInitiators(); } finally { eventHandlingStrategy.stopHandlingMessages(); - Session.unregisterSessions(getSessions()); + Session.unregisterSessions(getSessions(), true); + clearConnectorSessions(); isStarted = Boolean.FALSE; } } diff --git a/quickfixj-core/src/main/java/quickfix/ThreadedSocketAcceptor.java b/quickfixj-core/src/main/java/quickfix/ThreadedSocketAcceptor.java index adf3dbbb67..eb4de0b3b8 100644 --- a/quickfixj-core/src/main/java/quickfix/ThreadedSocketAcceptor.java +++ b/quickfixj-core/src/main/java/quickfix/ThreadedSocketAcceptor.java @@ -87,7 +87,8 @@ public void stop(boolean forceDisconnect) { } stopSessionTimer(); eventHandlingStrategy.stopDispatcherThreads(); - Session.unregisterSessions(getSessions()); + Session.unregisterSessions(getSessions(), true); + clearConnectorSessions(); } public void block() throws ConfigError, RuntimeError { diff --git a/quickfixj-core/src/main/java/quickfix/ThreadedSocketInitiator.java b/quickfixj-core/src/main/java/quickfix/ThreadedSocketInitiator.java index 29233c65a5..46a30ca5bc 100644 --- a/quickfixj-core/src/main/java/quickfix/ThreadedSocketInitiator.java +++ b/quickfixj-core/src/main/java/quickfix/ThreadedSocketInitiator.java @@ -85,7 +85,8 @@ public void stop(boolean forceDisconnect) { logoutAllSessions(forceDisconnect); stopInitiators(); eventHandlingStrategy.stopDispatcherThreads(); - Session.unregisterSessions(getSessions()); + Session.unregisterSessions(getSessions(), true); + clearConnectorSessions(); } public void block() throws ConfigError, RuntimeError { diff --git a/quickfixj-core/src/main/java/quickfix/mina/SessionConnector.java b/quickfixj-core/src/main/java/quickfix/mina/SessionConnector.java index 06f207ed4e..f0ce6cc3bd 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/SessionConnector.java +++ b/quickfixj-core/src/main/java/quickfix/mina/SessionConnector.java @@ -119,6 +119,15 @@ protected void setSessions(Map sessions) { propertyChangeSupport.firePropertyChange(SESSIONS_PROPERTY, null, sessions); } + /** + * Will remove all Sessions from the SessionConnector's Session map. + * Please make sure that these Sessions were unregistered before via + * Session.unregisterSessions(). + */ + protected void clearConnectorSessions() { + this.sessions.clear(); + } + /** * Get the list of session managed by this connector. * diff --git a/quickfixj-core/src/main/java/quickfix/mina/initiator/AbstractSocketInitiator.java b/quickfixj-core/src/main/java/quickfix/mina/initiator/AbstractSocketInitiator.java index 3e9e0473cc..b17ca58387 100644 --- a/quickfixj-core/src/main/java/quickfix/mina/initiator/AbstractSocketInitiator.java +++ b/quickfixj-core/src/main/java/quickfix/mina/initiator/AbstractSocketInitiator.java @@ -77,9 +77,6 @@ protected AbstractSocketInitiator(SessionSettings settings, SessionFactory sessi protected void createSessionInitiators() throws ConfigError { try { - // QFJ698: clear() is needed on restart, otherwise the set gets filled up with - // more and more initiators which are not equal because the local port differs - initiators.clear(); createSessions(); SessionSettings settings = getSettings(); for (final Session session : getSessionMap().values()) { @@ -278,8 +275,9 @@ protected void startInitiators() { } protected void stopInitiators() { - for (final IoSessionInitiator initiator : initiators) { - initiator.stop(); + for (Iterator iterator = initiators.iterator(); iterator.hasNext();) { + iterator.next().stop(); + iterator.remove(); } super.stopSessionTimer(); } diff --git a/quickfixj-core/src/test/java/org/quickfixj/jmx/mbean/session/SessionAdminTest.java b/quickfixj-core/src/test/java/org/quickfixj/jmx/mbean/session/SessionAdminTest.java index 2352f64499..e5fcebc347 100644 --- a/quickfixj-core/src/test/java/org/quickfixj/jmx/mbean/session/SessionAdminTest.java +++ b/quickfixj-core/src/test/java/org/quickfixj/jmx/mbean/session/SessionAdminTest.java @@ -20,11 +20,12 @@ public class SessionAdminTest extends TestCase { public void testResetSequence() throws Exception { - Session session = SessionFactoryTestSupport.createSession(); - MockSessionAdmin admin = new MockSessionAdmin(session, null, null); - admin.resetSequence(25); - assertEquals(1, admin.sentMessages.size()); - assertEquals(25, admin.sentMessages.get(0).getInt(NewSeqNo.FIELD)); + try (Session session = SessionFactoryTestSupport.createSession()) { + MockSessionAdmin admin = new MockSessionAdmin(session, null, null); + admin.resetSequence(25); + assertEquals(1, admin.sentMessages.size()); + assertEquals(25, admin.sentMessages.get(0).getInt(NewSeqNo.FIELD)); + } } private class MockSessionAdmin extends SessionAdmin { diff --git a/quickfixj-core/src/test/java/quickfix/DefaultSessionFactoryTest.java b/quickfixj-core/src/test/java/quickfix/DefaultSessionFactoryTest.java index 0c305f3032..a991f559b6 100644 --- a/quickfixj-core/src/test/java/quickfix/DefaultSessionFactoryTest.java +++ b/quickfixj-core/src/test/java/quickfix/DefaultSessionFactoryTest.java @@ -19,6 +19,7 @@ package quickfix; +import java.io.IOException; import org.junit.Before; import org.junit.Test; import quickfix.field.ApplVerID; @@ -29,6 +30,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import org.junit.After; import static org.junit.Assert.*; public class DefaultSessionFactoryTest { @@ -45,6 +47,11 @@ public void setUp() throws Exception { new SLF4JLogFactory(new SessionSettings())); } + @After + public void tearDown() { + Session.unregisterSession(sessionID, true); + } + @Test public void testMinimalSettings() throws Exception { factory.create(sessionID, settings); @@ -86,29 +93,31 @@ public void testFixtDataDictionaryConfiguration() throws Exception { settings.setString(sessionID, Session.SETTING_APP_DATA_DICTIONARY, "FIX42.xml"); settings.setString(sessionID, Session.SETTING_APP_DATA_DICTIONARY + "." + FixVersions.BEGINSTRING_FIX40, "FIX40.xml"); - Session session = factory.create(sessionID, settings); - - DataDictionaryProvider provider = session.getDataDictionaryProvider(); - assertThat(provider.getSessionDataDictionary(sessionID.getBeginString()), - is(notNullValue())); + try (Session session = factory.create(sessionID, settings)) { - assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX42)), - is(notNullValue())); - assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX40)), - is(notNullValue())); + DataDictionaryProvider provider = session.getDataDictionaryProvider(); + assertThat(provider.getSessionDataDictionary(sessionID.getBeginString()), + is(notNullValue())); + + assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX42)), + is(notNullValue())); + assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX40)), + is(notNullValue())); + } } @Test public void testPreFixtDataDictionaryConfiguration() throws Exception { settings.setBool(sessionID, Session.SETTING_USE_DATA_DICTIONARY, true); - Session session = factory.create(sessionID, settings); + try (Session session = factory.create(sessionID, settings)) { - DataDictionaryProvider provider = session.getDataDictionaryProvider(); - assertThat(provider.getSessionDataDictionary(sessionID.getBeginString()), - is(notNullValue())); - assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX42)), - is(notNullValue())); + DataDictionaryProvider provider = session.getDataDictionaryProvider(); + assertThat(provider.getSessionDataDictionary(sessionID.getBeginString()), + is(notNullValue())); + assertThat(provider.getApplicationDataDictionary(new ApplVerID(ApplVerID.FIX42)), + is(notNullValue())); + } } @Test @@ -181,13 +190,15 @@ public void testIncorrectTimeValues() throws Exception { @Test public void testTestRequestDelayMultiplier() throws Exception { settings.setString(sessionID, Session.SETTING_TEST_REQUEST_DELAY_MULTIPLIER, "0.37"); - Session session = factory.create(sessionID, settings); - assertEquals(0.37, session.getTestRequestDelayMultiplier(), 0); + try (Session session = factory.create(sessionID, settings)) { + assertEquals(0.37, session.getTestRequestDelayMultiplier(), 0); + } } private void createSessionAndAssertConfigError(String message, String pattern) { + Session session = null; try { - factory.create(sessionID, settings); + session = factory.create(sessionID, settings); fail(message); } catch (ConfigError e) { if (pattern != null) { @@ -196,6 +207,14 @@ private void createSessionAndAssertConfigError(String message, String pattern) { assertTrue("exception message not matched, expected: " + pattern + ", got: " + e.getMessage(), m.matches()); } + } finally { + if (session != null) { + try { + session.close(); + } catch (IOException ex) { + // ignore + } + } } } @@ -214,7 +233,8 @@ private void setUpDefaultSettings(SessionID sessionID) { @Test public void testReconnectIntervalInDefaultSession() throws Exception { settings.setString(sessionID, "ReconnectInterval", "2x5;3x15"); - factory.create(sessionID, settings); + Session session = factory.create(sessionID, settings); + session.close(); } @Test diff --git a/quickfixj-core/src/test/java/quickfix/FileLogTest.java b/quickfixj-core/src/test/java/quickfix/FileLogTest.java index 109964b640..cf524424c0 100644 --- a/quickfixj-core/src/test/java/quickfix/FileLogTest.java +++ b/quickfixj-core/src/test/java/quickfix/FileLogTest.java @@ -202,14 +202,15 @@ public void testLogErrorWhenFilesystemRemoved() throws IOException { settings.setBool(sessionID, FileLogFactory.SETTING_INCLUDE_MILLIS_IN_TIMESTAMP, false); FileLogFactory factory = new FileLogFactory(settings); - Session session = new Session(new UnitTestApplication(), new MemoryStoreFactory(), + try (Session session = new Session(new UnitTestApplication(), new MemoryStoreFactory(), sessionID, new DefaultDataDictionaryProvider(), null, factory, - new DefaultMessageFactory(), 0); - Session.registerSession(session); - - FileLog log = (FileLog) session.getLog(); - log.close(); - log.logIncoming("test"); - // no stack overflow exception thrown + new DefaultMessageFactory(), 0)) { + Session.registerSession(session); + + FileLog log = (FileLog) session.getLog(); + log.close(); + log.logIncoming("test"); + // no stack overflow exception thrown + } } } diff --git a/quickfixj-core/src/test/java/quickfix/JdbcLogTest.java b/quickfixj-core/src/test/java/quickfix/JdbcLogTest.java index ec50a5da16..9c1d5147b2 100644 --- a/quickfixj-core/src/test/java/quickfix/JdbcLogTest.java +++ b/quickfixj-core/src/test/java/quickfix/JdbcLogTest.java @@ -26,14 +26,25 @@ import javax.sql.DataSource; -import junit.framework.TestCase; - -public class JdbcLogTest extends TestCase { +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import static junit.framework.TestCase.fail; +import org.junit.After; +import org.junit.Test; + +public class JdbcLogTest { private JdbcLog log; private JdbcLogFactory logFactory; private Connection connection; private SessionID sessionID; + @After + public void tearDown() { + Session.unregisterSession(sessionID, true); + } + + @Test public void testLog() throws Exception { doLogTest(null); } @@ -60,6 +71,7 @@ private void doLogTest(DataSource dataSource) throws ClassNotFoundException, SQL assertEquals(0, getRowCount(connection, "event_log")); } + @Test public void testLogWithHeartbeatFiltering() throws Exception { setUpJdbcLog(false, null); @@ -83,6 +95,7 @@ public void testLogWithHeartbeatFiltering() throws Exception { * (such as we can't connect ot the DB, or the tables are missing) and doesn't try * to print failing exceptions recursively until the stack overflows */ + @Test public void testHandlesRecursivelyFailingException() throws Exception { setUpJdbcLog(false, null); diff --git a/quickfixj-core/src/test/java/quickfix/SessionDisconnectConcurrentlyTest.java b/quickfixj-core/src/test/java/quickfix/SessionDisconnectConcurrentlyTest.java index 48cad91c51..ebebb55309 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionDisconnectConcurrentlyTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionDisconnectConcurrentlyTest.java @@ -258,51 +258,52 @@ public void onLogout(SessionID sessionId) { }; final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = new SessionFactoryTestSupport.Builder() + try (Session session = new SessionFactoryTestSupport.Builder() .setSessionId(sessionID) .setApplication(application) .setLogFactory(null) .setResetOnLogon(false) .setIsInitiator(true) - .build(); - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - session.addStateListener(responder); - session.logon(); - session.next(); - - final Message logonRequest = new Message(responder.sentMessageData); - - final Message logonResponse = new DefaultMessageFactory().create(sessionID.getBeginString(), MsgType.LOGON); - logonResponse.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); - logonResponse.setInt(HeartBtInt.FIELD, logonRequest.getInt(HeartBtInt.FIELD)); - - final Message.Header header = logonResponse.getHeader(); - header.setString(BeginString.FIELD, sessionID.getBeginString()); - header.setString(SenderCompID.FIELD, sessionID.getSenderCompID()); - header.setString(TargetCompID.FIELD, sessionID.getTargetCompID()); - header.setInt(MsgSeqNum.FIELD, 1); - header.setUtcTimeStamp(SendingTime.FIELD, SystemTime.getLocalDateTime(), true); - - final PausableThreadPoolExecutor ptpe = new PausableThreadPoolExecutor(); - ptpe.pause(); - - for (int j=0; j<1000; j++) { - final Thread thread = new Thread(() -> { - try { - session.disconnect("No reason", false); - } catch (IOException e) { - e.printStackTrace(); - } - }, "disconnectThread"+j); - thread.setDaemon(true); - ptpe.submit(thread); + .build()) { + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + session.addStateListener(responder); + session.logon(); + session.next(); + + final Message logonRequest = new Message(responder.sentMessageData); + + final Message logonResponse = new DefaultMessageFactory().create(sessionID.getBeginString(), MsgType.LOGON); + logonResponse.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); + logonResponse.setInt(HeartBtInt.FIELD, logonRequest.getInt(HeartBtInt.FIELD)); + + final Message.Header header = logonResponse.getHeader(); + header.setString(BeginString.FIELD, sessionID.getBeginString()); + header.setString(SenderCompID.FIELD, sessionID.getSenderCompID()); + header.setString(TargetCompID.FIELD, sessionID.getTargetCompID()); + header.setInt(MsgSeqNum.FIELD, 1); + header.setUtcTimeStamp(SendingTime.FIELD, SystemTime.getLocalDateTime(), true); + + final PausableThreadPoolExecutor ptpe = new PausableThreadPoolExecutor(); + ptpe.pause(); + + for (int j=0; j<1000; j++) { + final Thread thread = new Thread(() -> { + try { + session.disconnect("No reason", false); + } catch (IOException e) { + e.printStackTrace(); + } + }, "disconnectThread"+j); + thread.setDaemon(true); + ptpe.submit(thread); + } + + ptpe.resume(); + ptpe.awaitTermination(2, TimeUnit.SECONDS); + ptpe.shutdownNow(); + assertEquals(1, onLogoutCount.intValue()); } - - ptpe.resume(); - ptpe.awaitTermination(2, TimeUnit.SECONDS); - ptpe.shutdownNow(); - assertEquals(1, onLogoutCount.intValue()); } private class UnitTestResponder implements Responder, SessionStateListener { diff --git a/quickfixj-core/src/test/java/quickfix/SessionDisconnectTest.java b/quickfixj-core/src/test/java/quickfix/SessionDisconnectTest.java index 84acd529cc..41543d6ea6 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionDisconnectTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionDisconnectTest.java @@ -46,27 +46,26 @@ public void fromAdmin(final Message message, final SessionID sessionId) throws F super.fromAdmin(message, sessionId); } }; - final Session session = buildSession(application, storeMessageLatch, sentLogoutLatch); - - final MessageStore messageStore = session.getStore(); - checkNextSeqNums(messageStore, 1, 1); - - session.logon(); - - processOnSeparateThread(session::next); - assertTrue(String.format("Message not stored within %s secs", TIMEOUT_SECS), storeMessageLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS)); - assertEquals(1, application.lastToAdminMessage().getHeader().getField(new MsgSeqNum()).getValue()); - checkNextSeqNums(messageStore, 1, 1); - - processOnSeparateThread(() -> { - storeMessageLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS); - session.next(createLogonResponse()); - }); - assertTrue(String.format("Logon response not received within %s secs", TIMEOUT_SECS), receiveLogonResponseLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS)); - assertTrue(String.format("Logout/SequenceReset not sent %s secs", TIMEOUT_SECS * 2), sentLogoutLatch.await(TIMEOUT_SECS * 2, TimeUnit.SECONDS)); - checkNextSeqNums(messageStore, 2, 2); - - session.close(); + try (Session session = buildSession(application, storeMessageLatch, sentLogoutLatch)) { + + final MessageStore messageStore = session.getStore(); + checkNextSeqNums(messageStore, 1, 1); + + session.logon(); + + processOnSeparateThread(session::next); + assertTrue(String.format("Message not stored within %s secs", TIMEOUT_SECS), storeMessageLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS)); + assertEquals(1, application.lastToAdminMessage().getHeader().getField(new MsgSeqNum()).getValue()); + checkNextSeqNums(messageStore, 1, 1); + + processOnSeparateThread(() -> { + storeMessageLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS); + session.next(createLogonResponse()); + }); + assertTrue(String.format("Logon response not received within %s secs", TIMEOUT_SECS), receiveLogonResponseLatch.await(TIMEOUT_SECS, TimeUnit.SECONDS)); + assertTrue(String.format("Logout/SequenceReset not sent %s secs", TIMEOUT_SECS * 2), sentLogoutLatch.await(TIMEOUT_SECS * 2, TimeUnit.SECONDS)); + checkNextSeqNums(messageStore, 2, 2); + } } private void checkNextSeqNums(final MessageStore messageStore, final int nextTarget, final int nextSender) throws IOException { diff --git a/quickfixj-core/src/test/java/quickfix/SessionResetTest.java b/quickfixj-core/src/test/java/quickfix/SessionResetTest.java index 77c79b5375..f83cc71720 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionResetTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionResetTest.java @@ -32,59 +32,60 @@ public void testSessionResetDeadlock() throws Exception { final UnitTestApplication application = new UnitTestApplication(); final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = SessionFactoryTestSupport.createSession(sessionID, - application, true, false); - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - session.addStateListener(responder); - session.logon(); - session.next(); - - assertFalse(responder.onResetCalled); - - final Message logonRequest = new Message(responder.sentMessageData); - final Message logonResponse = new DefaultMessageFactory().create( - sessionID.getBeginString(), MsgType.LOGON); - logonResponse.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); - logonResponse.setInt(HeartBtInt.FIELD, logonRequest.getInt(HeartBtInt.FIELD)); - - final Message.Header header = logonResponse.getHeader(); - header.setString(BeginString.FIELD, sessionID.getBeginString()); - header.setString(SenderCompID.FIELD, sessionID.getSenderCompID()); - header.setString(TargetCompID.FIELD, sessionID.getTargetCompID()); - header.setInt(MsgSeqNum.FIELD, 1); - header.setUtcTimeStamp(SendingTime.FIELD, SystemTime.getLocalDateTime(), true); - - Thread resetThread = new Thread(() -> { - try { - session.reset(); - } catch (IOException e) { - e.printStackTrace(); - } - }, "SessionReset"); - resetThread.setDaemon(true); - - Thread messageSender = new Thread(() -> { - for (int i = 2; i <= NUMBER_OF_ADMIN_MESSAGES; i++) { - session.send(createAdminMessage(i)); - } - }, "SessionSend"); - messageSender.setDaemon(true); - - // submit threads to pausable executor and try to let them start at the same time - PausableThreadPoolExecutor ptpe = new PausableThreadPoolExecutor(); - ptpe.pause(); - ptpe.submit(messageSender); - ptpe.submit(resetThread); - ptpe.resume(); - ptpe.awaitTermination(2, TimeUnit.SECONDS); - - ThreadMXBean bean = ManagementFactory.getThreadMXBean(); - long[] threadIds = bean.findDeadlockedThreads(); - assertNull("no threads should be deadlocked", threadIds); - assertTrue("session should have been reset", responder.onResetCalled); - - ptpe.shutdownNow(); + try (Session session = SessionFactoryTestSupport.createSession(sessionID, + application, true, false)) { + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + session.addStateListener(responder); + session.logon(); + session.next(); + + assertFalse(responder.onResetCalled); + + final Message logonRequest = new Message(responder.sentMessageData); + final Message logonResponse = new DefaultMessageFactory().create( + sessionID.getBeginString(), MsgType.LOGON); + logonResponse.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); + logonResponse.setInt(HeartBtInt.FIELD, logonRequest.getInt(HeartBtInt.FIELD)); + + final Message.Header header = logonResponse.getHeader(); + header.setString(BeginString.FIELD, sessionID.getBeginString()); + header.setString(SenderCompID.FIELD, sessionID.getSenderCompID()); + header.setString(TargetCompID.FIELD, sessionID.getTargetCompID()); + header.setInt(MsgSeqNum.FIELD, 1); + header.setUtcTimeStamp(SendingTime.FIELD, SystemTime.getLocalDateTime(), true); + + Thread resetThread = new Thread(() -> { + try { + session.reset(); + } catch (IOException e) { + e.printStackTrace(); + } + }, "SessionReset"); + resetThread.setDaemon(true); + + Thread messageSender = new Thread(() -> { + for (int i = 2; i <= NUMBER_OF_ADMIN_MESSAGES; i++) { + session.send(createAdminMessage(i)); + } + }, "SessionSend"); + messageSender.setDaemon(true); + + // submit threads to pausable executor and try to let them start at the same time + PausableThreadPoolExecutor ptpe = new PausableThreadPoolExecutor(); + ptpe.pause(); + ptpe.submit(messageSender); + ptpe.submit(resetThread); + ptpe.resume(); + ptpe.awaitTermination(2, TimeUnit.SECONDS); + + ThreadMXBean bean = ManagementFactory.getThreadMXBean(); + long[] threadIds = bean.findDeadlockedThreads(); + assertNull("no threads should be deadlocked", threadIds); + assertTrue("session should have been reset", responder.onResetCalled); + + ptpe.shutdownNow(); + } } private Message createAdminMessage(int sequence) { diff --git a/quickfixj-core/src/test/java/quickfix/SessionTest.java b/quickfixj-core/src/test/java/quickfix/SessionTest.java index a6e6fe5c6d..9d9ded0358 100644 --- a/quickfixj-core/src/test/java/quickfix/SessionTest.java +++ b/quickfixj-core/src/test/java/quickfix/SessionTest.java @@ -53,6 +53,8 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; import static quickfix.SessionFactoryTestSupport.createSession; +import quickfix.field.CheckSum; +import quickfix.field.NextExpectedMsgSeqNum; /** * Note: most session tests are in the form of acceptance tests. @@ -80,17 +82,15 @@ public void testDisposalOfFileResources() throws Exception { final CloseableLog mockLog = mock(CloseableLog.class); stub(mockLogFactory.create(sessionID)).toReturn(mockLog); - final Session session = new Session(application, + try (Session session = new Session(application, mockMessageStoreFactory, sessionID, null, null, mockLogFactory, new DefaultMessageFactory(), 30, false, 30, UtcTimestampPrecision.MILLIS, true, false, false, false, false, false, true, false, 1.5, null, true, new int[] { 5 }, false, false, false, true, false, true, false, - null, true, 0, false, false); - - // Simulate socket disconnect - session.setResponder(null); - - session.close(); + null, true, 0, false, false)) { + // Simulate socket disconnect + session.setResponder(null); + } verify(mockMessageStore).close(); verifyNoMoreInteractions(mockMessageStore); @@ -123,22 +123,20 @@ public void testNondisposableFileResources() throws Exception { final Log mockLog = mock(Log.class); stub(mockLogFactory.create(sessionID)).toReturn(mockLog); - final Session session = new Session(application, + try (Session session = new Session(application, mockMessageStoreFactory, sessionID, null, null, mockLogFactory, new DefaultMessageFactory(), 30, false, 30, UtcTimestampPrecision.MILLIS, true, false, false, false, false, false, true, false, 1.5, null, true, new int[] { 5 }, false, false, false, true, false, true, false, - null, true, 0, false, false); - - // Simulate socket disconnect - session.setResponder(null); - - verifyNoMoreInteractions(mockMessageStore); - - verify(mockLog, atLeastOnce()).onEvent(anyString()); - verifyNoMoreInteractions(mockLog); - - session.close(); + null, true, 0, false, false)) { + // Simulate socket disconnect + session.setResponder(null); + + verifyNoMoreInteractions(mockMessageStore); + + verify(mockLog, atLeastOnce()).onEvent(anyString()); + verifyNoMoreInteractions(mockLog); + } } private interface CloseableMessageStore extends MessageStore, Closeable { @@ -154,38 +152,37 @@ public void testSessionWithoutValidateSequenceNumbers() throws Exception { final SessionID sessionID = new SessionID( FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = createSession(sessionID, application, true, - true, false); - - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - - final Message logonRequest = new Message(responder.sentMessageData); - session.next(createLogonResponse(sessionID, logonRequest, 1)); - - assertEquals( - 1, - application.lastToAdminMessage().getHeader() - .getInt(MsgSeqNum.FIELD)); - assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); - assertEquals(2, session.getStore().getNextSenderMsgSeqNum()); - - session.next(createHeartbeatMessage(1002)); - assertFalse(ResendRequest.MSGTYPE.equals(application - .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); - - session.next(createHeartbeatMessage(1003)); - assertFalse(ResendRequest.MSGTYPE.equals(application - .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); - - session.next(createHeartbeatMessage(1001)); - assertFalse(ResendRequest.MSGTYPE.equals(application - .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); - - session.close(); + try (Session session = createSession(sessionID, application, true, + true, false)) { + + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + + final Message logonRequest = new Message(responder.sentMessageData); + session.next(createLogonResponse(sessionID, logonRequest, 1)); + + assertEquals( + 1, + application.lastToAdminMessage().getHeader() + .getInt(MsgSeqNum.FIELD)); + assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); + assertEquals(2, session.getStore().getNextSenderMsgSeqNum()); + + session.next(createHeartbeatMessage(1002)); + assertFalse(ResendRequest.MSGTYPE.equals(application + .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); + + session.next(createHeartbeatMessage(1003)); + assertFalse(ResendRequest.MSGTYPE.equals(application + .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); + + session.next(createHeartbeatMessage(1001)); + assertFalse(ResendRequest.MSGTYPE.equals(application + .lastToAdminMessage().getHeader().getString(MsgType.FIELD))); + } } // QFJ-703 @@ -265,23 +262,22 @@ public void testInferResetSeqNumAcceptedWithNonInitialSequenceNumber() final SessionID sessionID = new SessionID( FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = createSession(sessionID, application, true, - true); - - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - - final Message logonRequest = new Message(responder.sentMessageData); - session.next(createLogonResponse(sessionID, logonRequest, 2)); - - assertTrue( - "Should not infer a reset when the sequence number is not one", - responder.disconnectCalled); - - session.close(); + try (Session session = createSession(sessionID, application, true, + true)) { + + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + + final Message logonRequest = new Message(responder.sentMessageData); + session.next(createLogonResponse(sessionID, logonRequest, 2)); + + assertTrue( + "Should not infer a reset when the sequence number is not one", + responder.disconnectCalled); + } } @Test @@ -291,24 +287,23 @@ public void testInferResetSeqNumAccepted() throws Exception { final SessionID sessionID = new SessionID( FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = createSession(sessionID, application, true, - true); - - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - - final Message logonRequest = new Message(responder.sentMessageData); - final Message logonResponse = createLogonResponse(sessionID, - logonRequest, 1); - session.next(logonResponse); - - assertFalse("Should not disconnect when an accepted reset is inferred", - responder.disconnectCalled); - - session.close(); + try (Session session = createSession(sessionID, application, true, + true)) { + + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + + final Message logonRequest = new Message(responder.sentMessageData); + final Message logonResponse = createLogonResponse(sessionID, + logonRequest, 1); + session.next(logonResponse); + + assertFalse("Should not disconnect when an accepted reset is inferred", + responder.disconnectCalled); + } } @Test @@ -318,34 +313,33 @@ public void testUnsupportedVersion() throws Exception { final UnitTestApplication application = new UnitTestApplication(); final SessionID sessionID = new SessionID( FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = createSession(sessionID, application, true, - true); - - final UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - - final Message logonRequest = new Message(responder.sentMessageData); - final Message logonResponse = createLogonResponse(sessionID, - logonRequest, 1); - session.next(logonResponse); - - final News newsMessage = createAppMessage(2); - // set a BeginString unsupported by the session - newsMessage.getHeader().setString(BeginString.FIELD, - FixVersions.BEGINSTRING_FIX40); - session.next(newsMessage); - final Message lastToAdminMessage = application.lastToAdminMessage(); - assertEquals(MsgType.LOGOUT, - lastToAdminMessage.getHeader().getString(MsgType.FIELD)); - assertEquals( - "Incorrect BeginString: Message version 'FIX.4.0' does not match the session version 'FIX.4.4'", - lastToAdminMessage.getString(Text.FIELD)); - assertTrue(responder.disconnectCalled); - - session.close(); + try (Session session = createSession(sessionID, application, true, + true)) { + + final UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + + final Message logonRequest = new Message(responder.sentMessageData); + final Message logonResponse = createLogonResponse(sessionID, + logonRequest, 1); + session.next(logonResponse); + + final News newsMessage = createAppMessage(2); + // set a BeginString unsupported by the session + newsMessage.getHeader().setString(BeginString.FIELD, + FixVersions.BEGINSTRING_FIX40); + session.next(newsMessage); + final Message lastToAdminMessage = application.lastToAdminMessage(); + assertEquals(MsgType.LOGOUT, + lastToAdminMessage.getHeader().getString(MsgType.FIELD)); + assertEquals( + "Incorrect BeginString: Message version 'FIX.4.0' does not match the session version 'FIX.4.4'", + lastToAdminMessage.getString(Text.FIELD)); + assertTrue(responder.disconnectCalled); + } } // QFJ-650 @@ -353,39 +347,38 @@ public void testUnsupportedVersion() throws Exception { public void testLogoutOnMissingMsgSeqNum() throws Exception { final Application application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - final TestRequest testRequest = (TestRequest) createAdminMessage(2); - session.next(testRequest); - - assertEquals(3, state.getNextSenderMsgSeqNum()); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - testRequest.getHeader().removeField(MsgSeqNum.FIELD); - // this should disconnect the session due to the missing MsgSeqNum - session.next(testRequest); - assertFalse("Session should be disconnected", session.isLoggedOn()); - - // make sure that the target seq num has not been incremented - assertEquals(4, state.getNextSenderMsgSeqNum()); - assertEquals(3, state.getNextTargetMsgSeqNum()); - session.setResponder(new UnitTestResponder()); - logonTo(session, 3); - assertEquals(5, state.getNextSenderMsgSeqNum()); - assertEquals(4, state.getNextTargetMsgSeqNum()); - assertTrue("Session should be connected", session.isLoggedOn()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + final TestRequest testRequest = (TestRequest) createAdminMessage(2); + session.next(testRequest); + + assertEquals(3, state.getNextSenderMsgSeqNum()); + assertEquals(3, state.getNextTargetMsgSeqNum()); + + testRequest.getHeader().removeField(MsgSeqNum.FIELD); + // this should disconnect the session due to the missing MsgSeqNum + session.next(testRequest); + assertFalse("Session should be disconnected", session.isLoggedOn()); + + // make sure that the target seq num has not been incremented + assertEquals(4, state.getNextSenderMsgSeqNum()); + assertEquals(3, state.getNextTargetMsgSeqNum()); + session.setResponder(new UnitTestResponder()); + logonTo(session, 3); + assertEquals(5, state.getNextSenderMsgSeqNum()); + assertEquals(4, state.getNextTargetMsgSeqNum()); + assertTrue("Session should be connected", session.isLoggedOn()); + } } // QFJ-750 @@ -393,72 +386,70 @@ public void testLogoutOnMissingMsgSeqNum() throws Exception { public void testLogoutMsgSeqNumTooHighOrLow() throws Exception { final Application application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - final TestRequest testRequest = (TestRequest) createAdminMessage(2); - session.next(testRequest); - - assertEquals(3, state.getNextSenderMsgSeqNum()); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - logoutFrom(session, 100); - assertFalse("Session should be disconnected", session.isLoggedOn()); - - // make sure that the target seq num has not been incremented - assertEquals(4, state.getNextSenderMsgSeqNum()); - assertEquals(3, state.getNextTargetMsgSeqNum()); - session.setResponder(new UnitTestResponder()); - logonTo(session, 3); - assertEquals(5, state.getNextSenderMsgSeqNum()); - assertEquals(4, state.getNextTargetMsgSeqNum()); - assertTrue("Session should be connected", session.isLoggedOn()); - - logoutFrom(session, 1); - // make sure that the target seq num has not been incremented - assertEquals(6, state.getNextSenderMsgSeqNum()); - assertEquals(4, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + final TestRequest testRequest = (TestRequest) createAdminMessage(2); + session.next(testRequest); + + assertEquals(3, state.getNextSenderMsgSeqNum()); + assertEquals(3, state.getNextTargetMsgSeqNum()); + + logoutFrom(session, 100); + assertFalse("Session should be disconnected", session.isLoggedOn()); + + // make sure that the target seq num has not been incremented + assertEquals(4, state.getNextSenderMsgSeqNum()); + assertEquals(3, state.getNextTargetMsgSeqNum()); + session.setResponder(new UnitTestResponder()); + logonTo(session, 3); + assertEquals(5, state.getNextSenderMsgSeqNum()); + assertEquals(4, state.getNextTargetMsgSeqNum()); + assertTrue("Session should be connected", session.isLoggedOn()); + + logoutFrom(session, 1); + // make sure that the target seq num has not been incremented + assertEquals(6, state.getNextSenderMsgSeqNum()); + assertEquals(4, state.getNextTargetMsgSeqNum()); + } } @Test public void testRejectMsgSeqNumTooHighOrLow() throws Exception { final Application application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - processMessage(session, createReject(2, 100)); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - // Reject with unexpected seqnum should not increment target seqnum - processMessage(session, createReject(50, 100)); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - // Reject with unexpected seqnum should not increment target seqnum - processMessage(session, createReject(1, 100)); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + processMessage(session, createReject(2, 100)); + assertEquals(3, state.getNextTargetMsgSeqNum()); + + // Reject with unexpected seqnum should not increment target seqnum + processMessage(session, createReject(50, 100)); + assertEquals(3, state.getNextTargetMsgSeqNum()); + + // Reject with unexpected seqnum should not increment target seqnum + processMessage(session, createReject(1, 100)); + assertEquals(3, state.getNextTargetMsgSeqNum()); + } } /** @@ -481,28 +472,27 @@ public void testLogonIsFirstMessageOnAcceptor() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpFileStoreSession(application, false, - new UnitTestResponder(), settings, sessionID); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - // we should only answer with a Logon message - assertEquals(1, application.toAdminMessages.size()); - assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) - .getHeader().getString(MsgType.FIELD)); - - // no reset should have been triggered by QF/J after the Logon attempt - assertEquals(0, application.sessionResets); - assertTrue("Session should be connected", session.isLoggedOn()); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpFileStoreSession(application, false, + new UnitTestResponder(), settings, sessionID)) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + // we should only answer with a Logon message + assertEquals(1, application.toAdminMessages.size()); + assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) + .getHeader().getString(MsgType.FIELD)); + + // no reset should have been triggered by QF/J after the Logon attempt + assertEquals(0, application.sessionResets); + assertTrue("Session should be connected", session.isLoggedOn()); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + } } // QFJ-773 @@ -526,76 +516,75 @@ public void testLogonLogoutOnAcceptor() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); final UnitTestResponder responder = new UnitTestResponder(); - final Session session = setUpFileStoreSession(application, false, - responder, settings, sessionID); - session.addStateListener(application); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - // we should only answer with a Logon message - assertEquals(1, application.toAdminMessages.size()); - assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) - .getHeader().getString(MsgType.FIELD)); - - // no reset should have been triggered by QF/J after the Logon attempt - assertEquals(0, application.sessionResets); - assertTrue("Session should be connected", session.isLoggedOn()); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - session.next(); - // increment time to force logout and reset - systemTimeSource.increment(3700000); - session.next(); - assertEquals(SystemTime.getDate(), state.getCreationTime()); - systemTimeSource.increment(10000); - session.next(); - systemTimeSource.increment(10000); - session.next(); - systemTimeSource.increment(10000); - session.next(); - systemTimeSource.increment(10000); - - // we should only reset once outside of the session time window - assertEquals(1, application.sessionResets); - assertFalse("Session should be disconnected", session.isLoggedOn()); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.setResponder(responder); - // this should get rejected since we are outside of the session time - // window - logonTo(session); - assertFalse("Session should be disconnected", session.isLoggedOn()); - - // if we now logon to the session, it will be considered new - // and a reset will be done - session.setResponder(responder); - session.next(); - assertEquals(2, application.sessionResets); - systemTimeSource.increment(86100000); // jump one day but stay inside - // session time - session.next(); - logonTo(session); - assertTrue("Session should be connected", session.isLoggedOn()); - assertEquals(SystemTime.getDate(), state.getCreationTime()); - - // check that the creation time is not updated inside of the session - // time window - int delta = 60000; - systemTimeSource.increment(delta); - assertTrue(SystemTime.getDate().getTime() - - state.getCreationTime().getTime() == delta); - session.next(); - assertTrue("Session should be connected", session.isLoggedOn()); - - session.close(); + try (Session session = setUpFileStoreSession(application, false, + responder, settings, sessionID)) { + session.addStateListener(application); + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + // we should only answer with a Logon message + assertEquals(1, application.toAdminMessages.size()); + assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) + .getHeader().getString(MsgType.FIELD)); + + // no reset should have been triggered by QF/J after the Logon attempt + assertEquals(0, application.sessionResets); + assertTrue("Session should be connected", session.isLoggedOn()); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + session.next(); + // increment time to force logout and reset + systemTimeSource.increment(3700000); + session.next(); + assertEquals(SystemTime.getDate(), state.getCreationTime()); + systemTimeSource.increment(10000); + session.next(); + systemTimeSource.increment(10000); + session.next(); + systemTimeSource.increment(10000); + session.next(); + systemTimeSource.increment(10000); + + // we should only reset once outside of the session time window + assertEquals(1, application.sessionResets); + assertFalse("Session should be disconnected", session.isLoggedOn()); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + session.setResponder(responder); + // this should get rejected since we are outside of the session time + // window + logonTo(session); + assertFalse("Session should be disconnected", session.isLoggedOn()); + + // if we now logon to the session, it will be considered new + // and a reset will be done + session.setResponder(responder); + session.next(); + assertEquals(2, application.sessionResets); + systemTimeSource.increment(86100000); // jump one day but stay inside + // session time + session.next(); + logonTo(session); + assertTrue("Session should be connected", session.isLoggedOn()); + assertEquals(SystemTime.getDate(), state.getCreationTime()); + + // check that the creation time is not updated inside of the session + // time window + int delta = 60000; + systemTimeSource.increment(delta); + assertTrue(SystemTime.getDate().getTime() + - state.getCreationTime().getTime() == delta); + session.next(); + assertTrue("Session should be connected", session.isLoggedOn()); + } } @Test @@ -618,56 +607,55 @@ public void testStartOfInitiatorOutsideOfSessionTime() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpFileStoreSession(application, true, - new UnitTestResponder(), settings, sessionID); - session.addStateListener(application); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.next(); - systemTimeSource.increment(10000); - session.next(); - systemTimeSource.increment(10000); - session.next(); - - // we should send no messages since we are outside of session time - assertEquals(0, application.toAdminMessages.size()); - // no reset should have been triggered by QF/J (since we were not logged - // on) - assertEquals(0, application.sessionResets); - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - // increase time to be within session time - systemTimeSource.increment(1900000); - session.next(); - session.next(); - // we should have sent a Logon since the StartTime has been reached now - assertEquals(1, application.toAdminMessages.size()); - Message logon = application.toAdminMessages.get(0); - assertEquals(MsgType.LOGON, logon.getHeader().getString(MsgType.FIELD)); - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - Message createLogonResponse = createLogonResponse(new SessionID( - FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), logon, 1); - session.next(createLogonResponse); - assertTrue(session.isLoggedOn()); - assertEquals(1, application.sessionResets); - - // increase time to be out of session time - systemTimeSource.increment(1900000); - session.next(); - Message logout = application.lastToAdminMessage(); - assertEquals(MsgType.LOGOUT, logout.getHeader() - .getString(MsgType.FIELD)); - assertFalse(session.isLoggedOn()); - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - assertEquals(2, application.sessionResets); - - session.close(); + try (Session session = setUpFileStoreSession(application, true, + new UnitTestResponder(), settings, sessionID)) { + session.addStateListener(application); + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + session.next(); + systemTimeSource.increment(10000); + session.next(); + systemTimeSource.increment(10000); + session.next(); + + // we should send no messages since we are outside of session time + assertEquals(0, application.toAdminMessages.size()); + // no reset should have been triggered by QF/J (since we were not logged + // on) + assertEquals(0, application.sessionResets); + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + // increase time to be within session time + systemTimeSource.increment(1900000); + session.next(); + session.next(); + // we should have sent a Logon since the StartTime has been reached now + assertEquals(1, application.toAdminMessages.size()); + Message logon = application.toAdminMessages.get(0); + assertEquals(MsgType.LOGON, logon.getHeader().getString(MsgType.FIELD)); + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + Message createLogonResponse = createLogonResponse(new SessionID( + FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), logon, 1); + session.next(createLogonResponse); + assertTrue(session.isLoggedOn()); + assertEquals(1, application.sessionResets); + + // increase time to be out of session time + systemTimeSource.increment(1900000); + session.next(); + Message logout = application.lastToAdminMessage(); + assertEquals(MsgType.LOGOUT, logout.getHeader() + .getString(MsgType.FIELD)); + assertFalse(session.isLoggedOn()); + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + assertEquals(2, application.sessionResets); + } } @Test @@ -692,30 +680,29 @@ public void testStartOfInitiatorInsideOfSessionTime() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpFileStoreSession(application, true, - new UnitTestResponder(), settings, sessionID); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.next(); - systemTimeSource.increment(1000); - session.next(); - systemTimeSource.increment(1000); - session.next(); - - // we should have sent a Logon since we are inside of the SessionTime - assertEquals(1, application.toAdminMessages.size()); - assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) - .getHeader().getString(MsgType.FIELD)); - // no reset should have been triggered by QF/J - assertEquals(0, application.sessionResets); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpFileStoreSession(application, true, + new UnitTestResponder(), settings, sessionID)) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + session.next(); + systemTimeSource.increment(1000); + session.next(); + systemTimeSource.increment(1000); + session.next(); + + // we should have sent a Logon since we are inside of the SessionTime + assertEquals(1, application.toAdminMessages.size()); + assertEquals(MsgType.LOGON, application.toAdminMessages.get(0) + .getHeader().getString(MsgType.FIELD)); + // no reset should have been triggered by QF/J + assertEquals(0, application.sessionResets); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + } } @Test @@ -740,48 +727,47 @@ public void testSessionNotResetRightAfterLogonOnAcceptor() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpFileStoreSession(application, false, - new UnitTestResponder(), settings, sessionID); - session.addStateListener(application); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.next(); - - // we should send no messages since we are outside of session time - assertEquals(0, application.toAdminMessages.size()); - // no reset should have been triggered by QF/J (since we were not logged on) - assertEquals(0, application.sessionResets); - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - // increase time to be within session time - systemTimeSource.increment(5000); - // there should be a Logon but no subsequent reset - logonTo(session, 1); - // call next() to provoke SessionTime check which should NOT reset seqnums now - session.next(); - assertEquals(1, application.toAdminMessages.size()); - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - assertTrue(session.isLoggedOn()); - assertEquals(1, application.sessionResets); - - systemTimeSource.increment(5000); - session.disconnect("test", false); - systemTimeSource.increment(5000); - session.next(); - session.setResponder(new UnitTestResponder()); - - logonTo(session, 2); - session.next(); - - // check that no reset is done on next Logon - assertEquals(1, application.sessionResets); - - session.close(); + try (Session session = setUpFileStoreSession(application, false, + new UnitTestResponder(), settings, sessionID)) { + session.addStateListener(application); + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + session.next(); + + // we should send no messages since we are outside of session time + assertEquals(0, application.toAdminMessages.size()); + // no reset should have been triggered by QF/J (since we were not logged on) + assertEquals(0, application.sessionResets); + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + // increase time to be within session time + systemTimeSource.increment(5000); + // there should be a Logon but no subsequent reset + logonTo(session, 1); + // call next() to provoke SessionTime check which should NOT reset seqnums now + session.next(); + assertEquals(1, application.toAdminMessages.size()); + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + assertTrue(session.isLoggedOn()); + assertEquals(1, application.sessionResets); + + systemTimeSource.increment(5000); + session.disconnect("test", false); + systemTimeSource.increment(5000); + session.next(); + session.setResponder(new UnitTestResponder()); + + logonTo(session, 2); + session.next(); + + // check that no reset is done on next Logon + assertEquals(1, application.sessionResets); + } } @Test @@ -807,51 +793,50 @@ public void testSessionNotResetRightAfterLogonOnInitiator() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); UnitTestResponder responder = new UnitTestResponder(); - final Session session = setUpFileStoreSession(application, true, responder, settings, sessionID); - session.addStateListener(application); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.next(); - - // we should send no messages since we are outside of session time - assertEquals(0, application.toAdminMessages.size()); - // no reset should have been triggered by QF/J (since we were not logged on) - assertEquals(0, application.sessionResets); - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - // increase time to be almost within session time to check if session needs to be reset - // (will not reset since it is not yet within session time) - systemTimeSource.increment(4500); - session.next(); - // increase time further so that Logon is sent but reset is not done since last check - // of session time was done within one second - systemTimeSource.increment(600); - session.next(); - systemTimeSource.increment(1000); - session.next(createLogonResponse(new SessionID(FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), application.lastToAdminMessage(), 1)); - assertEquals(1, application.toAdminMessages.size()); - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - assertTrue(session.isLoggedOn()); - assertEquals(1, application.sessionResets); - - systemTimeSource.increment(5000); - session.disconnect("test", false); - systemTimeSource.increment(5000); - session.next(); - responder = new UnitTestResponder(); - session.setResponder(responder); - - session.next(); - session.next(createLogonResponse(new SessionID(FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), application.lastToAdminMessage(), 2)); - // check that no reset is done on next Logon - assertEquals(1, application.sessionResets); - - session.close(); + try (Session session = setUpFileStoreSession(application, true, responder, settings, sessionID)) { + session.addStateListener(application); + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + session.next(); + + // we should send no messages since we are outside of session time + assertEquals(0, application.toAdminMessages.size()); + // no reset should have been triggered by QF/J (since we were not logged on) + assertEquals(0, application.sessionResets); + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + // increase time to be almost within session time to check if session needs to be reset + // (will not reset since it is not yet within session time) + systemTimeSource.increment(4500); + session.next(); + // increase time further so that Logon is sent but reset is not done since last check + // of session time was done within one second + systemTimeSource.increment(600); + session.next(); + systemTimeSource.increment(1000); + session.next(createLogonResponse(new SessionID(FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), application.lastToAdminMessage(), 1)); + assertEquals(1, application.toAdminMessages.size()); + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + assertTrue(session.isLoggedOn()); + assertEquals(1, application.sessionResets); + + systemTimeSource.increment(5000); + session.disconnect("test", false); + systemTimeSource.increment(5000); + session.next(); + responder = new UnitTestResponder(); + session.setResponder(responder); + + session.next(); + session.next(createLogonResponse(new SessionID(FixVersions.BEGINSTRING_FIX44, "TARGET", "SENDER"), application.lastToAdminMessage(), 2)); + // check that no reset is done on next Logon + assertEquals(1, application.sessionResets); + } } @Test @@ -861,73 +846,72 @@ public void testLogonIsAnsweredWithLogoutOnException() throws Exception { final SessionID sessionID = new SessionID( FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); UnitTestApplication application = new UnitTestApplication(); - Session session = SessionFactoryTestSupport.createSession(sessionID, application, - false, false, true, true, null); - UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - session.logon(); - - session.next(); - Logon logonRequest = new Logon(); - setUpHeader(session.getSessionID(), logonRequest, true, 1); - logonRequest.setInt(HeartBtInt.FIELD, 30); - logonRequest.setString(EncryptMethod.FIELD, ""); - logonRequest.toString(); // calculate length and checksum - session.next(logonRequest); - // session should not be logged on due to empty EncryptMethod - assertFalse(session.isLoggedOn()); - - assertEquals(1, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); - assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); - assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); - assertEquals(2, session.getStore().getNextSenderMsgSeqNum()); - - session.setResponder(responder); - session.logon(); - session.next(); - setUpHeader(session.getSessionID(), logonRequest, true, 2); - logonRequest.removeField(EncryptMethod.FIELD); - logonRequest.toString(); // calculate length and checksum - session.next(logonRequest); - // session should not be logged on due to missing EncryptMethod - assertFalse(session.isLoggedOn()); - - assertEquals(2, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); - assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); - assertEquals(3, session.getStore().getNextTargetMsgSeqNum()); - assertEquals(3, session.getStore().getNextSenderMsgSeqNum()); - - session.setResponder(responder); - session.logon(); - session.next(); - setUpHeader(session.getSessionID(), logonRequest, true, 3); - logonRequest.setString(EncryptMethod.FIELD, "A"); - logonRequest.toString(); // calculate length and checksum - session.next(logonRequest); - // session should not be logged on due to IncorrectDataFormat - assertFalse(session.isLoggedOn()); - - assertEquals(3, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); - assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); - assertEquals(4, session.getStore().getNextTargetMsgSeqNum()); - assertEquals(4, session.getStore().getNextSenderMsgSeqNum()); - - session.setResponder(responder); - session.logon(); - session.next(); - setUpHeader(session.getSessionID(), logonRequest, true, 3); - logonRequest.setString(EncryptMethod.FIELD, "99"); - logonRequest.toString(); // calculate length and checksum - session.next(logonRequest); - // session should not be logged on due to IncorrectTagValue - assertFalse(session.isLoggedOn()); - - assertEquals(4, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); - assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); - assertEquals(5, session.getStore().getNextTargetMsgSeqNum()); - assertEquals(5, session.getStore().getNextSenderMsgSeqNum()); - - session.close(); + try (Session session = SessionFactoryTestSupport.createSession(sessionID, application, + false, false, true, true, null)) { + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + session.logon(); + + session.next(); + Logon logonRequest = new Logon(); + setUpHeader(session.getSessionID(), logonRequest, true, 1); + logonRequest.setInt(HeartBtInt.FIELD, 30); + logonRequest.setString(EncryptMethod.FIELD, ""); + logonRequest.toString(); // calculate length and checksum + session.next(logonRequest); + // session should not be logged on due to empty EncryptMethod + assertFalse(session.isLoggedOn()); + + assertEquals(1, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); + assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); + assertEquals(2, session.getStore().getNextSenderMsgSeqNum()); + + session.setResponder(responder); + session.logon(); + session.next(); + setUpHeader(session.getSessionID(), logonRequest, true, 2); + logonRequest.removeField(EncryptMethod.FIELD); + logonRequest.toString(); // calculate length and checksum + session.next(logonRequest); + // session should not be logged on due to missing EncryptMethod + assertFalse(session.isLoggedOn()); + + assertEquals(2, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); + assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(3, session.getStore().getNextTargetMsgSeqNum()); + assertEquals(3, session.getStore().getNextSenderMsgSeqNum()); + + session.setResponder(responder); + session.logon(); + session.next(); + setUpHeader(session.getSessionID(), logonRequest, true, 3); + logonRequest.setString(EncryptMethod.FIELD, "A"); + logonRequest.toString(); // calculate length and checksum + session.next(logonRequest); + // session should not be logged on due to IncorrectDataFormat + assertFalse(session.isLoggedOn()); + + assertEquals(3, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); + assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(4, session.getStore().getNextTargetMsgSeqNum()); + assertEquals(4, session.getStore().getNextSenderMsgSeqNum()); + + session.setResponder(responder); + session.logon(); + session.next(); + setUpHeader(session.getSessionID(), logonRequest, true, 3); + logonRequest.setString(EncryptMethod.FIELD, "99"); + logonRequest.toString(); // calculate length and checksum + session.next(logonRequest); + // session should not be logged on due to IncorrectTagValue + assertFalse(session.isLoggedOn()); + + assertEquals(4, application.lastToAdminMessage().getHeader().getInt(MsgSeqNum.FIELD)); + assertEquals(MsgType.LOGOUT, application.lastToAdminMessage().getHeader().getString(MsgType.FIELD)); + assertEquals(5, session.getStore().getNextTargetMsgSeqNum()); + assertEquals(5, session.getStore().getNextSenderMsgSeqNum()); + } } /** @@ -956,31 +940,30 @@ public void testLogonOutsideSessionTimeIsRejected() throws Exception { // Session gets constructed, triggering a reset final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpFileStoreSession(application, false, - new UnitTestResponder(), settings, sessionID); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - // we should only answer with a Logout message - assertEquals(1, application.toAdminMessages.size()); - assertEquals(MsgType.LOGOUT, application.toAdminMessages.get(0) - .getHeader().getString(MsgType.FIELD)); - assertFalse("Session should not be connected", session.isLoggedOn()); - assertTrue(application.toAdminMessages.get(0).getString(Text.FIELD) - .contains("Logon attempt not within session time")); - // Normally, next() is called periodically; we only do it here to reset - // the seqNums. - // The seqNums should be reset because it was tried to establish a - // connection - // outside of the session schedule. - session.next(); - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpFileStoreSession(application, false, + new UnitTestResponder(), settings, sessionID)) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + // we should only answer with a Logout message + assertEquals(1, application.toAdminMessages.size()); + assertEquals(MsgType.LOGOUT, application.toAdminMessages.get(0) + .getHeader().getString(MsgType.FIELD)); + assertFalse("Session should not be connected", session.isLoggedOn()); + assertTrue(application.toAdminMessages.get(0).getString(Text.FIELD) + .contains("Logon attempt not within session time")); + // Normally, next() is called periodically; we only do it here to reset + // the seqNums. + // The seqNums should be reset because it was tried to establish a + // connection + // outside of the session schedule. + session.next(); + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + } } // QFJ-357 @@ -1035,36 +1018,35 @@ public void testRejectLogon() throws Exception { final Application application = new UnitTestApplication() { @Override - public void fromAdmin(Message message, SessionID sessionId) - throws FieldNotFound, IncorrectDataFormat, - IncorrectTagValue, RejectLogon { - super.fromAdmin(message, sessionId); - throw new RejectLogon("FOR TEST"); - } - }; - - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - assertEquals(1, state.getNextSenderMsgSeqNum()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - - logonTo(session); - - assertEquals(false, state.isLogonSent()); - assertEquals(false, state.isLogonReceived()); - assertEquals(false, state.isLogonAlreadySent()); - assertEquals(false, state.isLogonSendNeeded()); - assertEquals(false, state.isLogonTimedOut()); - assertEquals(false, state.isLogoutSent()); - assertEquals(false, state.isLogoutReceived()); - assertEquals(false, state.isLogoutTimedOut()); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); + public void fromAdmin(Message message, SessionID sessionId) + throws FieldNotFound, IncorrectDataFormat, + IncorrectTagValue, RejectLogon { + super.fromAdmin(message, sessionId); + throw new RejectLogon("FOR TEST"); + } + }; - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + assertEquals(1, state.getNextSenderMsgSeqNum()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + + logonTo(session); + + assertEquals(false, state.isLogonSent()); + assertEquals(false, state.isLogonReceived()); + assertEquals(false, state.isLogonAlreadySent()); + assertEquals(false, state.isLogonSendNeeded()); + assertEquals(false, state.isLogonTimedOut()); + assertEquals(false, state.isLogoutSent()); + assertEquals(false, state.isLogoutReceived()); + assertEquals(false, state.isLogoutTimedOut()); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + } } // QFJ-696 @@ -1107,49 +1089,47 @@ public void fromAdmin(Message message, SessionID sessionId) @Test // QFJ-339 public void testSendingTimeRejectBeforeLogon() throws Exception { - final Session session = setUpSession(new UnitTestApplication(), false, - new UnitTestResponder()); - - final Message message = new Logon(); - message.getHeader().setString(SenderCompID.FIELD, "SENDER"); - message.getHeader().setString(TargetCompID.FIELD, "TARGET"); - message.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(LocalDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); - message.getHeader().setInt(MsgSeqNum.FIELD, 1); - - final SessionStateListener mockStateListener = mock(SessionStateListener.class); - session.addStateListener(mockStateListener); - - session.next(message); - - verify(mockStateListener).onDisconnect(); - verifyNoMoreInteractions(mockStateListener); - - session.close(); + try (Session session = setUpSession(new UnitTestApplication(), false, + new UnitTestResponder())) { + + final Message message = new Logon(); + message.getHeader().setString(SenderCompID.FIELD, "SENDER"); + message.getHeader().setString(TargetCompID.FIELD, "TARGET"); + message.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(LocalDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); + message.getHeader().setInt(MsgSeqNum.FIELD, 1); + + final SessionStateListener mockStateListener = mock(SessionStateListener.class); + session.addStateListener(mockStateListener); + + session.next(message); + + verify(mockStateListener).onDisconnect(); + verifyNoMoreInteractions(mockStateListener); + } } @Test // QFJ-339 public void testCorruptLogonReject() throws Exception { - final Session session = setUpSession(new UnitTestApplication(), false, - new UnitTestResponder()); - - final Message message = new Logon(); - message.getHeader().setString(SenderCompID.FIELD, "SENDER"); - message.getHeader().setString(TargetCompID.FIELD, "TARGET"); - message.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); - message.getHeader().setInt(MsgSeqNum.FIELD, 100); - - final SessionStateListener mockStateListener = mock(SessionStateListener.class); - session.addStateListener(mockStateListener); - - session.next(message); - - verify(mockStateListener).onDisconnect(); - verifyNoMoreInteractions(mockStateListener); - - session.close(); + try (Session session = setUpSession(new UnitTestApplication(), false, + new UnitTestResponder())) { + + final Message message = new Logon(); + message.getHeader().setString(SenderCompID.FIELD, "SENDER"); + message.getHeader().setString(TargetCompID.FIELD, "TARGET"); + message.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); + message.getHeader().setInt(MsgSeqNum.FIELD, 100); + + final SessionStateListener mockStateListener = mock(SessionStateListener.class); + session.addStateListener(mockStateListener); + + session.next(message); + + verify(mockStateListener).onDisconnect(); + verifyNoMoreInteractions(mockStateListener); + } } @Test @@ -1179,28 +1159,27 @@ public void fromAdmin(Message message, SessionID sessionId) } }; - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - logonTo(session); - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - processMessage(session, createAppMessage(2)); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - // To avoid resendRequest - state.setNextTargetMsgSeqNum(3); - - processMessage(session, createAdminMessage(3)); - - assertEquals(2, state.getNextSenderMsgSeqNum()); - assertEquals(3, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + logonTo(session); + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + processMessage(session, createAppMessage(2)); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + // To avoid resendRequest + state.setNextTargetMsgSeqNum(3); + + processMessage(session, createAdminMessage(3)); + + assertEquals(2, state.getNextSenderMsgSeqNum()); + assertEquals(3, state.getNextTargetMsgSeqNum()); + } } // QFJ-271 @@ -1208,35 +1187,34 @@ public void fromAdmin(Message message, SessionID sessionId) public void testSequenceResetStackOverflow() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - logonTo(session, 1); - - assertTrue(session.isLoggedOn()); - assertEquals(2, state.getNextTargetMsgSeqNum()); - - for (int i = 2; i <= 41; i++) { - processMessage(session, createAppMessage(i)); - } - assertEquals(42, state.getNextTargetMsgSeqNum()); - - processMessage(session, createAppMessage(50)); - processMessage(session, createSequenceReset(51, 51, true)); - - for (int i = 42; i <= 49; i++) { - processMessage(session, createAppMessage(i)); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + logonTo(session, 1); + + assertTrue(session.isLoggedOn()); + assertEquals(2, state.getNextTargetMsgSeqNum()); + + for (int i = 2; i <= 41; i++) { + processMessage(session, createAppMessage(i)); + } + assertEquals(42, state.getNextTargetMsgSeqNum()); + + processMessage(session, createAppMessage(50)); + processMessage(session, createSequenceReset(51, 51, true)); + + for (int i = 42; i <= 49; i++) { + processMessage(session, createAppMessage(i)); + } + + assertEquals(51, state.getNextTargetMsgSeqNum()); + processMessage(session, createHeartbeatMessage(51)); + assertEquals(52, state.getNextTargetMsgSeqNum()); + assertTrue(session.isLoggedOn()); + assertFalse(state.isResendRequested()); + assertTrue(state.getQueuedSeqNums().isEmpty()); } - - assertEquals(51, state.getNextTargetMsgSeqNum()); - processMessage(session, createHeartbeatMessage(51)); - assertEquals(52, state.getNextTargetMsgSeqNum()); - assertTrue(session.isLoggedOn()); - assertFalse(state.isResendRequested()); - assertTrue(state.getQueuedSeqNums().isEmpty()); - - session.close(); } // QFJ-626 @@ -1245,45 +1223,44 @@ public void testResendMessagesWithIncorrectChecksum() throws Exception { final UnitTestApplication application = new UnitTestApplication(); final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET"); - final Session session = SessionFactoryTestSupport.createSession(sessionID, application, false, false, true, true, null); - UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - final SessionState state = getSessionState(session); - - assertTrue(session.isUsingDataDictionary()); - - final Logon logonToSend = new Logon(); - setUpHeader(session.getSessionID(), logonToSend, true, 1); - logonToSend.setInt(HeartBtInt.FIELD, 30); - logonToSend.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); - logonToSend.toString(); // calculate length/checksum - session.next(logonToSend); - - session.send(createAppMessage(2)); - final News createAppMessage = createAppMessage(3); - createAppMessage.setString(11, "ÄÖÜäöü?ß"); - session.send(createAppMessage); - session.send(createAppMessage(4)); - session.send(createAppMessage(5)); - - // ugly hack: alter the store to get an invalid checksum - String toString = createAppMessage.toString(); - final String replace = toString.replace("10=", "10=1"); - state.set(3, replace); - - Message createResendRequest = createResendRequest(2, 1); - createResendRequest.toString(); // calculate length/checksum - processMessage(session, createResendRequest); - - Message createAdminMessage = createAdminMessage(3); - createAdminMessage.toString(); // calculate length/checksum - session.next(createAdminMessage); - - // all messages should have been resent - assertEquals(5, application.lastToAppMessage().header.getInt(MsgSeqNum.FIELD)); - assertFalse(state.isResendRequested()); - - session.close(); + try (Session session = SessionFactoryTestSupport.createSession(sessionID, application, false, false, true, true, null)) { + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + final SessionState state = getSessionState(session); + + assertTrue(session.isUsingDataDictionary()); + + final Logon logonToSend = new Logon(); + setUpHeader(session.getSessionID(), logonToSend, true, 1); + logonToSend.setInt(HeartBtInt.FIELD, 30); + logonToSend.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); + logonToSend.toString(); // calculate length/checksum + session.next(logonToSend); + + session.send(createAppMessage(2)); + final News createAppMessage = createAppMessage(3); + createAppMessage.setString(11, "ÄÖÜäöü?ß"); + session.send(createAppMessage); + session.send(createAppMessage(4)); + session.send(createAppMessage(5)); + + // ugly hack: alter the store to get an invalid checksum + String toString = createAppMessage.toString(); + final String replace = toString.replace("10=", "10=1"); + state.set(3, replace); + + Message createResendRequest = createResendRequest(2, 1); + createResendRequest.toString(); // calculate length/checksum + processMessage(session, createResendRequest); + + Message createAdminMessage = createAdminMessage(3); + createAdminMessage.toString(); // calculate length/checksum + session.next(createAdminMessage); + + // all messages should have been resent + assertEquals(5, application.lastToAppMessage().header.getInt(MsgSeqNum.FIELD)); + assertFalse(state.isResendRequested()); + } } // QFJ-493 @@ -1291,24 +1268,23 @@ public void testResendMessagesWithIncorrectChecksum() throws Exception { public void testGapFillSatisfiesResendRequest() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - session.setNextTargetMsgSeqNum(684); - logonTo(session, 687); - - assertTrue(state.isResendRequested()); - assertEquals(684, state.getNextTargetMsgSeqNum()); - processMessage(session, createResendRequest(688, 1)); - - processMessage(session, createSequenceReset(684, 688, true)); - - processMessage(session, createHeartbeatMessage(689)); - - assertFalse(state.isResendRequested()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + session.setNextTargetMsgSeqNum(684); + logonTo(session, 687); + + assertTrue(state.isResendRequested()); + assertEquals(684, state.getNextTargetMsgSeqNum()); + processMessage(session, createResendRequest(688, 1)); + + processMessage(session, createSequenceReset(684, 688, true)); + + processMessage(session, createHeartbeatMessage(689)); + + assertFalse(state.isResendRequested()); + } } // QFJ-673 @@ -1316,31 +1292,30 @@ public void testGapFillSatisfiesResendRequest() throws Exception { public void testResendRequestIsProcessedAndQueued() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - session.setNextSenderMsgSeqNum(1006); - logonTo(session, 6); - - assertTrue(state.isResendRequested()); - assertEquals(1, state.getNextTargetMsgSeqNum()); - processMessage(session, createResendRequest(7, 1005)); - assertEquals(1, state.getNextTargetMsgSeqNum()); - processMessage(session, createSequenceReset(1, 6, true)); - assertEquals(8, state.getNextTargetMsgSeqNum()); - // we need to satisfy the resendrequest of the opposing side - assertTrue(MsgType.SEQUENCE_RESET.equals(MessageUtils - .getMessageType(application.lastToAdminMessage().toString()))); - assertTrue(state.isResendRequested()); - processMessage(session, createHeartbeatMessage(8)); - assertFalse(state.isResendRequested()); - processMessage(session, createHeartbeatMessage(9)); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - assertEquals(10, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + session.setNextSenderMsgSeqNum(1006); + logonTo(session, 6); + + assertTrue(state.isResendRequested()); + assertEquals(1, state.getNextTargetMsgSeqNum()); + processMessage(session, createResendRequest(7, 1005)); + assertEquals(1, state.getNextTargetMsgSeqNum()); + processMessage(session, createSequenceReset(1, 6, true)); + assertEquals(8, state.getNextTargetMsgSeqNum()); + // we need to satisfy the resendrequest of the opposing side + assertTrue(MsgType.SEQUENCE_RESET.equals(MessageUtils + .getMessageType(application.lastToAdminMessage().toString()))); + assertTrue(state.isResendRequested()); + processMessage(session, createHeartbeatMessage(8)); + assertFalse(state.isResendRequested()); + processMessage(session, createHeartbeatMessage(9)); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + assertEquals(10, state.getNextTargetMsgSeqNum()); + } } @Test @@ -1389,50 +1364,49 @@ public void testResendRequestMsgSeqNum() throws Exception { public void testSimultaneousResendRequests() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - Session session = setUpSession(application, false, - new UnitTestResponder()); - SessionState state = getSessionState(session); - - assertEquals(1, state.getNextTargetMsgSeqNum()); - logonTo(session, 1); - assertEquals(2, state.getNextTargetMsgSeqNum()); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - - processMessage(session, createAppMessage(2)); - session.send(createAppMessage(2)); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - - processMessage(session, createAppMessage(3)); - session.send(createAppMessage(3)); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - - processMessage(session, createHeartbeatMessage(7)); - assertTrue(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - processMessage(session, createResendRequest(8, 2)); - assertTrue(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - - processMessage(session, createHeartbeatMessage(4)); - assertTrue(state.isResendRequested()); - processMessage(session, createHeartbeatMessage(5)); - assertTrue(state.isResendRequested()); - processMessage(session, createHeartbeatMessage(6)); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - - // we need to satisfy the resendrequest of the opposing side - assertTrue(MsgType.SEQUENCE_RESET.equals(MessageUtils - .getMessageType(application.lastToAdminMessage().toString()))); - assertEquals(9, state.getNextTargetMsgSeqNum()); - processMessage(session, createHeartbeatMessage(9)); - processMessage(session, createHeartbeatMessage(10)); - assertEquals(11, state.getNextTargetMsgSeqNum()); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + SessionState state = getSessionState(session); + + assertEquals(1, state.getNextTargetMsgSeqNum()); + logonTo(session, 1); + assertEquals(2, state.getNextTargetMsgSeqNum()); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + + processMessage(session, createAppMessage(2)); + session.send(createAppMessage(2)); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + + processMessage(session, createAppMessage(3)); + session.send(createAppMessage(3)); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + + processMessage(session, createHeartbeatMessage(7)); + assertTrue(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + processMessage(session, createResendRequest(8, 2)); + assertTrue(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + + processMessage(session, createHeartbeatMessage(4)); + assertTrue(state.isResendRequested()); + processMessage(session, createHeartbeatMessage(5)); + assertTrue(state.isResendRequested()); + processMessage(session, createHeartbeatMessage(6)); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + + // we need to satisfy the resendrequest of the opposing side + assertTrue(MsgType.SEQUENCE_RESET.equals(MessageUtils + .getMessageType(application.lastToAdminMessage().toString()))); + assertEquals(9, state.getNextTargetMsgSeqNum()); + processMessage(session, createHeartbeatMessage(9)); + processMessage(session, createHeartbeatMessage(10)); + assertEquals(11, state.getNextTargetMsgSeqNum()); + } } // QFJ-750 @@ -1440,38 +1414,37 @@ public void testSimultaneousResendRequests() throws Exception { public void testRemoveQueuedMessagesOnSequenceReset() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final SessionState state = getSessionState(session); - - final int from = 10; - int numberOfMsgs = 200; - int to = from + numberOfMsgs; - - logonTo(session, 1); - assertEquals(2, state.getNextTargetMsgSeqNum()); - for (int i = from; i < to; i++) { - processMessage(session, createAppMessage(i)); - } - for (int i = from; i < to; i++) { - assertTrue(state.getQueuedSeqNums().contains(i)); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final SessionState state = getSessionState(session); + + final int from = 10; + int numberOfMsgs = 200; + int to = from + numberOfMsgs; + + logonTo(session, 1); + assertEquals(2, state.getNextTargetMsgSeqNum()); + for (int i = from; i < to; i++) { + processMessage(session, createAppMessage(i)); + } + for (int i = from; i < to; i++) { + assertTrue(state.getQueuedSeqNums().contains(i)); + } + + assertTrue(state.getQueuedSeqNums().size() == numberOfMsgs); + assertTrue(application.fromAppMessages.isEmpty()); + // Create a sequence reset which will cause deletion of almost all + // messages + // from the sessionState queue since former messages are skipped. + // The remaining two messages will then be dequeued and processed by the + // app. + final int two = 2; + processMessage(session, createSequenceReset(2, to - two, true)); + assertTrue(application.fromAppMessages.size() == two); + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + assertTrue(state.getQueuedSeqNums().isEmpty()); } - - assertTrue(state.getQueuedSeqNums().size() == numberOfMsgs); - assertTrue(application.fromAppMessages.isEmpty()); - // Create a sequence reset which will cause deletion of almost all - // messages - // from the sessionState queue since former messages are skipped. - // The remaining two messages will then be dequeued and processed by the - // app. - final int two = 2; - processMessage(session, createSequenceReset(2, to - two, true)); - assertTrue(application.fromAppMessages.size() == two); - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - assertTrue(state.getQueuedSeqNums().isEmpty()); - - session.close(); } /** @@ -1487,21 +1460,20 @@ public void testNonLogonMessageNonFIXT() throws Exception { final ApplVerID applVerID = MessageUtils .toApplVerID(FixVersions.BEGINSTRING_FIX44); final UnitTestApplication application = new UnitTestApplication(); - final Session session = SessionFactoryTestSupport.createSession( - sessionID, application, true, false, true, true, null); - session.setResponder(new UnitTestResponder()); - - assertTrue(session.isUsingDataDictionary()); - assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); - session.next(); - session.next(); - Message createHeartbeatMessage = createHeartbeatMessage(1); - createHeartbeatMessage.toString(); // calculate checksum, length - processMessage(session, createHeartbeatMessage); - assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); - assertFalse(session.isLoggedOn()); - - session.close(); + try (Session session = SessionFactoryTestSupport.createSession( + sessionID, application, true, false, true, true, null)) { + session.setResponder(new UnitTestResponder()); + + assertTrue(session.isUsingDataDictionary()); + assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); + session.next(); + session.next(); + Message createHeartbeatMessage = createHeartbeatMessage(1); + createHeartbeatMessage.toString(); // calculate checksum, length + processMessage(session, createHeartbeatMessage); + assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); + assertFalse(session.isLoggedOn()); + } } /** @@ -1516,40 +1488,39 @@ public void testNonLogonMessageFIXT() throws Exception { final ApplVerID applVerID = MessageUtils .toApplVerID(FixVersions.FIX50SP2); final UnitTestApplication application = new UnitTestApplication(); - final Session session = SessionFactoryTestSupport.createSession( + try (Session session = SessionFactoryTestSupport.createSession( sessionID, application, true, false, true, true, - new DefaultApplVerID(ApplVerID.FIX50SP2)); - session.setResponder(new UnitTestResponder()); - - // construct example messages - final quickfix.fixt11.Heartbeat heartbeat = new quickfix.fixt11.Heartbeat(); - setUpHeader(session.getSessionID(), heartbeat, true, 1); - heartbeat.toString(); // calculate checksum, length - final quickfix.fixt11.Logon logon = new quickfix.fixt11.Logon(); - setUpHeader(session.getSessionID(), logon, true, 1); - logon.setInt(HeartBtInt.FIELD, 30); - logon.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); - logon.setString(DefaultApplVerID.FIELD, ApplVerID.FIX50SP2); - logon.toString(); // calculate checksum, length - - assertTrue(session.isUsingDataDictionary()); - assertNull(session.getTargetDefaultApplicationVersionID()); - session.next(); - session.next(); - session.next(heartbeat); - assertNull(session.getTargetDefaultApplicationVersionID()); - assertFalse(session.isLoggedOn()); - - // retry Logon - session.setResponder(new UnitTestResponder()); - session.next(); - session.next(); - assertNull(session.getTargetDefaultApplicationVersionID()); - session.next(logon); - assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); - assertTrue(session.isLoggedOn()); - - session.close(); + new DefaultApplVerID(ApplVerID.FIX50SP2))) { + session.setResponder(new UnitTestResponder()); + + // construct example messages + final quickfix.fixt11.Heartbeat heartbeat = new quickfix.fixt11.Heartbeat(); + setUpHeader(session.getSessionID(), heartbeat, true, 1); + heartbeat.toString(); // calculate checksum, length + final quickfix.fixt11.Logon logon = new quickfix.fixt11.Logon(); + setUpHeader(session.getSessionID(), logon, true, 1); + logon.setInt(HeartBtInt.FIELD, 30); + logon.setInt(EncryptMethod.FIELD, EncryptMethod.NONE_OTHER); + logon.setString(DefaultApplVerID.FIELD, ApplVerID.FIX50SP2); + logon.toString(); // calculate checksum, length + + assertTrue(session.isUsingDataDictionary()); + assertNull(session.getTargetDefaultApplicationVersionID()); + session.next(); + session.next(); + session.next(heartbeat); + assertNull(session.getTargetDefaultApplicationVersionID()); + assertFalse(session.isLoggedOn()); + + // retry Logon + session.setResponder(new UnitTestResponder()); + session.next(); + session.next(); + assertNull(session.getTargetDefaultApplicationVersionID()); + session.next(logon); + assertEquals(applVerID, session.getTargetDefaultApplicationVersionID()); + assertTrue(session.isLoggedOn()); + } } private void processMessage(Session session, Message message) @@ -1631,32 +1602,31 @@ public void fromApp(Message message, SessionID sessionId) } }; - final Session session = setUpSession(application, false, - new UnitTestResponder()); - logonTo(session); - - try { - session.next(createHeartbeatMessage(2)); // should increment target - // seqnum - session.next(createHeartbeatMessage(3)); // should increment target - // seqnum - session.next(createHeartbeatMessage(4)); // should increment target - // seqnum - assertEquals(5, session.getExpectedTargetNum()); - session.next(createAppMessage(5)); // should NOT increment target - // seqnum - fail("No error thrown"); - } catch (final Throwable t) { - assertEquals("java.lang.Error: TEST", t.getMessage()); - assertEquals(5, session.getExpectedTargetNum()); - assertEquals(2, session.getExpectedSenderNum()); - session.next(createHeartbeatMessage(5)); // should increment target - // seqnum - assertEquals(6, session.getExpectedTargetNum()); - assertEquals(2, session.getExpectedSenderNum()); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + logonTo(session); + + try { + session.next(createHeartbeatMessage(2)); // should increment target + // seqnum + session.next(createHeartbeatMessage(3)); // should increment target + // seqnum + session.next(createHeartbeatMessage(4)); // should increment target + // seqnum + assertEquals(5, session.getExpectedTargetNum()); + session.next(createAppMessage(5)); // should NOT increment target + // seqnum + fail("No error thrown"); + } catch (final Throwable t) { + assertEquals("java.lang.Error: TEST", t.getMessage()); + assertEquals(5, session.getExpectedTargetNum()); + assertEquals(2, session.getExpectedSenderNum()); + session.next(createHeartbeatMessage(5)); // should increment target + // seqnum + assertEquals(6, session.getExpectedTargetNum()); + assertEquals(2, session.getExpectedSenderNum()); + } } - - session.close(); } // QFJ-572 @@ -1686,41 +1656,40 @@ public void fromApp(Message message, SessionID sessionId) } }; - final Session session = setUpSession(application, false, - new UnitTestResponder()); - session.setRejectMessageOnUnhandledException(true); - logonTo(session); - - try { - session.next(createAppMessage(2)); - assertEquals(3, session.getExpectedTargetNum()); - assertEquals(3, session.getExpectedSenderNum()); - assertEquals(MsgType.NEWS, application.lastFromAppMessage() - .getHeader().getString(MsgType.FIELD)); - assertEquals(MsgType.BUSINESS_MESSAGE_REJECT, application - .lastToAppMessage().getHeader().getString(MsgType.FIELD)); - - session.next(createHeartbeatMessage(3)); - assertEquals(4, session.getExpectedTargetNum()); - assertEquals(4, session.getExpectedSenderNum()); - assertEquals(MsgType.HEARTBEAT, application.lastFromAdminMessage() - .getHeader().getString(MsgType.FIELD)); - assertEquals(MsgType.REJECT, application.lastToAdminMessage() - .getHeader().getString(MsgType.FIELD)); - - session.next(createAdminMessage(4)); - assertEquals(5, session.getExpectedTargetNum()); - assertEquals(5, session.getExpectedSenderNum()); - assertEquals(MsgType.TEST_REQUEST, application - .lastFromAdminMessage().getHeader() - .getString(MsgType.FIELD)); - assertEquals(MsgType.HEARTBEAT, application.lastToAdminMessage() - .getHeader().getString(MsgType.FIELD)); - } catch (final Throwable t) { - fail("Error was thrown: " + t.getMessage()); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + session.setRejectMessageOnUnhandledException(true); + logonTo(session); + + try { + session.next(createAppMessage(2)); + assertEquals(3, session.getExpectedTargetNum()); + assertEquals(3, session.getExpectedSenderNum()); + assertEquals(MsgType.NEWS, application.lastFromAppMessage() + .getHeader().getString(MsgType.FIELD)); + assertEquals(MsgType.BUSINESS_MESSAGE_REJECT, application + .lastToAppMessage().getHeader().getString(MsgType.FIELD)); + + session.next(createHeartbeatMessage(3)); + assertEquals(4, session.getExpectedTargetNum()); + assertEquals(4, session.getExpectedSenderNum()); + assertEquals(MsgType.HEARTBEAT, application.lastFromAdminMessage() + .getHeader().getString(MsgType.FIELD)); + assertEquals(MsgType.REJECT, application.lastToAdminMessage() + .getHeader().getString(MsgType.FIELD)); + + session.next(createAdminMessage(4)); + assertEquals(5, session.getExpectedTargetNum()); + assertEquals(5, session.getExpectedSenderNum()); + assertEquals(MsgType.TEST_REQUEST, application + .lastFromAdminMessage().getHeader() + .getString(MsgType.FIELD)); + assertEquals(MsgType.HEARTBEAT, application.lastToAdminMessage() + .getHeader().getString(MsgType.FIELD)); + } catch (final Throwable t) { + fail("Error was thrown: " + t.getMessage()); + } } - - session.close(); } private News createAppMessage(int sequence) { @@ -1758,9 +1727,9 @@ public void testSessionRegisteredCorrectly() throws Exception { new UnitTestApplication(), new MemoryStoreFactory(), new JdbcLogFactory(settings)); try { - final Session session = factory.create(sessionID, settings); - assertNotNull(session); - session.close(); + try (Session session = factory.create(sessionID, settings)) { + assertNotNull(session); + } } catch (final NullPointerException nex) { fail("Session not registering correctly so JdbcLog fails while printing an error: " + nex.getMessage()); @@ -1773,56 +1742,56 @@ public void testSessionRegisteredCorrectly() throws Exception { @Test public void testNonpersistedGapFill() throws Exception { final SessionID sessionID = new SessionID("FIX.4.4:SENDER->TARGET"); - final Session session = SessionFactoryTestSupport + try (Session session = SessionFactoryTestSupport .createNonpersistedSession(sessionID, - new UnitTestApplication(), false); - session.getStore().setNextTargetMsgSeqNum(200); - final SessionState state = ReflectionUtil.getField(session, "state", - SessionState.class); - state.setLogonReceived(true); - final ResendRequest resendRequest = new ResendRequest(); - resendRequest.getHeader().setField( - new SenderCompID(sessionID.getTargetCompID())); - resendRequest.getHeader().setField( - new TargetCompID(sessionID.getSenderCompID())); - resendRequest.getHeader().setField(new SendingTime(LocalDateTime.now(ZoneOffset.UTC))); - resendRequest.getHeader().setField(new MsgSeqNum(200)); - resendRequest.set(new BeginSeqNo(1)); - resendRequest.set(new EndSeqNo(100)); - session.next(resendRequest); - assertEquals(201, state.getNextTargetMsgSeqNum()); - session.close(); + new UnitTestApplication(), false)) { + session.getStore().setNextTargetMsgSeqNum(200); + final SessionState state = ReflectionUtil.getField(session, "state", + SessionState.class); + state.setLogonReceived(true); + final ResendRequest resendRequest = new ResendRequest(); + resendRequest.getHeader().setField( + new SenderCompID(sessionID.getTargetCompID())); + resendRequest.getHeader().setField( + new TargetCompID(sessionID.getSenderCompID())); + resendRequest.getHeader().setField(new SendingTime(LocalDateTime.now(ZoneOffset.UTC))); + resendRequest.getHeader().setField(new MsgSeqNum(200)); + resendRequest.set(new BeginSeqNo(1)); + resendRequest.set(new EndSeqNo(100)); + session.next(resendRequest); + assertEquals(201, state.getNextTargetMsgSeqNum()); + } } @Test // QFJ-457 public void testAcceptorRelogon() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - - logonTo(session); - assertTrue(session.isEnabled()); - assertTrue(session.isLoggedOn()); - - session.logout(); - session.next(); - - final Message logout = new Logout(); - logout.getHeader().setString(SenderCompID.FIELD, "TARGET"); - logout.getHeader().setString(TargetCompID.FIELD, "SENDER"); - logout.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); - logout.getHeader().setInt(MsgSeqNum.FIELD, 2); - session.next(logout); - - // session.reset(); - assertFalse(session.isLoggedOn()); - logonTo(session, 3); - Message lastToAdminMessage = application.lastToAdminMessage(); - assertFalse(Logout.MSGTYPE.equals(lastToAdminMessage.getHeader() - .getString(MsgType.FIELD))); - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + + logonTo(session); + assertTrue(session.isEnabled()); + assertTrue(session.isLoggedOn()); + + session.logout(); + session.next(); + + final Message logout = new Logout(); + logout.getHeader().setString(SenderCompID.FIELD, "TARGET"); + logout.getHeader().setString(TargetCompID.FIELD, "SENDER"); + logout.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); + logout.getHeader().setInt(MsgSeqNum.FIELD, 2); + session.next(logout); + + // session.reset(); + assertFalse(session.isLoggedOn()); + logonTo(session, 3); + Message lastToAdminMessage = application.lastToAdminMessage(); + assertFalse(Logout.MSGTYPE.equals(lastToAdminMessage.getHeader() + .getString(MsgType.FIELD))); + } } @Test @@ -1830,52 +1799,51 @@ public void testAcceptorRelogon() throws Exception { public void testStateFlagsAreResetOnLogout() throws Exception { final UnitTestApplication application = new UnitTestApplication(); - final Session session = setUpSession(application, false, - new UnitTestResponder()); - final Message logout = new Logout(); - logout.getHeader().setString(SenderCompID.FIELD, "TARGET"); - logout.getHeader().setString(TargetCompID.FIELD, "SENDER"); - logout.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); - logout.getHeader().setInt(MsgSeqNum.FIELD, 2); - - logonTo(session); - assertFalse(session.isLogoutSent()); - assertFalse(session.isLogoutReceived()); - assertTrue(session.isLogonReceived()); - assertTrue(session.isLogonSent()); - - /* - * Setting the responder to NULL here was formerly causing that the - * flags logoutReceived and logoutSent (amongst others) were not reset - * to false because the Session.disconnect() method returned too early - * since no responder was set anymore. - */ - session.setResponder(null); - session.next(logout); - - assertFalse(session.isLogoutReceived()); - assertFalse(session.isLogoutSent()); - assertFalse(session.isLogonReceived()); - assertFalse(session.isLogonSent()); - - session.setResponder(new UnitTestResponder()); - logonTo(session, 3); - assertFalse(session.isLogoutSent()); - assertFalse(session.isLogoutReceived()); - assertTrue(session.isLogonReceived()); - assertTrue(session.isLogonSent()); - - session.disconnect("Forced by UnitTest", true); - assertFalse(session.isLogoutReceived()); - assertFalse(session.isLogoutSent()); - assertFalse(session.isLogonReceived()); - assertFalse(session.isLogonSent()); - - // onLogout was called - assertTrue(application.logoutSessions.size() == 1); - - session.close(); + try (Session session = setUpSession(application, false, + new UnitTestResponder())) { + final Message logout = new Logout(); + logout.getHeader().setString(SenderCompID.FIELD, "TARGET"); + logout.getHeader().setString(TargetCompID.FIELD, "SENDER"); + logout.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(LocalDateTime.now(ZoneOffset.UTC), UtcTimestampPrecision.SECONDS)); + logout.getHeader().setInt(MsgSeqNum.FIELD, 2); + + logonTo(session); + assertFalse(session.isLogoutSent()); + assertFalse(session.isLogoutReceived()); + assertTrue(session.isLogonReceived()); + assertTrue(session.isLogonSent()); + + /* + * Setting the responder to NULL here was formerly causing that the + * flags logoutReceived and logoutSent (amongst others) were not reset + * to false because the Session.disconnect() method returned too early + * since no responder was set anymore. + */ + session.setResponder(null); + session.next(logout); + + assertFalse(session.isLogoutReceived()); + assertFalse(session.isLogoutSent()); + assertFalse(session.isLogonReceived()); + assertFalse(session.isLogonSent()); + + session.setResponder(new UnitTestResponder()); + logonTo(session, 3); + assertFalse(session.isLogoutSent()); + assertFalse(session.isLogoutReceived()); + assertTrue(session.isLogonReceived()); + assertTrue(session.isLogonSent()); + + session.disconnect("Forced by UnitTest", true); + assertFalse(session.isLogoutReceived()); + assertFalse(session.isLogoutSent()); + assertFalse(session.isLogonReceived()); + assertFalse(session.isLogonSent()); + + // onLogout was called + assertTrue(application.logoutSessions.size() == 1); + } } @Test @@ -1892,26 +1860,25 @@ public void testGenerateRejectAndTargetSeqNum() throws Exception { settings.setString(Session.SETTING_END_TIME, "00:00:00"); settings.setBool(Session.SETTING_CHECK_LATENCY, false); - Session session = new DefaultSessionFactory(new ApplicationAdapter(), + try (Session session = new DefaultSessionFactory(new ApplicationAdapter(), new MemoryStoreFactory(), new SLF4JLogFactory(settings)) - .create(sessionID, settings); - - session.setResponder(new UnitTestResponder()); - - session.next(); - session.setNextSenderMsgSeqNum(177); - session.setNextTargetMsgSeqNum(223); - String[] messages = { + .create(sessionID, settings)) { + + session.setResponder(new UnitTestResponder()); + + session.next(); + session.setNextSenderMsgSeqNum(177); + session.setNextTargetMsgSeqNum(223); + String[] messages = { "8=FIX.4.2\0019=0081\00135=A\00149=THEM\00156=US\001369=177\00152=20100908-17:59:30.551\00134=227\00198=0\001108=30\00110=36\001", "8=FIX.4.2\0019=0107\00135=z\001115=THEM\00149=THEM\00156=US\001369=177\00152=20100908-17:59:30.551\00134=228\001336=1\001340=2\00176=US\001439=USS\00110=133\001", "8=FIX.4.2\0019=0113\00135=4\00134=223\00143=Y\001122=20100908-17:59:30.642\00149=THEM\00156=US\001369=178\00152=20100908-17:59:30.642\001123=Y\00136=225\00110=110\001", "8=FIX.4.2\0019=0246\00135=8\001115=THEM\00134=225\00143=Y\001122=20100908-17:52:37.920\00149=THEM\00156=US\001369=178\00152=20100908-17:59:30.642\00137=10118506\00111=a00000052.1\00117=17537743\00120=0\001150=4\00139=4\00155=ETFC\00154=1\00138=500000\00144=0.998\00132=0\00131=0\001151=0\00114=0\0016=0\00160=20100908-17:52:37.920\00110=80\001" }; - for (String message : messages) - session.next(MessageUtils.parse(session, message)); - - assertEquals(226, session.getStore().getNextTargetMsgSeqNum()); - - session.close(); + for (String message : messages) + session.next(MessageUtils.parse(session, message)); + + assertEquals(226, session.getStore().getNextTargetMsgSeqNum()); + } } @Test @@ -1993,61 +1960,60 @@ private void testSequenceResetGapFillWithChunkSize(int chunkSize) boolean isInitiator = true, resetOnLogon = false, validateSequenceNumbers = true; - Session session = new Session(new UnitTestApplication(), + try (Session session = new Session(new UnitTestApplication(), new MemoryStoreFactory(), sessionID, null, null, new SLF4JLogFactory(new SessionSettings()), new DefaultMessageFactory(), isInitiator ? 30 : 0, false, 30, UtcTimestampPrecision.MILLIS, resetOnLogon, false, false, false, false, false, true, false, 1.5, null, validateSequenceNumbers, new int[] { 5 }, false, false, false, true, false, true, false, null, true, - chunkSize, false, false); - - UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - final SessionState state = getSessionState(session); - - session.logon(); - session.next(); - - assertEquals(1, session.getStore().getNextTargetMsgSeqNum()); - - Message logonRequest = new Message(responder.sentMessageData); - - // Deliver Logon response with too high sequence 20 instead of 1. - session.next(createLogonResponse(sessionID, logonRequest, 20)); - - assertTrue(state.isResendRequested()); - // The expected target sequence should still be 1. - assertEquals(1, session.getStore().getNextTargetMsgSeqNum()); - - // Deliver the missing message #1. - session.next(createAppMessage(1)); - assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); - - // Deliver the missing message #2. - session.next(createAppMessage(2)); - assertEquals(3, session.getStore().getNextTargetMsgSeqNum()); - - // Deliver SequenceReset-GapFill from 3 to 5 - session.next(createSequenceReset(3, 5, true)); - - // Deliver the missing message #5. - session.next(createAppMessage(5)); - /* - * The expected target sequence number should be 6 now. - */ - assertEquals(6, session.getStore().getNextTargetMsgSeqNum()); - assertTrue(session.isLoggedOn()); - assertTrue(state.isResendRequested()); - for (int i = 6; i <= 19; i++) { - session.next(createAppMessage(i)); + chunkSize, false, false)) { + + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + final SessionState state = getSessionState(session); + + session.logon(); + session.next(); + + assertEquals(1, session.getStore().getNextTargetMsgSeqNum()); + + Message logonRequest = new Message(responder.sentMessageData); + + // Deliver Logon response with too high sequence 20 instead of 1. + session.next(createLogonResponse(sessionID, logonRequest, 20)); + + assertTrue(state.isResendRequested()); + // The expected target sequence should still be 1. + assertEquals(1, session.getStore().getNextTargetMsgSeqNum()); + + // Deliver the missing message #1. + session.next(createAppMessage(1)); + assertEquals(2, session.getStore().getNextTargetMsgSeqNum()); + + // Deliver the missing message #2. + session.next(createAppMessage(2)); + assertEquals(3, session.getStore().getNextTargetMsgSeqNum()); + + // Deliver SequenceReset-GapFill from 3 to 5 + session.next(createSequenceReset(3, 5, true)); + + // Deliver the missing message #5. + session.next(createAppMessage(5)); + /* + * The expected target sequence number should be 6 now. + */ + assertEquals(6, session.getStore().getNextTargetMsgSeqNum()); + assertTrue(session.isLoggedOn()); + assertTrue(state.isResendRequested()); + for (int i = 6; i <= 19; i++) { + session.next(createAppMessage(i)); + } + assertFalse(state.isResendRequested()); + assertTrue(session.isLoggedOn()); + // seqnum 20 will be retrieved from the queue, so we should be at 21 now + assertEquals(21, session.getStore().getNextTargetMsgSeqNum()); } - assertFalse(state.isResendRequested()); - assertTrue(session.isLoggedOn()); - // seqnum 20 will be retrieved from the queue, so we should be at 21 now - assertEquals(21, session.getStore().getNextTargetMsgSeqNum()); - - session.close(); } @Test @@ -2153,31 +2119,30 @@ public void testMsgSeqNumTooHighWithDisconnectOnError() throws Exception { final boolean disconnectOnError = true; - Session session = new Session(new UnitTestApplication(), + try (Session session = new Session(new UnitTestApplication(), new MemoryStoreFactory(), sessionID, null, null, new SLF4JLogFactory(new SessionSettings()), new DefaultMessageFactory(), isInitiator ? 30 : 0, false, 30, UtcTimestampPrecision.MILLIS, resetOnLogon, false, false, false, false, false, true, false, 1.5, null, validateSequenceNumbers, new int[] { 5 }, false, disconnectOnError, false, true, false, true, false, - null, true, 0, false, false); - - UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - - // Deliver Logon response with too high sequence number 100 - Message logonRequest = new Message(responder.sentMessageData); - session.next(createLogonResponse(sessionID, logonRequest, 100)); - - // Deliver application message with too high sequence number 101 - session.next(createAppMessage(101)); - // Check, if session is still connected. - assertEquals(true, session.hasResponder()); - - session.close(); + null, true, 0, false, false)) { + + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + + // Deliver Logon response with too high sequence number 100 + Message logonRequest = new Message(responder.sentMessageData); + session.next(createLogonResponse(sessionID, logonRequest, 100)); + + // Deliver application message with too high sequence number 101 + session.next(createAppMessage(101)); + // Check, if session is still connected. + assertEquals(true, session.hasResponder()); + } } @Test @@ -2190,26 +2155,26 @@ public void testTimestampPrecision() throws Exception { final boolean disconnectOnError = true; UnitTestApplication unitTestApplication = new UnitTestApplication(); - Session session = new Session(unitTestApplication, + try (Session session = new Session(unitTestApplication, new MemoryStoreFactory(), sessionID, null, null, new SLF4JLogFactory(new SessionSettings()), new DefaultMessageFactory(), isInitiator ? 30 : 0, false, 30, UtcTimestampPrecision.NANOS, resetOnLogon, false, false, false, false, false, true, false, 1.5, null, validateSequenceNumbers, new int[] { 5 }, false, disconnectOnError, false, true, false, true, false, - null, true, 0, false, false); - - UnitTestResponder responder = new UnitTestResponder(); - session.setResponder(responder); - - session.logon(); - session.next(); - String sendingTimeField = unitTestApplication.toAdminMessages.get(0).getHeader().getString(SendingTime.FIELD); - assertTrue("SendingTime should have NANOS precision (27 characters total)", sendingTimeField.length() == 27); - String substring = sendingTimeField.substring(sendingTimeField.lastIndexOf(".") + 1); - assertTrue("SendingTime should have NANOS precision (9 digits after dot)", substring.length() == 9); - Long.parseLong(substring); - session.close(); + null, true, 0, false, false)) { + + UnitTestResponder responder = new UnitTestResponder(); + session.setResponder(responder); + + session.logon(); + session.next(); + String sendingTimeField = unitTestApplication.toAdminMessages.get(0).getHeader().getString(SendingTime.FIELD); + assertTrue("SendingTime should have NANOS precision (27 characters total)", sendingTimeField.length() == 27); + String substring = sendingTimeField.substring(sendingTimeField.lastIndexOf(".") + 1); + assertTrue("SendingTime should have NANOS precision (9 digits after dot)", substring.length() == 9); + Long.parseLong(substring); + } } @Test diff --git a/quickfixj-core/src/test/java/quickfix/SocketAcceptorTest.java b/quickfixj-core/src/test/java/quickfix/SocketAcceptorTest.java index 6593d606a3..01227d06d9 100644 --- a/quickfixj-core/src/test/java/quickfix/SocketAcceptorTest.java +++ b/quickfixj-core/src/test/java/quickfix/SocketAcceptorTest.java @@ -45,6 +45,9 @@ * MultiAcceptorTest served as a template for this test. */ public class SocketAcceptorTest { + // store static Session count before the test to check cleanup + private static final int SESSION_COUNT = Session.numSessions(); + private final Logger log = LoggerFactory.getLogger(getClass()); private final SessionID acceptorSessionID = new SessionID(FixVersions.BEGINSTRING_FIX42, "ACCEPTOR", "INITIATOR"); @@ -63,13 +66,14 @@ public void cleanup() { @Test public void testRestartOfAcceptor() throws Exception { TestAcceptorApplication testAcceptorApplication = new TestAcceptorApplication(); + TestInitiatorApplication testInitiatorApplication = new TestInitiatorApplication(); ThreadMXBean bean = ManagementFactory.getThreadMXBean(); Acceptor acceptor = null; Initiator initiator = null; try { acceptor = createAcceptor(testAcceptorApplication); acceptor.start(); - initiator = createInitiator(); + initiator = createInitiator(testInitiatorApplication); assertNotNull("Session should be registered", lookupSession(acceptorSessionID)); @@ -84,7 +88,9 @@ public void testRestartOfAcceptor() throws Exception { checkThreads(bean, 2); testAcceptorApplication.waitForLogon(); - assertTrue("initiator should have logged on by now", acceptor.isLoggedOn()); + testInitiatorApplication.waitForLogon(); + assertTrue("acceptor should have logged on by now", acceptor.isLoggedOn()); + assertTrue("initiator should have logged on by now", initiator.isLoggedOn()); } finally { if (initiator != null) { try { @@ -101,6 +107,7 @@ public void testRestartOfAcceptor() throws Exception { } } assertEquals("application should receive logout", 1, testAcceptorApplication.logoutCounter); + assertEquals("application should receive logout", 1, testInitiatorApplication.logoutCounter); } } @@ -145,6 +152,44 @@ public void testDoubleStartOfAcceptor() throws Exception { } } + @Test + public void testSessionsAreCleanedUp() throws Exception { + Acceptor acceptor = null; + try { + TestAcceptorApplication testAcceptorApplication = new TestAcceptorApplication(); + acceptor = createAcceptor(testAcceptorApplication); + acceptor.start(); + assertEquals(1, acceptor.getSessions().size() ); + assertEquals(1 + SESSION_COUNT, Session.numSessions() ); + + } finally { + if (acceptor != null) { + acceptor.stop(true); + assertTrue("After stop() the Session count should not be higher than before the test", Session.numSessions() <= SESSION_COUNT ); + assertEquals("After stop() the Session count should be zero in Connector", 0, acceptor.getSessions().size() ); + } + } + } + + @Test + public void testSessionsAreCleanedUpOnThreadedSocketAcceptor() throws Exception { + Acceptor acceptor = null; + try { + TestAcceptorApplication testAcceptorApplication = new TestAcceptorApplication(); + acceptor = createAcceptorThreaded(testAcceptorApplication); + acceptor.start(); + assertEquals(1, acceptor.getSessions().size() ); + assertEquals(1 + SESSION_COUNT, Session.numSessions() ); + + } finally { + if (acceptor != null) { + acceptor.stop(true); + assertTrue("After stop() the Session count should not be higher than before the test", Session.numSessions() <= SESSION_COUNT ); + assertEquals("After stop() the Session count should be zero in Connector", 0, acceptor.getSessions().size() ); + } + } + } + private void checkThreads(ThreadMXBean bean, int expectedNum) { ThreadInfo[] dumpAllThreads = bean.dumpAllThreads(false, false); int qfjMPThreads = 0; @@ -196,9 +241,64 @@ public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound } } + private static class TestInitiatorApplication extends ApplicationAdapter { + + private final CountDownLatch logonLatch; + public volatile int logoutCounter = 0; + + public TestInitiatorApplication() { + logonLatch = new CountDownLatch(1); + } + + @Override + public void onLogon(SessionID sessionId) { + super.onLogon(sessionId); + logonLatch.countDown(); + } + + public void waitForLogon() { + try { + assertTrue("Logon timed out", logonLatch.await(10, TimeUnit.SECONDS)); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + } + + @Override + public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, RejectLogon { + try { + if (MsgType.LOGOUT.equals(MessageUtils.getMessageType(message.toString()))) { + logoutCounter++; + } + } catch (InvalidMessage ex) { + // ignore + } + } + } + private Acceptor createAcceptor(TestAcceptorApplication testAcceptorApplication) throws ConfigError { + SessionSettings settings = createAcceptorSettings(); + + MessageStoreFactory factory = new MemoryStoreFactory(); + quickfix.LogFactory logFactory = new SLF4JLogFactory(new SessionSettings()); + return new SocketAcceptor(testAcceptorApplication, factory, settings, logFactory, + new DefaultMessageFactory()); + } + + private Acceptor createAcceptorThreaded(TestAcceptorApplication testAcceptorApplication) + throws ConfigError { + + SessionSettings settings = createAcceptorSettings(); + + MessageStoreFactory factory = new MemoryStoreFactory(); + quickfix.LogFactory logFactory = new SLF4JLogFactory(new SessionSettings()); + return new ThreadedSocketAcceptor(testAcceptorApplication, factory, settings, logFactory, + new DefaultMessageFactory()); + } + + private SessionSettings createAcceptorSettings() { SessionSettings settings = new SessionSettings(); HashMap defaults = new HashMap<>(); defaults.put("ConnectionType", "acceptor"); @@ -208,14 +308,10 @@ private Acceptor createAcceptor(TestAcceptorApplication testAcceptorApplication) settings.setString(acceptorSessionID, "SocketAcceptProtocol", ProtocolFactory.getTypeString(ProtocolFactory.VM_PIPE)); settings.setString(acceptorSessionID, "SocketAcceptPort", "10000"); settings.set(defaults); - - MessageStoreFactory factory = new MemoryStoreFactory(); - quickfix.LogFactory logFactory = new SLF4JLogFactory(new SessionSettings()); - return new SocketAcceptor(testAcceptorApplication, factory, settings, logFactory, - new DefaultMessageFactory()); + return settings; } - private Initiator createInitiator() throws ConfigError { + private Initiator createInitiator(TestInitiatorApplication testInitiatorApplication) throws ConfigError { SessionSettings settings = new SessionSettings(); HashMap defaults = new HashMap<>(); defaults.put("ConnectionType", "initiator"); @@ -233,8 +329,7 @@ private Initiator createInitiator() throws ConfigError { MessageStoreFactory factory = new MemoryStoreFactory(); quickfix.LogFactory logFactory = new SLF4JLogFactory(new SessionSettings()); - return new SocketInitiator(new ApplicationAdapter() { - }, factory, settings, logFactory, new DefaultMessageFactory()); + return new SocketInitiator(testInitiatorApplication, factory, settings, logFactory, new DefaultMessageFactory()); } } diff --git a/quickfixj-core/src/test/java/quickfix/SocketInitiatorTest.java b/quickfixj-core/src/test/java/quickfix/SocketInitiatorTest.java index da790a4845..aefc8bc7bd 100644 --- a/quickfixj-core/src/test/java/quickfix/SocketInitiatorTest.java +++ b/quickfixj-core/src/test/java/quickfix/SocketInitiatorTest.java @@ -58,6 +58,8 @@ public class SocketInitiatorTest { private final Logger log = LoggerFactory.getLogger(getClass()); + // store static Session count before the test to check cleanup + private static final int SESSION_COUNT = Session.numSessions(); @Before public void setUp() throws Exception { @@ -376,8 +378,8 @@ private void doTestOfRestart(SessionID clientSessionID, ClientApplication client initiator.stop(); assertFalse(clientSession.isLoggedOn()); - assertTrue(initiator.getSessions().contains(clientSessionID)); - assertTrue(initiator.getSessions().size() == 1); + assertFalse(initiator.getSessions().contains(clientSessionID)); + assertTrue(initiator.getSessions().size() == 0); if (messageLog != null) { messageLogLength = messageLog.length(); assertTrue(messageLog.length() > 0); @@ -404,6 +406,8 @@ private void doTestOfRestart(SessionID clientSessionID, ClientApplication client serverThread.join(); } assertEquals("Client application should receive logout", 2, clientApplication.logoutCounter); + assertTrue("After stop() the Session count should not be higher than before the test", Session.numSessions() <= SESSION_COUNT ); + assertEquals("After stop() the Session count should be zero in Connector", 0, initiator.getSessions().size() ); } private void doTestOfStop(SessionID clientSessionID, ClientApplication clientApplication, diff --git a/quickfixj-core/src/test/java/quickfix/mina/SessionConnectorTest.java b/quickfixj-core/src/test/java/quickfix/mina/SessionConnectorTest.java index 7936d48bb2..413b64e344 100644 --- a/quickfixj-core/src/test/java/quickfix/mina/SessionConnectorTest.java +++ b/quickfixj-core/src/test/java/quickfix/mina/SessionConnectorTest.java @@ -19,7 +19,6 @@ package quickfix.mina; -import junit.framework.TestCase; import quickfix.Acceptor; import quickfix.ConfigError; import quickfix.DefaultSessionFactory; @@ -42,10 +41,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import org.junit.Test; -public class SessionConnectorTest extends TestCase { +public class SessionConnectorTest { private final List propertyChangeEvents = new ArrayList<>(); + @Test public void testConnector() throws Exception { SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionSettings settings = setUpSessionSettings(sessionID); @@ -88,6 +93,7 @@ public void testConnector() throws Exception { assertEquals(settings, connector.getSettings()); } + @Test public void testOneSessionLoggedOnOneSessionNotLoggedOne() throws Exception { SessionID sessionID1 = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionSettings settings = setUpSessionSettings(sessionID1); @@ -96,47 +102,50 @@ public void testOneSessionLoggedOnOneSessionNotLoggedOne() throws Exception { SessionConnector connector = new SessionConnectorUnderTest(settings, sessionFactory); - Session session1 = connector.createSession(sessionID1); - assertNotNull(session1); + try (Session session1 = connector.createSession(sessionID1)) { + assertNotNull(session1); - // test add/remove - SessionConnectorListener connectorListener = new SessionConnectorListener(); - connector.addPropertyChangeListener(connectorListener); - connector.removePropertyChangeListener(connectorListener); + // test add/remove + SessionConnectorListener connectorListener = new SessionConnectorListener(); + connector.addPropertyChangeListener(connectorListener); + connector.removePropertyChangeListener(connectorListener); - Map sessions = new HashMap<>(); - sessions.put(session1.getSessionID(), session1); - connector.setSessions(sessions); + Map sessions = new HashMap<>(); + sessions.put(session1.getSessionID(), session1); + connector.setSessions(sessions); - assertEquals(0, propertyChangeEvents.size()); + assertEquals(0, propertyChangeEvents.size()); - assertEquals(1, connector.getManagedSessions().size()); - assertEquals(session1, connector.getManagedSessions().get(0)); + assertEquals(1, connector.getManagedSessions().size()); + assertEquals(session1, connector.getManagedSessions().get(0)); - assertFalse(connector.isLoggedOn()); + assertFalse(connector.isLoggedOn()); - Field stateField = session1.getClass().getDeclaredField("state"); - stateField.setAccessible(true); - SessionState state = (SessionState) stateField.get(session1); + Field stateField = session1.getClass().getDeclaredField("state"); + stateField.setAccessible(true); + SessionState state = (SessionState) stateField.get(session1); - state.setLogonSent(true); - state.setLogonReceived(true); - assertTrue(connector.isLoggedOn()); + state.setLogonSent(true); + state.setLogonReceived(true); + assertTrue(connector.isLoggedOn()); - SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD1"); - settings.setString(sessionID2, SessionFactory.SETTING_CONNECTION_TYPE, - SessionFactory.ACCEPTOR_CONNECTION_TYPE); - Session session2 = connector.createSession(sessionID2); - assertNotNull(session2); - sessions.put(session2.getSessionID(), session2); - assertFalse(connector.isLoggedOn()); - assertTrue(connector.anyLoggedOn()); + SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD1"); + settings.setString(sessionID2, SessionFactory.SETTING_CONNECTION_TYPE, + SessionFactory.ACCEPTOR_CONNECTION_TYPE); + try (Session session2 = connector.createSession(sessionID2)) { + assertNotNull(session2); + sessions.put(session2.getSessionID(), session2); + assertFalse(connector.isLoggedOn()); + assertTrue(connector.anyLoggedOn()); + } + } } /** * Test that adding/removing dynamic sessions works correctly */ - public void testAddingRemovingDymaicSessions() throws Exception { + @Test + public void testAddingRemovingDynamicSessions() throws Exception { SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "me", "you"); SessionSettings settings = setUpSessionSettings(sessionID); @@ -173,6 +182,9 @@ public void testAddingRemovingDymaicSessions() throws Exception { assertEquals(session2, connector.getManagedSessions().get(0)); connector.removeDynamicSession(session2.getSessionID()); assertEquals(0, connector.getManagedSessions().size()); + + session.close(); + session2.close(); } private SessionSettings setUpSessionSettings(SessionID sessionID) { diff --git a/quickfixj-core/src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java b/quickfixj-core/src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java index 06d005f179..95990ea64c 100644 --- a/quickfixj-core/src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java +++ b/quickfixj-core/src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java @@ -123,54 +123,55 @@ public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound } }; - final Session session = setUpSession(sessionID, application); - - final Message message = new Logon(); - message.getHeader().setString(SenderCompID.FIELD, "ISLD"); - message.getHeader().setString(TargetCompID.FIELD, "TW"); - message.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(new Date(), false)); - message.getHeader().setInt(MsgSeqNum.FIELD, 1); - message.setInt(HeartBtInt.FIELD, 30); - - strategy.onMessage(session, message); - - // Wait for a received message - if (!latch.await(5, TimeUnit.SECONDS)) { - fail("Timeout"); - } - - assertEquals(1, application.fromAdminMessages.size()); - - final Thread[] threads = new Thread[1024]; - Thread.enumerate(threads); - - Thread dispatcherThread = null; - for (final Thread thread : threads) { - if (thread.getName().startsWith("QF/J Session dispatcher")) { - dispatcherThread = thread; - // Dispatcher threads are not daemon threads - assertThat(dispatcherThread.isDaemon(), is(false)); - break; + try (Session session = setUpSession(sessionID, application)) { + + final Message message = new Logon(); + message.getHeader().setString(SenderCompID.FIELD, "ISLD"); + message.getHeader().setString(TargetCompID.FIELD, "TW"); + message.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(new Date(), false)); + message.getHeader().setInt(MsgSeqNum.FIELD, 1); + message.setInt(HeartBtInt.FIELD, 30); + + strategy.onMessage(session, message); + + // Wait for a received message + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("Timeout"); } - } - - // We should have found the dispatcher thread - assertThat(dispatcherThread, notNullValue()); - - // Stop the threads and then check the thread state - strategy.stopDispatcherThreads(); - - for (int i = 0; i < 10; i++) { - Thread.sleep(100); - if (!dispatcherThread.isAlive()) { - break; + + assertEquals(1, application.fromAdminMessages.size()); + + final Thread[] threads = new Thread[1024]; + Thread.enumerate(threads); + + Thread dispatcherThread = null; + for (final Thread thread : threads) { + if (thread.getName().startsWith("QF/J Session dispatcher")) { + dispatcherThread = thread; + // Dispatcher threads are not daemon threads + assertThat(dispatcherThread.isDaemon(), is(false)); + break; + } + } + + // We should have found the dispatcher thread + assertThat(dispatcherThread, notNullValue()); + + // Stop the threads and then check the thread state + strategy.stopDispatcherThreads(); + + for (int i = 0; i < 10; i++) { + Thread.sleep(100); + if (!dispatcherThread.isAlive()) { + break; + } } + + // Dispatcher thread should be dead + assertThat(dispatcherThread.isAlive(), is(false)); + assertNull(strategy.getDispatcher(sessionID)); } - - // Dispatcher thread should be dead - assertThat(dispatcherThread.isAlive(), is(false)); - assertNull(strategy.getDispatcher(sessionID)); } /** @@ -191,94 +192,97 @@ public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound } }; - final Session session = setUpSession(sessionID, application); - - final Message message = new Logon(); - message.getHeader().setString(SenderCompID.FIELD, "ISLD"); - message.getHeader().setString(TargetCompID.FIELD, "TW"); - message.getHeader().setString(SendingTime.FIELD, - UtcTimestampConverter.convert(new Date(), false)); - message.getHeader().setInt(MsgSeqNum.FIELD, 1); - message.setInt(HeartBtInt.FIELD, 30); - - strategy.onMessage(session, message); - - // Wait for a received message - if (!latch.await(5, TimeUnit.SECONDS)) { - fail("Timeout"); - } - - assertEquals(1, application.fromAdminMessages.size()); - - Thread[] threads = new Thread[1024]; - Thread.enumerate(threads); - - Thread dispatcherThread = null; - for (final Thread thread : threads) { - if (thread != null && thread.getName().startsWith("QF/J Session dispatcher")) { - dispatcherThread = thread; - // Dispatcher threads are not daemon threads - assertThat(dispatcherThread.isDaemon(), is(false)); - break; + try (Session session = setUpSession(sessionID, application)) { + + final Message message = new Logon(); + message.getHeader().setString(SenderCompID.FIELD, "ISLD"); + message.getHeader().setString(TargetCompID.FIELD, "TW"); + message.getHeader().setString(SendingTime.FIELD, + UtcTimestampConverter.convert(new Date(), false)); + message.getHeader().setInt(MsgSeqNum.FIELD, 1); + message.setInt(HeartBtInt.FIELD, 30); + + strategy.onMessage(session, message); + + // Wait for a received message + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("Timeout"); } - } - - assertTrue(session.hasResponder()); - // QFJ-790: we do not check the state of the responder anymore - // but wait for the END_OF_STREAM message to stop the threads. - strategy.onMessage(session, EventHandlingStrategy.END_OF_STREAM); - - // sleep some time to let the thread stop - for (int i = 0; i < 20; i++) { - Thread.sleep(100); - if (!dispatcherThread.isAlive()) { - break; + + assertEquals(1, application.fromAdminMessages.size()); + + Thread[] threads = new Thread[1024]; + Thread.enumerate(threads); + + Thread dispatcherThread = null; + for (final Thread thread : threads) { + if (thread != null && thread.getName().startsWith("QF/J Session dispatcher")) { + dispatcherThread = thread; + // Dispatcher threads are not daemon threads + assertThat(dispatcherThread.isDaemon(), is(false)); + break; + } } - } - assertNull(strategy.getDispatcher(sessionID)); - - threads = new Thread[1024]; - Thread.enumerate(threads); - - dispatcherThread = null; - for (final Thread thread : threads) { - if (thread != null && thread.getName().startsWith("QF/J Session dispatcher")) { - dispatcherThread = thread; - // Dispatcher threads are not daemon threads - assertThat(dispatcherThread.isDaemon(), is(false)); - break; + + assertTrue(session.hasResponder()); + // QFJ-790: we do not check the state of the responder anymore + // but wait for the END_OF_STREAM message to stop the threads. + strategy.onMessage(session, EventHandlingStrategy.END_OF_STREAM); + + // sleep some time to let the thread stop + for (int i = 0; i < 20; i++) { + Thread.sleep(100); + if (!dispatcherThread.isAlive()) { + break; + } + } + assertNull(strategy.getDispatcher(sessionID)); + + threads = new Thread[1024]; + Thread.enumerate(threads); + + dispatcherThread = null; + for (final Thread thread : threads) { + if (thread != null && thread.getName().startsWith("QF/J Session dispatcher")) { + dispatcherThread = thread; + // Dispatcher threads are not daemon threads + assertThat(dispatcherThread.isDaemon(), is(false)); + break; + } } + + // the session dispatcher should be dead and hence not listed in the threads array + assertNull(dispatcherThread); + assertFalse(session.hasResponder()); } - - // the session dispatcher should be dead and hence not listed in the threads array - assertNull(dispatcherThread); - assertFalse(session.hasResponder()); } @Test public void testEventHandlingInterruptInRun() throws Exception { final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); - final Session session = setUpSession(sessionID); - final Message message = new Logon(); - message.setInt(HeartBtInt.FIELD, 30); - final ThreadPerSessionEventHandlingStrategyUnderTest strategy = new ThreadPerSessionEventHandlingStrategyUnderTest(); - - strategy.onMessage(session, message); - strategy.getNextMessageException = new InterruptedException("TEST"); - strategy.getDispatcher(sessionID).run(); + try (Session session = setUpSession(sessionID)) { + final Message message = new Logon(); + message.setInt(HeartBtInt.FIELD, 30); + final ThreadPerSessionEventHandlingStrategyUnderTest strategy = new ThreadPerSessionEventHandlingStrategyUnderTest(); + + strategy.onMessage(session, message); + strategy.getNextMessageException = new InterruptedException("TEST"); + strategy.getDispatcher(sessionID).run(); + } } @Test public void testEventHandlingRuntimeException() throws Exception { final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); - final Session session = setUpSession(sessionID); - final Message message = new Logon(); - message.setInt(HeartBtInt.FIELD, 30); - final ThreadPerSessionEventHandlingStrategyUnderTest strategy = new ThreadPerSessionEventHandlingStrategyUnderTest(); - - strategy.onMessage(session, message); - strategy.getNextMessageException = new NullPointerException("TEST"); - strategy.getDispatcher(sessionID).run(); + try (Session session = setUpSession(sessionID)) { + final Message message = new Logon(); + message.setInt(HeartBtInt.FIELD, 30); + final ThreadPerSessionEventHandlingStrategyUnderTest strategy = new ThreadPerSessionEventHandlingStrategyUnderTest(); + + strategy.onMessage(session, message); + strategy.getNextMessageException = new NullPointerException("TEST"); + strategy.getDispatcher(sessionID).run(); + } } // verify the assumption that this always returns null diff --git a/quickfixj-core/src/test/java/quickfix/mina/acceptor/AcceptorIoHandlerTest.java b/quickfixj-core/src/test/java/quickfix/mina/acceptor/AcceptorIoHandlerTest.java index 718b2882fc..cbc444a19a 100644 --- a/quickfixj-core/src/test/java/quickfix/mina/acceptor/AcceptorIoHandlerTest.java +++ b/quickfixj-core/src/test/java/quickfix/mina/acceptor/AcceptorIoHandlerTest.java @@ -43,7 +43,6 @@ import java.util.HashMap; import java.util.Properties; -import static junit.framework.TestCase.fail; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; @@ -65,28 +64,29 @@ public void testFIXTLogonAndApplVerID() throws Exception { final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIXT11, "SENDER", "TARGET"); - final Session session = SessionFactoryTestSupport.createSession(sessionID, - new UnitTestApplication(), false); - stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); // to create a new Session - - final HashMap acceptorSessions = new HashMap<>(); - acceptorSessions.put(sessionID, session); - final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); - - final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, - new NetworkingOptions(new Properties()), mockEventHandlingStrategy); - - final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); - final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), - new HeartBtInt(30), defaultApplVerID); - message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); - message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); - message.getHeader().setField(new SendingTime(LocalDateTime.now())); - message.getHeader().setInt(MsgSeqNum.FIELD, 1); - - handler.processMessage(mockIoSession, message); - assertEquals(defaultApplVerID.getValue(), session.getTargetDefaultApplicationVersionID() - .getValue()); + try (Session session = SessionFactoryTestSupport.createSession(sessionID, + new UnitTestApplication(), false)) { + stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); // to create a new Session + + final HashMap acceptorSessions = new HashMap<>(); + acceptorSessions.put(sessionID, session); + final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); + + final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, + new NetworkingOptions(new Properties()), mockEventHandlingStrategy); + + final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); + final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), + new HeartBtInt(30), defaultApplVerID); + message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); + message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); + message.getHeader().setField(new SendingTime(LocalDateTime.now())); + message.getHeader().setInt(MsgSeqNum.FIELD, 1); + + handler.processMessage(mockIoSession, message); + assertEquals(defaultApplVerID.getValue(), session.getTargetDefaultApplicationVersionID() + .getValue()); + } } @Test @@ -115,26 +115,27 @@ private StaticAcceptorSessionProvider createSessionProvider(HashMap acceptorSessions = new HashMap<>(); - - AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), - new NetworkingOptions(new Properties()), mockEventHandlingStrategy); - - handler.processMessage(mockIoSession, logout); - - verify(mockIoSession).getAttribute("QF_SESSION"); - verify(mockEventHandlingStrategy).onMessage(qfSession, logout); + try (Session qfSession = SessionFactoryTestSupport.createSession()) { + stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(qfSession); + + EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); + + Logout logout = new Logout(); + logout.getHeader() + .setString(SenderCompID.FIELD, qfSession.getSessionID().getSenderCompID()); + logout.getHeader() + .setString(TargetCompID.FIELD, qfSession.getSessionID().getTargetCompID()); + + HashMap acceptorSessions = new HashMap<>(); + + AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), + new NetworkingOptions(new Properties()), mockEventHandlingStrategy); + + handler.processMessage(mockIoSession, logout); + + verify(mockIoSession).getAttribute("QF_SESSION"); + verify(mockEventHandlingStrategy).onMessage(qfSession, logout); + } } @Test @@ -145,26 +146,27 @@ public void testMessageBeforeLogonWithKnownButUnboundSession() throws Exception EventHandlingStrategy mockEventHandlingStrategy = mock(EventHandlingStrategy.class); - Session qfSession = SessionFactoryTestSupport.createSession(); - - Logout logout = new Logout(); - logout.getHeader() - .setString(SenderCompID.FIELD, qfSession.getSessionID().getSenderCompID()); - logout.getHeader() - .setString(TargetCompID.FIELD, qfSession.getSessionID().getTargetCompID()); - - // Expect that onMessage will not be called - //mockEventHandlingStrategy.onMessage(qfSession, logout); - - HashMap acceptorSessions = new HashMap<>(); - acceptorSessions.put(qfSession.getSessionID(), qfSession); - AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), - new NetworkingOptions(new Properties()), mockEventHandlingStrategy); - - handler.processMessage(mockIoSession, logout); - - verify(mockIoSession).getAttribute("QF_SESSION"); - verifyNoMoreInteractions(mockEventHandlingStrategy); + try (Session qfSession = SessionFactoryTestSupport.createSession()) { + + Logout logout = new Logout(); + logout.getHeader() + .setString(SenderCompID.FIELD, qfSession.getSessionID().getSenderCompID()); + logout.getHeader() + .setString(TargetCompID.FIELD, qfSession.getSessionID().getTargetCompID()); + + // Expect that onMessage will not be called + //mockEventHandlingStrategy.onMessage(qfSession, logout); + + HashMap acceptorSessions = new HashMap<>(); + acceptorSessions.put(qfSession.getSessionID(), qfSession); + AcceptorIoHandler handler = new AcceptorIoHandler(createSessionProvider(acceptorSessions), + new NetworkingOptions(new Properties()), mockEventHandlingStrategy); + + handler.processMessage(mockIoSession, logout); + + verify(mockIoSession).getAttribute("QF_SESSION"); + verifyNoMoreInteractions(mockEventHandlingStrategy); + } } // QFJ-933 @@ -175,30 +177,28 @@ public void testLogonWithoutHeartBtInt() throws Exception { final SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIXT11, "SENDER", "TARGET"); - final Session session = SessionFactoryTestSupport.createSession(sessionID, - new UnitTestApplication(), false); - stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); // to create a new Session - - final HashMap acceptorSessions = new HashMap<>(); - acceptorSessions.put(sessionID, session); - final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); - - final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, - new NetworkingOptions(new Properties()), mockEventHandlingStrategy); - - final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); - final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), - new HeartBtInt(30), defaultApplVerID); - message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); - message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); - message.getHeader().setField(new SendingTime(LocalDateTime.now())); - message.getHeader().setInt(MsgSeqNum.FIELD, 1); - // remove HeartBtInt field and make sure there is no Exception - message.removeField(HeartBtInt.FIELD); - try { + try (Session session = SessionFactoryTestSupport.createSession(sessionID, + new UnitTestApplication(), false)) { + stub(mockIoSession.getAttribute("QF_SESSION")).toReturn(null); // to create a new Session + + final HashMap acceptorSessions = new HashMap<>(); + acceptorSessions.put(sessionID, session); + final StaticAcceptorSessionProvider sessionProvider = createSessionProvider(acceptorSessions); + + final AcceptorIoHandler handler = new AcceptorIoHandler(sessionProvider, + new NetworkingOptions(new Properties()), mockEventHandlingStrategy); + + final DefaultApplVerID defaultApplVerID = new DefaultApplVerID(ApplVerID.FIX50SP2); + final Logon message = new Logon(new EncryptMethod(EncryptMethod.NONE_OTHER), + new HeartBtInt(30), defaultApplVerID); + message.getHeader().setString(TargetCompID.FIELD, sessionID.getSenderCompID()); + message.getHeader().setString(SenderCompID.FIELD, sessionID.getTargetCompID()); + message.getHeader().setField(new SendingTime(LocalDateTime.now())); + message.getHeader().setInt(MsgSeqNum.FIELD, 1); + // remove HeartBtInt field and make sure there is no Exception + message.removeField(HeartBtInt.FIELD); handler.processMessage(mockIoSession, message); - } catch (Exception e) { - fail("No exception should be thrown! " + e); + // No exception should be thrown! } } diff --git a/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java b/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java index bde9c3a16a..bf4d67f323 100644 --- a/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java +++ b/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java @@ -81,37 +81,40 @@ protected void setUp() throws Exception { public void testSessionCreation() throws Exception { - Session session1 = provider.getSession(new SessionID("FIX.4.2", "SENDER", "SENDERSUB", - "SENDERLOC", "TARGET", "TARGETSUB", "TARGETLOC", null), null); - SessionID sessionID1 = session1.getSessionID(); - assertEquals("wrong FIX version", "FIX.4.2", sessionID1.getBeginString()); - assertEquals("wrong sender", "SENDER", sessionID1.getSenderCompID()); - assertEquals("wrong senderSub", "SENDERSUB", sessionID1.getSenderSubID()); - assertEquals("wrong senderLoc", "SENDERLOC", sessionID1.getSenderLocationID()); - assertEquals("wrong target", "TARGET", sessionID1.getTargetCompID()); - assertEquals("wrong targetSub", "TARGETSUB", sessionID1.getTargetSubID()); - assertEquals("wrong targetLoc", "TARGETLOC", sessionID1.getTargetLocationID()); - assertEquals("wrong setting", false, session1.getResetOnLogout()); - assertEquals("wrong setting", false, session1.getRefreshOnLogon()); - assertEquals("wrong setting", false, session1.getCheckCompID()); - - Session session2 = provider.getSession(new SessionID("FIX.4.4", "S1", "T"), null); - SessionID sessionID2 = session2.getSessionID(); - assertEquals("wrong FIX version", "FIX.4.4", sessionID2.getBeginString()); - assertEquals("wrong sender", "S1", sessionID2.getSenderCompID()); - assertEquals("wrong target", "T", sessionID2.getTargetCompID()); - assertEquals("wrong setting", true, session2.getResetOnLogout()); - assertEquals("wrong setting", false, session2.getRefreshOnLogon()); - assertEquals("wrong setting", true, session2.getCheckCompID()); - - Session session3 = provider.getSession(new SessionID("FIX.4.4", "X", "Y"), null); - SessionID sessionID3 = session3.getSessionID(); - assertEquals("wrong FIX version", "FIX.4.4", sessionID3.getBeginString()); - assertEquals("wrong sender", "X", sessionID3.getSenderCompID()); - assertEquals("wrong target", "Y", sessionID3.getTargetCompID()); - assertEquals("wrong setting", false, session3.getResetOnLogout()); - assertEquals("wrong setting", true, session3.getRefreshOnLogon()); - assertEquals("wrong setting", true, session3.getCheckCompID()); + try (Session session1 = provider.getSession(new SessionID("FIX.4.2", "SENDER", "SENDERSUB", + "SENDERLOC", "TARGET", "TARGETSUB", "TARGETLOC", null), null)) { + SessionID sessionID1 = session1.getSessionID(); + assertEquals("wrong FIX version", "FIX.4.2", sessionID1.getBeginString()); + assertEquals("wrong sender", "SENDER", sessionID1.getSenderCompID()); + assertEquals("wrong senderSub", "SENDERSUB", sessionID1.getSenderSubID()); + assertEquals("wrong senderLoc", "SENDERLOC", sessionID1.getSenderLocationID()); + assertEquals("wrong target", "TARGET", sessionID1.getTargetCompID()); + assertEquals("wrong targetSub", "TARGETSUB", sessionID1.getTargetSubID()); + assertEquals("wrong targetLoc", "TARGETLOC", sessionID1.getTargetLocationID()); + assertEquals("wrong setting", false, session1.getResetOnLogout()); + assertEquals("wrong setting", false, session1.getRefreshOnLogon()); + assertEquals("wrong setting", false, session1.getCheckCompID()); + } + + try (Session session2 = provider.getSession(new SessionID("FIX.4.4", "S1", "T"), null)) { + SessionID sessionID2 = session2.getSessionID(); + assertEquals("wrong FIX version", "FIX.4.4", sessionID2.getBeginString()); + assertEquals("wrong sender", "S1", sessionID2.getSenderCompID()); + assertEquals("wrong target", "T", sessionID2.getTargetCompID()); + assertEquals("wrong setting", true, session2.getResetOnLogout()); + assertEquals("wrong setting", false, session2.getRefreshOnLogon()); + assertEquals("wrong setting", true, session2.getCheckCompID()); + } + + try (Session session3 = provider.getSession(new SessionID("FIX.4.4", "X", "Y"), null)) { + SessionID sessionID3 = session3.getSessionID(); + assertEquals("wrong FIX version", "FIX.4.4", sessionID3.getBeginString()); + assertEquals("wrong sender", "X", sessionID3.getSenderCompID()); + assertEquals("wrong target", "Y", sessionID3.getTargetCompID()); + assertEquals("wrong setting", false, session3.getResetOnLogout()); + assertEquals("wrong setting", true, session3.getRefreshOnLogon()); + assertEquals("wrong setting", true, session3.getCheckCompID()); + } } private void setUpSettings(SessionID templateID, String key, String value) { @@ -137,9 +140,11 @@ public void testToString() throws Exception { public void testSimpleConstructor() throws Exception { provider = new DynamicAcceptorSessionProvider(settings, new SessionID("FIX.4.2", "ANY", "ANY"), application, messageStoreFactory, logFactory, messageFactory); - // Should actually throw an exception if it fails (see previous test) - assertNotNull(provider.getSession(new SessionID("FIX.4.2", "S", "T"), null)); + try (Session session = provider.getSession(new SessionID("FIX.4.2", "S", "T"), null)) { + // Should actually throw an exception if it fails (see previous test) + assertNotNull(session); + } } /** @@ -150,16 +155,18 @@ public void testDynamicSessionIsAddedToSessionConnector() throws Exception { SessionID id1 = new SessionID("FIX.4.2", "me", "SENDERSUB", "SENDERLOC", "you", "TARGETSUB", "TARGETLOC", null); - provider.getSession(id1, connector); + Session session = provider.getSession(id1, connector); assertEquals(1, connector.sessions.size()); // try again with same sesionID - should still be 1 - provider.getSession(id1, connector); + session = provider.getSession(id1, connector); assertEquals(1, connector.sessions.size()); + session.close(); SessionID id2 = new SessionID("FIX.4.2", "SENDER2", "SENDERSUB", "SENDERLOC", "TARGET2", "TARGETSUB", "TARGETLOC", null); - provider.getSession(id2, connector); + Session session2 = provider.getSession(id2, connector); assertEquals(2, connector.sessions.size()); + session2.close(); } private static class MySessionConnector extends SessionConnector { From fa8e76fcefbacee7f73fc52a0e613ee7a2999f93 Mon Sep 17 00:00:00 2001 From: chrjohn Date: Sun, 25 Feb 2018 00:39:34 +0100 Subject: [PATCH 2/2] Removed duplicate comment. --- .../mina/acceptor/DynamicAcceptorSessionProviderTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java b/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java index bf4d67f323..5cfbf482ec 100644 --- a/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java +++ b/quickfixj-core/src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java @@ -142,7 +142,6 @@ public void testSimpleConstructor() throws Exception { "ANY"), application, messageStoreFactory, logFactory, messageFactory); // Should actually throw an exception if it fails (see previous test) try (Session session = provider.getSession(new SessionID("FIX.4.2", "S", "T"), null)) { - // Should actually throw an exception if it fails (see previous test) assertNotNull(session); } }