From f715c287e7acaf787fe5da029ad58dec31e71547 Mon Sep 17 00:00:00 2001
From: Chris Busbey <cbusbey@connamara.com>
Date: Sat, 6 Aug 2016 15:06:10 -0500
Subject: [PATCH 1/2] adds time range, necessary for session start/end time
 features

---
 Makefile                    |  2 +-
 internal/time_range.go      | 51 +++++++++++++++++++++++++++++++
 internal/time_range_test.go | 60 +++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 internal/time_range.go
 create mode 100644 internal/time_range_test.go

diff --git a/Makefile b/Makefile
index f00d1a1b..53cf4737 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ lint:
 	golint .
 
 test: get
-	go test -v -cover . ./datadictionary
+	go test -v -cover . ./datadictionary ./internal
 
 _build_all: get
 	go build -v ./...
diff --git a/internal/time_range.go b/internal/time_range.go
new file mode 100644
index 00000000..4255b4d9
--- /dev/null
+++ b/internal/time_range.go
@@ -0,0 +1,51 @@
+package internal
+
+import (
+	"errors"
+	"time"
+)
+
+//UTCTimeOnly represents the time of day in UTC
+type UTCTimeOnly struct {
+	seconds int
+}
+
+const shortForm = "15:04:05"
+
+var errParseTime = errors.New("Time must be in the format HH:MM:SS")
+
+//NewTime returns a newly initialized UTCTimeOnly
+func NewTime(hour, minute, second int) UTCTimeOnly {
+	return UTCTimeOnly{second + minute*60 + hour*60*60}
+}
+
+//ParseTime parses a UTCTimeOnly from a string in the format HH:MM:SS
+func ParseTime(str string) (UTCTimeOnly, error) {
+	t, err := time.Parse(shortForm, str)
+	if err != nil {
+		return UTCTimeOnly{}, errParseTime
+	}
+
+	return NewTime(t.Clock()), nil
+}
+
+//TimeRange represents a time band from StartTime to EndTime
+type TimeRange struct {
+	StartTime, EndTime UTCTimeOnly
+}
+
+//IsInRange returns true if time t is within in the time range
+func (r *TimeRange) IsInRange(t time.Time) bool {
+	if r == nil {
+		return true
+	}
+
+	ts := NewTime(t.UTC().Clock()).seconds
+	start := r.StartTime.seconds
+	end := r.EndTime.seconds
+
+	if start > end {
+		return !(end < ts && ts < start)
+	}
+	return start <= ts && ts <= end
+}
diff --git a/internal/time_range_test.go b/internal/time_range_test.go
new file mode 100644
index 00000000..0703b849
--- /dev/null
+++ b/internal/time_range_test.go
@@ -0,0 +1,60 @@
+package internal
+
+import (
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestParseTime(t *testing.T) {
+	to, err := ParseTime("12:34:04")
+	assert.Nil(t, err)
+	assert.Equal(t, NewTime(12, 34, 4), to)
+
+	_, err = ParseTime("0:0:0")
+	assert.NotNil(t, err)
+
+	_, err = ParseTime("00:00")
+	assert.NotNil(t, err)
+
+	_, err = ParseTime("0000:00")
+	assert.NotNil(t, err)
+}
+
+func TestTimeRangeIsInRange(t *testing.T) {
+	start := NewTime(3, 0, 0)
+	end := NewTime(18, 0, 0)
+
+	now := time.Date(2016, time.August, 10, 10, 0, 0, 0, time.UTC)
+	assert.True(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 18, 0, 0, 0, time.UTC)
+	assert.True(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 2, 0, 0, 0, time.UTC)
+	assert.False(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 19, 0, 0, 0, time.UTC)
+	assert.False(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 18, 0, 1, 0, time.UTC)
+	assert.False(t, (&TimeRange{start, end}).IsInRange(now))
+
+	start = NewTime(18, 0, 0)
+	end = NewTime(3, 0, 0)
+	now = time.Date(2016, time.August, 10, 18, 0, 0, 0, time.UTC)
+	assert.True(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 3, 0, 0, 0, time.UTC)
+	assert.True(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 4, 0, 0, 0, time.UTC)
+	assert.False(t, (&TimeRange{start, end}).IsInRange(now))
+
+	now = time.Date(2016, time.August, 10, 17, 0, 0, 0, time.UTC)
+	assert.False(t, (&TimeRange{start, end}).IsInRange(now))
+
+	var tr *TimeRange
+	assert.True(t, tr.IsInRange(now), "always in range if time range is nil")
+}
-- 
GitLab


From 47a65aeb64797a33d709573a2a8b4a1e197ed938 Mon Sep 17 00:00:00 2001
From: Chris Busbey <cbusbey@connamara.com>
Date: Sat, 6 Aug 2016 18:19:16 -0500
Subject: [PATCH 2/2] adds session start/end time configuration, more test util

---
 config/configuration.go |   2 +
 quickfix_test.go        |  41 ++++++++--
 session.go              |  29 +++++++
 session_test.go         | 175 ++++++++++++++++++----------------------
 test_helpers.go         |   2 +
 5 files changed, 147 insertions(+), 102 deletions(-)

diff --git a/config/configuration.go b/config/configuration.go
index 374eb3da..a3ca80a7 100644
--- a/config/configuration.go
+++ b/config/configuration.go
@@ -12,6 +12,8 @@ const (
 	SocketCertificateFile    string = "SocketCertificateFile"
 	SocketCAFile             string = "SocketCAFile"
 	DefaultApplVerID         string = "DefaultApplVerID"
+	StartTime                string = "StartTime"
+	EndTime                  string = "EndTime"
 	DataDictionary           string = "DataDictionary"
 	TransportDataDictionary  string = "TransportDataDictionary"
 	AppDataDictionary        string = "AppDataDictionary"
diff --git a/quickfix_test.go b/quickfix_test.go
index d7de0efb..e529c1c2 100644
--- a/quickfix_test.go
+++ b/quickfix_test.go
@@ -12,6 +12,10 @@ type KnowsFieldMap interface {
 	GetInt(Tag) (int, MessageRejectError)
 }
 
+func (s *QuickFIXSuite) MessageType(msgType string, msg Message) {
+	s.FieldEquals(tagMsgType, msgType, msg.Header)
+}
+
 func (s *QuickFIXSuite) FieldEquals(tag Tag, expectedValue interface{}, fieldMap KnowsFieldMap) {
 	s.Require().True(fieldMap.Has(tag), "Tag %v not set", tag)
 
@@ -29,6 +33,12 @@ func (s *QuickFIXSuite) FieldEquals(tag Tag, expectedValue interface{}, fieldMap
 	}
 }
 
+func (s *QuickFIXSuite) MessageEqualsBytes(msgBytes []byte, msg Message) {
+	_, err := msg.Build()
+	s.Require().Nil(err)
+	s.Equal(string(msg.rawMessage), string(msgBytes))
+}
+
 type SessionSuite struct {
 	QuickFIXSuite
 	*messageFactory
@@ -50,14 +60,18 @@ func (s *SessionSuite) Init() {
 	}
 }
 
-func (s *SessionSuite) LastToAdminMessageSent() {
+func (s *SessionSuite) MessageSentEquals(msg Message) {
 	msgBytes := s.Receiver.LastMessage()
-	s.NotNil(msgBytes)
+	s.NotNil(msgBytes, "Message should have been sent")
+	s.MessageEqualsBytes(msgBytes, msg)
+}
 
-	_, err := s.mockApp.lastToAdmin.Build()
-	s.Nil(err)
+func (s *SessionSuite) LastToAppMessageSent() {
+	s.MessageSentEquals(s.mockApp.lastToApp)
+}
 
-	s.Equal(string(s.mockApp.lastToAdmin.rawMessage), string(msgBytes))
+func (s *SessionSuite) LastToAdminMessageSent() {
+	s.MessageSentEquals(s.mockApp.lastToAdmin)
 }
 
 func (s *SessionSuite) NoMessageSent() {
@@ -75,3 +89,20 @@ func (s *SessionSuite) NextTargetMsgSeqNum(expected int) {
 func (s *SessionSuite) NextSenderMsgSeqNum(expected int) {
 	s.Equal(expected, s.session.store.NextSenderMsgSeqNum(), "NextSenderMsgSeqNum should be ", expected)
 }
+
+func (s *SessionSuite) NoMessagePersisted(seqNum int) {
+	persistedMessages, err := s.session.store.GetMessages(seqNum, seqNum)
+	s.Nil(err)
+	s.Empty(persistedMessages, "The message should not be persisted")
+}
+
+func (s *SessionSuite) MessagePersisted(msg Message) {
+	var err error
+	seqNum, err := msg.Header.GetInt(tagMsgSeqNum)
+	s.Nil(err, "message should have seq num")
+
+	persistedMessages, err := s.session.store.GetMessages(seqNum, seqNum)
+	s.Nil(err)
+	s.Len(persistedMessages, 1, "a message should be stored at %v", seqNum)
+	s.MessageEqualsBytes(persistedMessages[0], msg)
+}
diff --git a/session.go b/session.go
index fff945b4..04fa60eb 100644
--- a/session.go
+++ b/session.go
@@ -8,6 +8,7 @@ import (
 	"github.com/quickfixgo/quickfix/config"
 	"github.com/quickfixgo/quickfix/datadictionary"
 	"github.com/quickfixgo/quickfix/enum"
+	"github.com/quickfixgo/quickfix/internal"
 )
 
 //The Session is the primary FIX abstraction for message communication
@@ -43,6 +44,8 @@ type session struct {
 	//required on logon for FIX.T.1 messages
 	defaultApplVerID       string
 	targetDefaultApplVerID string
+
+	sessionTime *internal.TimeRange
 }
 
 func (s *session) logError(err error) {
@@ -133,6 +136,32 @@ func newSession(sessionID SessionID, storeFactory MessageStoreFactory, settings
 		}
 	}
 
+	switch {
+	case !settings.HasSetting(config.StartTime) && !settings.HasSetting(config.EndTime):
+	//no session times
+	case settings.HasSetting(config.StartTime) && settings.HasSetting(config.EndTime):
+		var startTimeStr, endTimeStr string
+		if startTimeStr, err = settings.Setting(config.StartTime); err != nil {
+			return session, err
+		}
+
+		if endTimeStr, err = settings.Setting(config.EndTime); err != nil {
+			return session, err
+		}
+
+		session.sessionTime = new(internal.TimeRange)
+		if session.sessionTime.StartTime, err = internal.ParseTime(startTimeStr); err != nil {
+			return session, err
+		}
+		if session.sessionTime.EndTime, err = internal.ParseTime(endTimeStr); err != nil {
+			return session, err
+		}
+	case settings.HasSetting(config.StartTime):
+		return session, requiredConfigurationMissing(config.EndTime)
+	case settings.HasSetting(config.EndTime):
+		return session, requiredConfigurationMissing(config.StartTime)
+	}
+
 	if session.log, err = logFactory.CreateSessionLog(session.sessionID); err != nil {
 		return session, err
 	}
diff --git a/session_test.go b/session_test.go
index a3a5ae9a..e661237f 100644
--- a/session_test.go
+++ b/session_test.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/quickfixgo/quickfix/config"
 	"github.com/quickfixgo/quickfix/enum"
+	"github.com/quickfixgo/quickfix/internal"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -189,6 +190,7 @@ func (s *NewSessionTestSuite) TestDefaults() {
 
 	s.False(session.resetOnLogon)
 	s.False(session.resetOnLogout)
+	s.Nil(session.sessionTime, "By default, start and end time unset")
 }
 
 func (s *NewSessionTestSuite) TestResetOnLogon() {
@@ -225,78 +227,53 @@ func (s *NewSessionTestSuite) TestResetOnLogout() {
 	}
 }
 
-type SessionSendTestSuite struct {
-	suite.Suite
+func (s *NewSessionTestSuite) TestStartAndEndTime() {
+	s.SessionSettings.Set(config.StartTime, "12:00:00")
+	s.SessionSettings.Set(config.EndTime, "14:00:00")
+	session, err := newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App)
+	s.Nil(err)
+	s.NotNil(session.sessionTime)
 
-	*messageFactory
-	*mockApp
-	receiver *mockSessionReceiver
-	*session
+	s.Equal(internal.NewTime(12, 0, 0), session.sessionTime.StartTime)
+	s.Equal(internal.NewTime(14, 0, 0), session.sessionTime.EndTime)
 }
 
-func (suite *SessionSendTestSuite) SetupTest() {
-	suite.mockApp = new(mockApp)
-	suite.messageFactory = new(messageFactory)
-	suite.receiver = newMockSessionReceiver()
-	suite.session = &session{
-		store:        new(memoryStore),
-		application:  suite,
-		log:          nullLog{},
-		messageOut:   suite.receiver.sendChannel,
-		sessionState: inSession{},
-		sessionID:    SessionID{BeginString: "FIX.4.2", TargetCompID: "TW", SenderCompID: "ISLD"},
-	}
-}
+func (s *NewSessionTestSuite) TestMissingStartOrEndTime() {
+	s.SessionSettings.Set(config.StartTime, "12:00:00")
+	_, err := newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App)
+	s.NotNil(err)
 
-func TestSessionSendTestSuite(t *testing.T) {
-	suite.Run(t, new(SessionSendTestSuite))
+	s.SetupTest()
+	s.SessionSettings.Set(config.EndTime, "14:00:00")
+	_, err = newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App)
+	s.NotNil(err)
 }
 
-func (suite *SessionSendTestSuite) shouldNotPersistMessage() {
-	suite.Equal(1, suite.store.NextSenderMsgSeqNum(), "The next sender sequence number should not be incremented")
-	persistedMessages, err := suite.store.GetMessages(1, 1)
-	suite.Nil(err)
-	suite.Len(persistedMessages, 0, "The message should not be persisted")
-}
+func (s *NewSessionTestSuite) TestStartOrEndTimeParseError() {
+	s.SessionSettings.Set(config.StartTime, "1200:00")
+	s.SessionSettings.Set(config.EndTime, "14:00:00")
 
-func (suite *SessionSendTestSuite) shouldPersistMessage() {
-	suite.Equal(2, suite.store.NextSenderMsgSeqNum(), "The next sender sequence number should be incremented")
-	persistedMessages, err := suite.store.GetMessages(1, 1)
-	suite.Nil(err)
-	suite.Len(persistedMessages, 1, "The message should be persisted")
-}
+	_, err := newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App)
+	s.NotNil(err)
 
-func (suite *SessionSendTestSuite) shouldPersistMessageWithSequenceNum(expectedSeqNum int) {
-	suite.Equal(expectedSeqNum+1, suite.store.NextSenderMsgSeqNum(), "The next sender sequence number should be incremented")
-	persistedMessages, err := suite.store.GetMessages(expectedSeqNum, expectedSeqNum)
-	suite.Nil(err)
-	suite.Len(persistedMessages, 1, "The message should be persisted")
-}
+	s.SessionSettings.Set(config.StartTime, "12:00:00")
+	s.SessionSettings.Set(config.EndTime, "")
 
-func (suite *SessionSendTestSuite) shouldBeType(msg Message, expectedMsgType string) {
-	actual, err := msg.Header.GetString(tagMsgType)
-	suite.Nil(err, "Message doesn't have message type")
-	suite.Equal(expectedMsgType, actual)
+	_, err = newSession(s.SessionID, s.MessageStoreFactory, s.SessionSettings, s.LogFactory, s.App)
+	s.NotNil(err)
 }
 
-func (suite *SessionSendTestSuite) shouldSendMessage() {
-	suite.NotNil(suite.receiver.LastMessage(), "The message should have been sent")
-}
-func (suite *SessionSendTestSuite) shouldNotSendMessage() {
-	suite.Nil(suite.receiver.LastMessage(), "The message should not have been sent")
+type SessionSendTestSuite struct {
+	SessionSuite
 }
 
-func (suite *SessionSendTestSuite) shouldSendMessages(cnt int) {
-	for i := 0; i < cnt; i++ {
-		suite.shouldSendMessage()
-	}
-
-	suite.shouldNotSendMessage()
+func TestSessionSendTestSuite(t *testing.T) {
+	suite.Run(t, new(SessionSendTestSuite))
 }
 
-func (suite *SessionSendTestSuite) sentMessageShouldBe(sentMsg []byte, msg Message) {
-	expectedBytes, _ := msg.Build()
-	suite.Equal(string(expectedBytes), string(sentMsg))
+func (suite *SessionSendTestSuite) SetupTest() {
+	suite.Init()
+	suite.session.sessionState = inSession{}
 }
 
 func (suite *SessionSendTestSuite) TestQueueForSendAppMessage() {
@@ -304,8 +281,10 @@ func (suite *SessionSendTestSuite) TestQueueForSendAppMessage() {
 	require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle()))
 
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldPersistMessage()
-	suite.shouldNotSendMessage()
+	suite.NoMessageSent()
+	suite.MessagePersisted(suite.mockApp.lastToApp)
+	suite.FieldEquals(tagMsgSeqNum, 1, suite.mockApp.lastToApp.Header)
+	suite.NextSenderMsgSeqNum(2)
 }
 
 func (suite *SessionSendTestSuite) TestQueueForSendDoNotSendAppMessage() {
@@ -313,13 +292,17 @@ func (suite *SessionSendTestSuite) TestQueueForSendDoNotSendAppMessage() {
 	suite.Equal(DoNotSend, suite.queueForSend(suite.NewOrderSingle()))
 
 	suite.AssertExpectations(suite.T())
-	suite.shouldNotPersistMessage()
-	suite.shouldNotSendMessage()
+	suite.NoMessagePersisted(1)
+	suite.NoMessageSent()
+	suite.NextSenderMsgSeqNum(1)
 
 	suite.mockApp.On("ToAdmin")
 	require.Nil(suite.T(), suite.send(suite.Heartbeat()))
+
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldSendMessages(1)
+	suite.LastToAdminMessageSent()
+	suite.MessagePersisted(suite.mockApp.lastToAdmin)
+	suite.NextSenderMsgSeqNum(2)
 }
 
 func (suite *SessionSendTestSuite) TestQueueForSendAdminMessage() {
@@ -327,8 +310,9 @@ func (suite *SessionSendTestSuite) TestQueueForSendAdminMessage() {
 	require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat()))
 
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldPersistMessage()
-	suite.shouldNotSendMessage()
+	suite.MessagePersisted(suite.mockApp.lastToAdmin)
+	suite.NoMessageSent()
+	suite.NextSenderMsgSeqNum(2)
 }
 
 func (suite *SessionSendTestSuite) TestSendAppMessage() {
@@ -336,8 +320,9 @@ func (suite *SessionSendTestSuite) TestSendAppMessage() {
 	require.Nil(suite.T(), suite.send(suite.NewOrderSingle()))
 
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldPersistMessage()
-	suite.shouldSendMessage()
+	suite.MessagePersisted(suite.mockApp.lastToApp)
+	suite.LastToAppMessageSent()
+	suite.NextSenderMsgSeqNum(2)
 }
 
 func (suite *SessionSendTestSuite) TestSendAppDoNotSendMessage() {
@@ -345,8 +330,8 @@ func (suite *SessionSendTestSuite) TestSendAppDoNotSendMessage() {
 	suite.Equal(DoNotSend, suite.send(suite.NewOrderSingle()))
 
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldNotPersistMessage()
-	suite.shouldNotSendMessage()
+	suite.NextSenderMsgSeqNum(1)
+	suite.NoMessageSent()
 }
 
 func (suite *SessionSendTestSuite) TestSendAdminMessage() {
@@ -354,8 +339,8 @@ func (suite *SessionSendTestSuite) TestSendAdminMessage() {
 	require.Nil(suite.T(), suite.send(suite.Heartbeat()))
 	suite.mockApp.AssertExpectations(suite.T())
 
-	suite.shouldPersistMessage()
-	suite.shouldSendMessage()
+	suite.LastToAdminMessageSent()
+	suite.MessagePersisted(suite.mockApp.lastToAdmin)
 }
 
 func (suite *SessionSendTestSuite) TestSendFlushesQueue() {
@@ -364,13 +349,20 @@ func (suite *SessionSendTestSuite) TestSendFlushesQueue() {
 	require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle()))
 	require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat()))
 
+	order1 := suite.mockApp.lastToApp
+	heartbeat := suite.mockApp.lastToAdmin
+
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldNotSendMessage()
+	suite.NoMessageSent()
 
 	suite.mockApp.On("ToApp").Return(nil)
 	require.Nil(suite.T(), suite.send(suite.NewOrderSingle()))
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldSendMessages(3)
+	order2 := suite.mockApp.lastToApp
+	suite.MessageSentEquals(order1)
+	suite.MessageSentEquals(heartbeat)
+	suite.MessageSentEquals(order2)
+	suite.NoMessageSent()
 }
 
 func (suite *SessionSendTestSuite) TestSendNotLoggedOn() {
@@ -380,7 +372,7 @@ func (suite *SessionSendTestSuite) TestSendNotLoggedOn() {
 	require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat()))
 
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldNotSendMessage()
+	suite.NoMessageSent()
 
 	var tests = []sessionState{logoutState{}, latentState{}, logonState{}}
 
@@ -389,7 +381,7 @@ func (suite *SessionSendTestSuite) TestSendNotLoggedOn() {
 		suite.sessionState = test
 		require.Nil(suite.T(), suite.send(suite.NewOrderSingle()))
 		suite.mockApp.AssertExpectations(suite.T())
-		suite.shouldNotSendMessage()
+		suite.NoMessageSent()
 	}
 }
 
@@ -398,8 +390,8 @@ func (suite *SessionSendTestSuite) TestDropAndSendAdminMessage() {
 	suite.Require().Nil(suite.dropAndSend(suite.Heartbeat(), false))
 	suite.mockApp.AssertExpectations(suite.T())
 
-	suite.shouldPersistMessage()
-	suite.shouldSendMessage()
+	suite.MessagePersisted(suite.mockApp.lastToAdmin)
+	suite.LastToAdminMessageSent()
 }
 
 func (suite *SessionSendTestSuite) TestDropAndSendDropsQueue() {
@@ -409,25 +401,19 @@ func (suite *SessionSendTestSuite) TestDropAndSendDropsQueue() {
 	require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat()))
 	suite.mockApp.AssertExpectations(suite.T())
 
-	suite.shouldNotSendMessage()
+	suite.NoMessageSent()
 
 	suite.mockApp.On("ToAdmin")
 	require.Nil(suite.T(), suite.dropAndSend(suite.Logon(), false))
 	suite.mockApp.AssertExpectations(suite.T())
 
 	msg := suite.mockApp.lastToAdmin
-	suite.shouldBeType(msg, enum.MsgType_LOGON)
-
-	seqNum, err := msg.Header.GetInt(tagMsgSeqNum)
-	suite.Nil(err)
-	suite.Equal(3, seqNum)
+	suite.MessageType(enum.MsgType_LOGON, msg)
+	suite.FieldEquals(tagMsgSeqNum, 3, msg.Header)
 
 	//only one message sent
-	sentMsgBytes := suite.receiver.LastMessage()
-	suite.NotNil(sentMsgBytes)
-	suite.shouldNotSendMessage()
-
-	suite.sentMessageShouldBe(sentMsgBytes, msg)
+	suite.LastToAdminMessageSent()
+	suite.NoMessageSent()
 }
 
 func (suite *SessionSendTestSuite) TestDropAndSendDropsQueueWithReset() {
@@ -436,22 +422,17 @@ func (suite *SessionSendTestSuite) TestDropAndSendDropsQueueWithReset() {
 	require.Nil(suite.T(), suite.queueForSend(suite.NewOrderSingle()))
 	require.Nil(suite.T(), suite.queueForSend(suite.Heartbeat()))
 	suite.mockApp.AssertExpectations(suite.T())
-	suite.shouldNotSendMessage()
+	suite.NoMessageSent()
 
 	suite.mockApp.On("ToAdmin")
 	require.Nil(suite.T(), suite.dropAndSend(suite.Logon(), true))
 	suite.mockApp.AssertExpectations(suite.T())
 	msg := suite.mockApp.lastToAdmin
 
-	suite.shouldBeType(msg, enum.MsgType_LOGON)
-	seqNum, err := msg.Header.GetInt(tagMsgSeqNum)
-	suite.Nil(err)
-	suite.Equal(1, seqNum)
+	suite.MessageType(enum.MsgType_LOGON, msg)
+	suite.FieldEquals(tagMsgSeqNum, 1, msg.Header)
 
 	//only one message sent
-	sentMsgBytes := suite.receiver.LastMessage()
-	suite.NotNil(sentMsgBytes)
-	suite.shouldNotSendMessage()
-
-	suite.sentMessageShouldBe(sentMsgBytes, msg)
+	suite.LastToAdminMessageSent()
+	suite.NoMessageSent()
 }
diff --git a/test_helpers.go b/test_helpers.go
index 75a9c9f6..093bfc99 100644
--- a/test_helpers.go
+++ b/test_helpers.go
@@ -44,6 +44,7 @@ type mockApp struct {
 	mock.Mock
 
 	lastToAdmin Message
+	lastToApp   Message
 }
 
 func (e *mockApp) OnCreate(sessionID SessionID) {
@@ -70,6 +71,7 @@ func (e *mockApp) ToAdmin(msg Message, sessionID SessionID) {
 }
 
 func (e *mockApp) ToApp(msg Message, sessionID SessionID) (err error) {
+	e.lastToApp = msg
 	return e.Called().Error(0)
 }
 
-- 
GitLab