Skip to content

Commit

Permalink
Merge pull request #195 from cbusbey/session_time
Browse files Browse the repository at this point in the history
Session time configuration
  • Loading branch information
cbusbey committed Aug 6, 2016
2 parents 88e283b + 47a65ae commit c2585ef
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 103 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ./...
Expand Down
2 changes: 2 additions & 0 deletions config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
51 changes: 51 additions & 0 deletions internal/time_range.go
Original file line number Diff line number Diff line change
@@ -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
}
60 changes: 60 additions & 0 deletions internal/time_range_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
41 changes: 36 additions & 5 deletions quickfix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
Expand All @@ -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() {
Expand All @@ -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)
}
29 changes: 29 additions & 0 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit c2585ef

Please sign in to comment.