Skip to content

Commit 0762fea

Browse files
author
Chris Busbey
committed
fixes issue where initiator ignores toAdmin reset seqnum
1 parent 2b1295d commit 0762fea

File tree

4 files changed

+130
-3
lines changed

4 files changed

+130
-3
lines changed

logon_state_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,32 @@ func (s *LogonStateTestSuite) TestFixMsgInLogon() {
9191
s.NextSenderMsgSeqNum(3)
9292
}
9393

94+
func (s *LogonStateTestSuite) TestFixMsgInLogonResetSeqNum() {
95+
s.Require().Nil(s.store.IncrNextTargetMsgSeqNum())
96+
97+
logon := s.Logon()
98+
logon.Body.SetField(tagHeartBtInt, FIXInt(32))
99+
logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true))
100+
101+
s.MockApp.On("FromAdmin").Return(nil)
102+
s.MockApp.On("OnLogon")
103+
s.MockApp.On("ToAdmin")
104+
s.fixMsgIn(s.session, logon)
105+
106+
s.MockApp.AssertExpectations(s.T())
107+
108+
s.State(inSession{})
109+
s.Equal(32*time.Second, s.session.HeartBtInt)
110+
111+
s.LastToAdminMessageSent()
112+
s.MessageType(enum.MsgType_LOGON, s.MockApp.lastToAdmin)
113+
s.FieldEquals(tagHeartBtInt, 32, s.MockApp.lastToAdmin.Body)
114+
s.FieldEquals(tagResetSeqNumFlag, true, s.MockApp.lastToAdmin.Body)
115+
116+
s.NextTargetMsgSeqNum(2)
117+
s.NextSenderMsgSeqNum(2)
118+
}
119+
94120
func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogon() {
95121
s.session.InitiateLogon = true
96122
s.Require().Nil(s.store.IncrNextSenderMsgSeqNum())
@@ -111,6 +137,47 @@ func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogon() {
111137
s.NextSenderMsgSeqNum(2)
112138
}
113139

140+
func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogonExpectResetSeqNum() {
141+
s.session.InitiateLogon = true
142+
s.session.sentReset = true
143+
s.Require().Nil(s.store.IncrNextSenderMsgSeqNum())
144+
145+
logon := s.Logon()
146+
logon.Body.SetField(tagHeartBtInt, FIXInt(32))
147+
logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true))
148+
149+
s.MockApp.On("FromAdmin").Return(nil)
150+
s.MockApp.On("OnLogon")
151+
s.fixMsgIn(s.session, logon)
152+
153+
s.MockApp.AssertExpectations(s.T())
154+
s.State(inSession{})
155+
156+
s.NextTargetMsgSeqNum(2)
157+
s.NextSenderMsgSeqNum(2)
158+
}
159+
160+
func (s *LogonStateTestSuite) TestFixMsgInLogonInitiateLogonUnExpectedResetSeqNum() {
161+
s.session.InitiateLogon = true
162+
s.session.sentReset = false
163+
s.Require().Nil(s.store.IncrNextTargetMsgSeqNum())
164+
s.Require().Nil(s.store.IncrNextSenderMsgSeqNum())
165+
166+
logon := s.Logon()
167+
logon.Body.SetField(tagHeartBtInt, FIXInt(32))
168+
logon.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true))
169+
170+
s.MockApp.On("FromAdmin").Return(nil)
171+
s.MockApp.On("OnLogon")
172+
s.fixMsgIn(s.session, logon)
173+
174+
s.MockApp.AssertExpectations(s.T())
175+
s.State(inSession{})
176+
177+
s.NextTargetMsgSeqNum(2)
178+
s.NextSenderMsgSeqNum(1)
179+
}
180+
114181
func (s *LogonStateTestSuite) TestFixMsgInLogonRefreshOnLogon() {
115182
var tests = []bool{true, false}
116183

quickfix_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ func (s *MockStore) Refresh() error {
6565
type MockApp struct {
6666
mock.Mock
6767

68-
lastToAdmin Message
69-
lastToApp Message
68+
decorateToAdmin func(Message)
69+
lastToAdmin Message
70+
lastToApp Message
7071
}
7172

7273
func (e *MockApp) OnCreate(sessionID SessionID) {
@@ -90,6 +91,11 @@ func (e *MockApp) FromAdmin(msg Message, sessionID SessionID) (reject MessageRej
9091

9192
func (e *MockApp) ToAdmin(msg Message, sessionID SessionID) {
9293
e.Called()
94+
95+
if e.decorateToAdmin != nil {
96+
e.decorateToAdmin(msg)
97+
}
98+
9399
e.lastToAdmin = msg
94100
}
95101

session.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type session struct {
3434
stateTimer internal.EventTimer
3535
peerTimer internal.EventTimer
3636
messageStash map[int]Message
37+
sentReset bool
3738

3839
targetDefaultApplVerID string
3940

@@ -241,6 +242,26 @@ func (s *session) prepMessageForSend(msg *Message) error {
241242

242243
if isAdminMessageType(string(msgType)) {
243244
s.application.ToAdmin(*msg, s.sessionID)
245+
246+
if msgType.String() == enum.MsgType_LOGON {
247+
var resetSeqNumFlag FIXBoolean
248+
if msg.Body.Has(tagResetSeqNumFlag) {
249+
if err := msg.Body.GetField(tagResetSeqNumFlag, &resetSeqNumFlag); err != nil {
250+
return err
251+
}
252+
}
253+
254+
if resetSeqNumFlag.Bool() {
255+
if err := s.store.Reset(); err != nil {
256+
return err
257+
}
258+
259+
s.sentReset = true
260+
seqNum = s.store.NextSenderMsgSeqNum()
261+
msg.Header.SetField(tagMsgSeqNum, FIXInt(seqNum))
262+
}
263+
264+
}
244265
} else {
245266
if err := s.application.ToApp(*msg, s.sessionID); err != nil {
246267
return err
@@ -333,7 +354,9 @@ func (s *session) handleLogon(msg Message) error {
333354
if err := msg.Body.GetField(tagResetSeqNumFlag, &resetSeqNumFlag); err == nil {
334355
if resetSeqNumFlag {
335356
s.log.OnEvent("Logon contains ResetSeqNumFlag=Y, resetting sequence numbers to 1")
336-
resetStore = true
357+
if !s.sentReset {
358+
resetStore = true
359+
}
337360
}
338361
}
339362

@@ -358,6 +381,7 @@ func (s *session) handleLogon(msg Message) error {
358381
return err
359382
}
360383
}
384+
s.sentReset = false
361385

362386
s.peerTimer.Reset(time.Duration(float64(1.2) * float64(s.HeartBtInt)))
363387
s.application.OnLogon(s.sessionID)
@@ -596,6 +620,7 @@ func (s *session) onAdmin(msg interface{}) {
596620
s.messageIn = msg.messageIn
597621
s.messageOut = msg.messageOut
598622
s.messageStash = make(map[int]Message)
623+
s.sentReset = false
599624

600625
s.Connect(s)
601626

session_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ func (s *SessionSuite) TestOnAdminConnectInitiateLogon() {
490490

491491
s.MockApp.AssertExpectations(s.T())
492492
s.True(s.session.InitiateLogon)
493+
s.False(s.sentReset)
493494
s.State(logonState{})
494495
s.LastToAdminMessageSent()
495496
s.MessageType(enum.MsgType_LOGON, s.MockApp.lastToAdmin)
@@ -498,6 +499,34 @@ func (s *SessionSuite) TestOnAdminConnectInitiateLogon() {
498499
s.NextSenderMsgSeqNum(3)
499500
}
500501

502+
func (s *SessionSuite) TestInitiateLogonResetSeqNumFlag() {
503+
adminMsg := connect{
504+
messageOut: s.Receiver.sendChannel,
505+
}
506+
s.session.State = latentState{}
507+
s.session.HeartBtInt = time.Duration(45) * time.Second
508+
s.session.store.IncrNextTargetMsgSeqNum()
509+
s.session.store.IncrNextSenderMsgSeqNum()
510+
s.session.InitiateLogon = true
511+
512+
s.MockApp.On("ToAdmin")
513+
s.MockApp.decorateToAdmin = func(msg Message) {
514+
msg.Body.SetField(tagResetSeqNumFlag, FIXBoolean(true))
515+
}
516+
s.session.onAdmin(adminMsg)
517+
518+
s.MockApp.AssertExpectations(s.T())
519+
s.True(s.session.InitiateLogon)
520+
s.True(s.sentReset)
521+
s.State(logonState{})
522+
s.LastToAdminMessageSent()
523+
s.MessageType(enum.MsgType_LOGON, s.MockApp.lastToAdmin)
524+
s.FieldEquals(tagMsgSeqNum, 1, s.MockApp.lastToAdmin.Header)
525+
s.FieldEquals(tagResetSeqNumFlag, true, s.MockApp.lastToAdmin.Body)
526+
s.NextSenderMsgSeqNum(2)
527+
s.NextTargetMsgSeqNum(1)
528+
}
529+
501530
func (s *SessionSuite) TestOnAdminConnectInitiateLogonFIXT11() {
502531
s.session.sessionID.BeginString = enum.BeginStringFIXT11
503532
s.session.DefaultApplVerID = "8"

0 commit comments

Comments
 (0)