Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions quickfixj-core/src/main/java/quickfix/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -2107,7 +2107,6 @@ private boolean generateLogon() throws IOException {
}
state.setLastReceivedTime(SystemTime.currentTimeMillis());
state.clearTestRequestCounter();
state.setLogonSent(true);
logonAttempts++;

if (enableNextExpectedMsgSeqNum) {
Expand All @@ -2117,7 +2116,9 @@ private boolean generateLogon() throws IOException {
}

setLogonTags(logon);
return sendRaw(logon, 0);
final boolean result = sendRaw(logon, 0);
state.setLogonSent(result);
return result;
}

/**
Expand Down Expand Up @@ -2650,8 +2651,7 @@ private void generateLogon(Message otherLogon, int expectedTargetNum) throws Fie
}

setLogonTags(logon);
sendRaw(logon, 0);
state.setLogonSent(true);
state.setLogonSent(sendRaw(logon, 0));
}

private void persist(Header header, String messageString, int num) throws IOException, FieldNotFound {
Expand Down
56 changes: 54 additions & 2 deletions quickfixj-core/src/test/java/quickfix/SessionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
Expand All @@ -66,10 +65,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import org.mockito.Mockito;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -1824,6 +1824,58 @@ public void testNonLogonMessageFIXT() throws Exception {
}
}

/**
* QFJ-1302: The Session's logonSent state should only be set to true
* if the Logon message was actually sent, i.e. if the underlying
* MessageStore successfully persisted it. Previously, logonSent was
* set unconditionally before checking the result of sendRaw().
*/
@Test
// QFJ-1302
public void testLogonNotMarkedAsSentWhenMessageStorePersistFails() throws Exception {
final Application application = new UnitTestApplication();
final SessionID sessionID = new SessionID(
FixVersions.BEGINSTRING_FIX44, "SENDER", "TARGET");

final MessageStoreFactory mockMessageStoreFactory = mock(MessageStoreFactory.class);
final MessageStore mockMessageStore = mock(MessageStore.class);
when(mockMessageStoreFactory.create(sessionID)).thenReturn(mockMessageStore);
when(mockMessageStore.getNextSenderMsgSeqNum()).thenReturn(1);
when(mockMessageStore.getNextTargetMsgSeqNum()).thenReturn(1);
when(mockMessageStore.getCreationTime()).thenReturn(new Date());

// Simulate the persistence failure described in ticket QFJ-1302
doThrow(new IOException("Simulated persist failure"))
.when(mockMessageStore).set(anyInt(), anyString());

final MessageQueueFactory mockMessageQueueFactory = mock(MessageQueueFactory.class);
final MessageQueue mockMessageQueue = mock(MessageQueue.class);
when(mockMessageQueueFactory.create(sessionID)).thenReturn(mockMessageQueue);

final LogFactory mockLogFactory = mock(LogFactory.class);
final Log mockLog = mock(Log.class);
when(mockLogFactory.create(sessionID)).thenReturn(mockLog);

try (Session session = new Session(application,
mockMessageStoreFactory, mockMessageQueueFactory, sessionID, null, 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, false, true, false, true, false,
null, true, 0, false, false, true, new ArrayList<>(), Session.DEFAULT_HEARTBEAT_TIMEOUT_MULTIPLIER, false)) {

final UnitTestResponder responder = new UnitTestResponder();
session.setResponder(responder);

session.logon();
session.next();

final SessionState state = getSessionState(session);
assertFalse(
"logonSent should remain false when the MessageStore fails to persist the Logon",
state.isLogonSent());
}
}

private void processMessage(Session session, Message message)
throws FieldNotFound, RejectLogon, IncorrectDataFormat,
IncorrectTagValue, UnsupportedMessageType, IOException,
Expand Down
Loading