Skip to content

Commit 384c286

Browse files
authored
Merge pull request #181 from cbusbey/forget_resend
corrects behavior where resend state is forgotten
2 parents 25a64db + 4210335 commit 384c286

File tree

5 files changed

+125
-13
lines changed

5 files changed

+125
-13
lines changed

in_session.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (state inSession) Timeout(session *session, event event) (nextState session
100100
}
101101
session.log.OnEvent("Sent test request TEST")
102102
session.peerTimer.Reset(time.Duration(int64(1.2 * float64(session.heartBeatTimeout))))
103-
return pendingTimeout{}
103+
return pendingTimeout{state}
104104
}
105105
return state
106106
}

pending_timeout.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package quickfix
22

33
type pendingTimeout struct {
4-
inSession
4+
sessionState
55
}
66

7-
func (currentState pendingTimeout) Timeout(session *session, event event) (nextState sessionState) {
7+
func (s pendingTimeout) Timeout(session *session, event event) (nextState sessionState) {
88
switch event {
99
case peerTimeout:
1010
session.log.OnEvent("Session Timeout")
1111
return latentState{}
1212
}
1313

14-
return currentState
14+
return s
1515
}

pending_timeout_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package quickfix
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestPendingTimeout_SessionTimeout(t *testing.T) {
10+
session := &session{
11+
log: nullLog{},
12+
}
13+
14+
tests := []pendingTimeout{
15+
pendingTimeout{inSession{}},
16+
pendingTimeout{resendState{}},
17+
}
18+
19+
for _, state := range tests {
20+
nextState := state.Timeout(session, peerTimeout)
21+
assert.IsType(t, latentState{}, nextState)
22+
}
23+
}
24+
25+
func TestPendingTimeout_TimeoutUnchangedState(t *testing.T) {
26+
session := &session{
27+
log: nullLog{},
28+
}
29+
30+
tests := []pendingTimeout{
31+
pendingTimeout{inSession{}},
32+
pendingTimeout{resendState{}},
33+
}
34+
35+
testEvents := []event{needHeartbeat, logonTimeout, logoutTimeout}
36+
37+
for _, state := range tests {
38+
for _, event := range testEvents {
39+
nextState := state.Timeout(session, event)
40+
assert.Equal(t, state, nextState)
41+
}
42+
}
43+
}

resend_state.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
package quickfix
22

3-
type resendState struct {
4-
inSession
3+
type resendState struct{}
4+
5+
func (s resendState) String() string { return "Resend" }
6+
7+
func (s resendState) IsLoggedOn() bool { return true }
8+
9+
func (s resendState) Timeout(session *session, event event) (nextState sessionState) {
10+
nextState = inSession{}.Timeout(session, event)
11+
switch nextState.(type) {
12+
case inSession:
13+
nextState = s
14+
case pendingTimeout:
15+
//wrap pendingTimeout in resend. prevents us falling back to inSession if recovering
16+
//from pendingTimeout
17+
nextState = pendingTimeout{s}
18+
}
19+
20+
return
521
}
622

7-
func (state resendState) String() string { return "Resend" }
23+
func (s resendState) VerifyMsgIn(session *session, msg Message) (err MessageRejectError) {
24+
return inSession{}.VerifyMsgIn(session, msg)
25+
}
826

9-
func (state resendState) FixMsgIn(session *session, msg Message) (nextState sessionState) {
10-
return state.handleNextState(session, state.inSession.FixMsgIn(session, msg))
27+
func (s resendState) FixMsgIn(session *session, msg Message) (nextState sessionState) {
28+
session.log.OnEventf("Got FIXMsgIn in resend %s", msg.rawMessage)
29+
return s.handleNextState(session, inSession{}.FixMsgIn(session, msg))
1130
}
1231

13-
func (state resendState) FixMsgInRej(session *session, msg Message, rej MessageRejectError) (nextState sessionState) {
14-
return state.handleNextState(session, state.inSession.FixMsgInRej(session, msg, rej))
32+
func (s resendState) FixMsgInRej(session *session, msg Message, rej MessageRejectError) (nextState sessionState) {
33+
return s.handleNextState(session, inSession{}.FixMsgInRej(session, msg, rej))
1534
}
1635

17-
func (state resendState) handleNextState(session *session, nextState sessionState) sessionState {
36+
func (s resendState) handleNextState(session *session, nextState sessionState) sessionState {
1837
if !nextState.IsLoggedOn() || len(session.messageStash) == 0 {
1938
return nextState
2039
}
@@ -25,5 +44,5 @@ func (state resendState) handleNextState(session *session, nextState sessionStat
2544
session.resendIn <- msg
2645
}
2746

28-
return resendState{}
47+
return s
2948
}

resend_state_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package quickfix
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestResendState_IsLoggedOn(t *testing.T) {
10+
assert.True(t, resendState{}.IsLoggedOn())
11+
}
12+
13+
func TestResendState_TimeoutPeerTimeout(t *testing.T) {
14+
otherEnd := make(chan []byte)
15+
go func() {
16+
<-otherEnd
17+
}()
18+
19+
session := &session{
20+
store: new(memoryStore),
21+
application: new(TestClient),
22+
messageOut: otherEnd,
23+
log: nullLog{},
24+
}
25+
state := resendState{}
26+
nextState := state.Timeout(session, peerTimeout)
27+
assert.Equal(t, pendingTimeout{state}, nextState)
28+
}
29+
30+
func TestResendState_TimeoutUnchanged(t *testing.T) {
31+
otherEnd := make(chan []byte)
32+
go func() {
33+
<-otherEnd
34+
}()
35+
36+
session := &session{
37+
store: new(memoryStore),
38+
application: new(TestClient),
39+
messageOut: otherEnd,
40+
log: nullLog{},
41+
}
42+
state := resendState{}
43+
44+
tests := []event{needHeartbeat, logonTimeout, logoutTimeout}
45+
46+
for _, event := range tests {
47+
nextState := state.Timeout(session, event)
48+
assert.Equal(t, state, nextState)
49+
}
50+
}

0 commit comments

Comments
 (0)