Skip to content
Merged
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
2 changes: 1 addition & 1 deletion in_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (state inSession) Timeout(session *session, event event) (nextState session
}
session.log.OnEvent("Sent test request TEST")
session.peerTimer.Reset(time.Duration(int64(1.2 * float64(session.heartBeatTimeout))))
return pendingTimeout{}
return pendingTimeout{state}
}
return state
}
Expand Down
6 changes: 3 additions & 3 deletions pending_timeout.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package quickfix

type pendingTimeout struct {
inSession
sessionState
}

func (currentState pendingTimeout) Timeout(session *session, event event) (nextState sessionState) {
func (s pendingTimeout) Timeout(session *session, event event) (nextState sessionState) {
switch event {
case peerTimeout:
session.log.OnEvent("Session Timeout")
return latentState{}
}

return currentState
return s
}
43 changes: 43 additions & 0 deletions pending_timeout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package quickfix

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestPendingTimeout_SessionTimeout(t *testing.T) {
session := &session{
log: nullLog{},
}

tests := []pendingTimeout{
pendingTimeout{inSession{}},
pendingTimeout{resendState{}},
}

for _, state := range tests {
nextState := state.Timeout(session, peerTimeout)
assert.IsType(t, latentState{}, nextState)
}
}

func TestPendingTimeout_TimeoutUnchangedState(t *testing.T) {
session := &session{
log: nullLog{},
}

tests := []pendingTimeout{
pendingTimeout{inSession{}},
pendingTimeout{resendState{}},
}

testEvents := []event{needHeartbeat, logonTimeout, logoutTimeout}

for _, state := range tests {
for _, event := range testEvents {
nextState := state.Timeout(session, event)
assert.Equal(t, state, nextState)
}
}
}
37 changes: 28 additions & 9 deletions resend_state.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
package quickfix

type resendState struct {
inSession
type resendState struct{}

func (s resendState) String() string { return "Resend" }

func (s resendState) IsLoggedOn() bool { return true }

func (s resendState) Timeout(session *session, event event) (nextState sessionState) {
nextState = inSession{}.Timeout(session, event)
switch nextState.(type) {
case inSession:
nextState = s
case pendingTimeout:
//wrap pendingTimeout in resend. prevents us falling back to inSession if recovering
//from pendingTimeout
nextState = pendingTimeout{s}
}

return
}

func (state resendState) String() string { return "Resend" }
func (s resendState) VerifyMsgIn(session *session, msg Message) (err MessageRejectError) {
return inSession{}.VerifyMsgIn(session, msg)
}

func (state resendState) FixMsgIn(session *session, msg Message) (nextState sessionState) {
return state.handleNextState(session, state.inSession.FixMsgIn(session, msg))
func (s resendState) FixMsgIn(session *session, msg Message) (nextState sessionState) {
session.log.OnEventf("Got FIXMsgIn in resend %s", msg.rawMessage)
return s.handleNextState(session, inSession{}.FixMsgIn(session, msg))
}

func (state resendState) FixMsgInRej(session *session, msg Message, rej MessageRejectError) (nextState sessionState) {
return state.handleNextState(session, state.inSession.FixMsgInRej(session, msg, rej))
func (s resendState) FixMsgInRej(session *session, msg Message, rej MessageRejectError) (nextState sessionState) {
return s.handleNextState(session, inSession{}.FixMsgInRej(session, msg, rej))
}

func (state resendState) handleNextState(session *session, nextState sessionState) sessionState {
func (s resendState) handleNextState(session *session, nextState sessionState) sessionState {
if !nextState.IsLoggedOn() || len(session.messageStash) == 0 {
return nextState
}
Expand All @@ -25,5 +44,5 @@ func (state resendState) handleNextState(session *session, nextState sessionStat
session.resendIn <- msg
}

return resendState{}
return s
}
50 changes: 50 additions & 0 deletions resend_state_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package quickfix

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestResendState_IsLoggedOn(t *testing.T) {
assert.True(t, resendState{}.IsLoggedOn())
}

func TestResendState_TimeoutPeerTimeout(t *testing.T) {
otherEnd := make(chan []byte)
go func() {
<-otherEnd
}()

session := &session{
store: new(memoryStore),
application: new(TestClient),
messageOut: otherEnd,
log: nullLog{},
}
state := resendState{}
nextState := state.Timeout(session, peerTimeout)
assert.Equal(t, pendingTimeout{state}, nextState)
}

func TestResendState_TimeoutUnchanged(t *testing.T) {
otherEnd := make(chan []byte)
go func() {
<-otherEnd
}()

session := &session{
store: new(memoryStore),
application: new(TestClient),
messageOut: otherEnd,
log: nullLog{},
}
state := resendState{}

tests := []event{needHeartbeat, logonTimeout, logoutTimeout}

for _, event := range tests {
nextState := state.Timeout(session, event)
assert.Equal(t, state, nextState)
}
}