From 84b29568c0b6b71d2f3e69161b895f08b947bc4a Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 3 Nov 2023 00:55:45 +0000 Subject: [PATCH 1/9] Refactor external stores into packages --- .../testsuite/store_suite.go | 117 ++++++++--------- memorystore.go | 122 ++++++++++++++++++ session_test.go | 10 +- store.go | 99 +------------- filestore.go => store/file/filestore.go | 30 +++-- .../file/filestore_test.go | 14 +- store/file/util.go | 80 ++++++++++++ store/memory/memorystore_test.go | 40 ++++++ mongostore.go => store/mongo/mongostore.go | 41 +++--- .../mongo/mongostore_test.go | 20 +-- sqlstore.go => store/sql/sqlstore.go | 32 +++-- .../sql/sqlstore_test.go | 14 +- 12 files changed, 396 insertions(+), 223 deletions(-) rename store_test.go => internal/testsuite/store_suite.go (60%) create mode 100644 memorystore.go rename filestore.go => store/file/filestore.go (93%) rename filestore_test.go => store/file/filestore_test.go (82%) create mode 100644 store/file/util.go create mode 100644 store/memory/memorystore_test.go rename mongostore.go => store/mongo/mongostore.go (89%) rename mongostore_test.go => store/mongo/mongostore_test.go (74%) rename sqlstore.go => store/sql/sqlstore.go (92%) rename sqlstore_test.go => store/sql/sqlstore_test.go (85%) diff --git a/store_test.go b/internal/testsuite/store_suite.go similarity index 60% rename from store_test.go rename to internal/testsuite/store_suite.go index 075b3fd6c..4881e67cf 100644 --- a/store_test.go +++ b/internal/testsuite/store_suite.go @@ -13,87 +13,72 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package testsuite import ( - "testing" "time" + "github.com/quickfixgo/quickfix" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) -// MessageStoreTestSuite is the suite of all tests that should be run against all MessageStore implementations. -type MessageStoreTestSuite struct { +type StoreTestSuite struct { suite.Suite - msgStore MessageStore + MsgStore quickfix.MessageStore } -// MemoryStoreTestSuite runs all tests in the MessageStoreTestSuite against the MemoryStore implementation. -type MemoryStoreTestSuite struct { - MessageStoreTestSuite -} - -func (suite *MemoryStoreTestSuite) SetupTest() { - var err error - suite.msgStore, err = NewMemoryStoreFactory().Create(SessionID{}) - require.Nil(suite.T(), err) -} - -func TestMemoryStoreTestSuite(t *testing.T) { - suite.Run(t, new(MemoryStoreTestSuite)) -} -func (s *MessageStoreTestSuite) TestMessageStore_SetNextMsgSeqNum_Refresh_IncrNextMsgSeqNum() { +func (s *StoreTestSuite) TestMessageStore_SetNextMsgSeqNum_Refresh_IncrNextMsgSeqNum() { // Given a MessageStore with the following sender and target seqnums - s.Require().Nil(s.msgStore.SetNextSenderMsgSeqNum(867)) - s.Require().Nil(s.msgStore.SetNextTargetMsgSeqNum(5309)) + s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(867)) + s.Require().Nil(s.MsgStore.SetNextTargetMsgSeqNum(5309)) // When the store is refreshed from its backing store - s.Require().Nil(s.msgStore.Refresh()) + s.Require().Nil(s.MsgStore.Refresh()) // Then the sender and target seqnums should still be - s.Equal(867, s.msgStore.NextSenderMsgSeqNum()) - s.Equal(5309, s.msgStore.NextTargetMsgSeqNum()) + s.Equal(867, s.MsgStore.NextSenderMsgSeqNum()) + s.Equal(5309, s.MsgStore.NextTargetMsgSeqNum()) // When the sender and target seqnums are incremented - s.Require().Nil(s.msgStore.IncrNextSenderMsgSeqNum()) - s.Require().Nil(s.msgStore.IncrNextTargetMsgSeqNum()) + s.Require().Nil(s.MsgStore.IncrNextSenderMsgSeqNum()) + s.Require().Nil(s.MsgStore.IncrNextTargetMsgSeqNum()) // Then the sender and target seqnums should be - s.Equal(868, s.msgStore.NextSenderMsgSeqNum()) - s.Equal(5310, s.msgStore.NextTargetMsgSeqNum()) + s.Equal(868, s.MsgStore.NextSenderMsgSeqNum()) + s.Equal(5310, s.MsgStore.NextTargetMsgSeqNum()) // When the store is refreshed from its backing store - s.Require().Nil(s.msgStore.Refresh()) + s.Require().Nil(s.MsgStore.Refresh()) // Then the sender and target seqnums should still be - s.Equal(868, s.msgStore.NextSenderMsgSeqNum()) - s.Equal(5310, s.msgStore.NextTargetMsgSeqNum()) + s.Equal(868, s.MsgStore.NextSenderMsgSeqNum()) + s.Equal(5310, s.MsgStore.NextTargetMsgSeqNum()) } -func (s *MessageStoreTestSuite) TestMessageStore_Reset() { +func (s *StoreTestSuite) TestMessageStore_Reset() { // Given a MessageStore with the following sender and target seqnums - s.Require().Nil(s.msgStore.SetNextSenderMsgSeqNum(1234)) - s.Require().Nil(s.msgStore.SetNextTargetMsgSeqNum(5678)) + s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(1234)) + s.Require().Nil(s.MsgStore.SetNextTargetMsgSeqNum(5678)) // When the store is reset - s.Require().Nil(s.msgStore.Reset()) + s.Require().Nil(s.MsgStore.Reset()) // Then the sender and target seqnums should be - s.Equal(1, s.msgStore.NextSenderMsgSeqNum()) - s.Equal(1, s.msgStore.NextTargetMsgSeqNum()) + s.Equal(1, s.MsgStore.NextSenderMsgSeqNum()) + s.Equal(1, s.MsgStore.NextTargetMsgSeqNum()) // When the store is refreshed from its backing store - s.Require().Nil(s.msgStore.Refresh()) + s.Require().Nil(s.MsgStore.Refresh()) // Then the sender and target seqnums should still be - s.Equal(1, s.msgStore.NextSenderMsgSeqNum()) - s.Equal(1, s.msgStore.NextTargetMsgSeqNum()) + s.Equal(1, s.MsgStore.NextSenderMsgSeqNum()) + s.Equal(1, s.MsgStore.NextTargetMsgSeqNum()) } -func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { +func (s *StoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { // Given the following saved messages expectedMsgsBySeqNum := map[int]string{ 1: "In the frozen land of Nador", @@ -101,11 +86,11 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { 3: "and there was much rejoicing", } for seqNum, msg := range expectedMsgsBySeqNum { - s.Require().Nil(s.msgStore.SaveMessage(seqNum, []byte(msg))) + s.Require().Nil(s.MsgStore.SaveMessage(seqNum, []byte(msg))) } // When the messages are retrieved from the MessageStore - actualMsgs, err := s.msgStore.GetMessages(1, 3) + actualMsgs, err := s.MsgStore.GetMessages(1, 3) s.Require().Nil(err) // Then the messages should be @@ -115,10 +100,10 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) // When the store is refreshed from its backing store - s.Require().Nil(s.msgStore.Refresh()) + s.Require().Nil(s.MsgStore.Refresh()) // And the messages are retrieved from the MessageStore - actualMsgs, err = s.msgStore.GetMessages(1, 3) + actualMsgs, err = s.MsgStore.GetMessages(1, 3) s.Require().Nil(err) // Then the messages should still be @@ -128,8 +113,8 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } -func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() { - s.Require().Nil(s.msgStore.SetNextSenderMsgSeqNum(420)) +func (s *StoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() { + s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(420)) // Given the following saved messages expectedMsgsBySeqNum := map[int]string{ @@ -138,12 +123,12 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMes 3: "and there was much rejoicing", } for seqNum, msg := range expectedMsgsBySeqNum { - s.Require().Nil(s.msgStore.SaveMessageAndIncrNextSenderMsgSeqNum(seqNum, []byte(msg))) + s.Require().Nil(s.MsgStore.SaveMessageAndIncrNextSenderMsgSeqNum(seqNum, []byte(msg))) } - s.Equal(423, s.msgStore.NextSenderMsgSeqNum()) + s.Equal(423, s.MsgStore.NextSenderMsgSeqNum()) // When the messages are retrieved from the MessageStore - actualMsgs, err := s.msgStore.GetMessages(1, 3) + actualMsgs, err := s.MsgStore.GetMessages(1, 3) s.Require().Nil(err) // Then the messages should be @@ -153,13 +138,13 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMes s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) // When the store is refreshed from its backing store - s.Require().Nil(s.msgStore.Refresh()) + s.Require().Nil(s.MsgStore.Refresh()) // And the messages are retrieved from the MessageStore - actualMsgs, err = s.msgStore.GetMessages(1, 3) + actualMsgs, err = s.MsgStore.GetMessages(1, 3) s.Require().Nil(err) - s.Equal(423, s.msgStore.NextSenderMsgSeqNum()) + s.Equal(423, s.MsgStore.NextSenderMsgSeqNum()) // Then the messages should still be s.Require().Len(actualMsgs, 3) @@ -168,22 +153,22 @@ func (s *MessageStoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMes s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } -func (s *MessageStoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { +func (s *StoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { // When messages are retrieved from an empty store - messages, err := s.msgStore.GetMessages(1, 2) + messages, err := s.MsgStore.GetMessages(1, 2) require.Nil(s.T(), err) // Then no messages should be returned require.Empty(s.T(), messages, "Did not expect messages from empty store") } -func (s *MessageStoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { +func (s *StoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { t := s.T() // Given the following saved messages - require.Nil(t, s.msgStore.SaveMessage(1, []byte("hello"))) - require.Nil(t, s.msgStore.SaveMessage(2, []byte("cruel"))) - require.Nil(t, s.msgStore.SaveMessage(3, []byte("world"))) + require.Nil(t, s.MsgStore.SaveMessage(1, []byte("hello"))) + require.Nil(t, s.MsgStore.SaveMessage(2, []byte("cruel"))) + require.Nil(t, s.MsgStore.SaveMessage(3, []byte("world"))) // When the following requests are made to the store var testCases = []struct { @@ -203,7 +188,7 @@ func (s *MessageStoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { // Then the returned messages should be for _, tc := range testCases { - actualMsgs, err := s.msgStore.GetMessages(tc.beginSeqNo, tc.endSeqNo) + actualMsgs, err := s.MsgStore.GetMessages(tc.beginSeqNo, tc.endSeqNo) require.Nil(t, err) require.Len(t, actualMsgs, len(tc.expectedBytes)) for i, expectedMsg := range tc.expectedBytes { @@ -212,12 +197,12 @@ func (s *MessageStoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { } } -func (s *MessageStoreTestSuite) TestMessageStore_CreationTime() { - s.False(s.msgStore.CreationTime().IsZero()) +func (s *StoreTestSuite) TestMessageStore_CreationTime() { + s.False(s.MsgStore.CreationTime().IsZero()) t0 := time.Now() - s.Require().Nil(s.msgStore.Reset()) + s.Require().Nil(s.MsgStore.Reset()) t1 := time.Now() - s.Require().True(s.msgStore.CreationTime().After(t0)) - s.Require().True(s.msgStore.CreationTime().Before(t1)) + s.Require().True(s.MsgStore.CreationTime().After(t0)) + s.Require().True(s.MsgStore.CreationTime().Before(t1)) } diff --git a/memorystore.go b/memorystore.go new file mode 100644 index 000000000..8ea694030 --- /dev/null +++ b/memorystore.go @@ -0,0 +1,122 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + +package quickfix + +import ( + "time" + + "github.com/pkg/errors" +) + + +type memoryStore struct { + senderMsgSeqNum, targetMsgSeqNum int + creationTime time.Time + messageMap map[int][]byte +} + +func (store *memoryStore) NextSenderMsgSeqNum() int { + return store.senderMsgSeqNum + 1 +} + +func (store *memoryStore) NextTargetMsgSeqNum() int { + return store.targetMsgSeqNum + 1 +} + +func (store *memoryStore) IncrNextSenderMsgSeqNum() error { + store.senderMsgSeqNum++ + return nil +} + +func (store *memoryStore) IncrNextTargetMsgSeqNum() error { + store.targetMsgSeqNum++ + return nil +} + +func (store *memoryStore) SetNextSenderMsgSeqNum(nextSeqNum int) error { + store.senderMsgSeqNum = nextSeqNum - 1 + return nil +} +func (store *memoryStore) SetNextTargetMsgSeqNum(nextSeqNum int) error { + store.targetMsgSeqNum = nextSeqNum - 1 + return nil +} + +func (store *memoryStore) CreationTime() time.Time { + return store.creationTime +} + +func (store *memoryStore) SetCreationTime(t time.Time) { + store.creationTime = t +} + +func (store *memoryStore) Reset() error { + store.senderMsgSeqNum = 0 + store.targetMsgSeqNum = 0 + store.creationTime = time.Now() + store.messageMap = nil + return nil +} + +func (store *memoryStore) Refresh() error { + // NOP, nothing to refresh. + return nil +} + +func (store *memoryStore) Close() error { + // NOP, nothing to close. + return nil +} + +func (store *memoryStore) SaveMessage(seqNum int, msg []byte) error { + if store.messageMap == nil { + store.messageMap = make(map[int][]byte) + } + + store.messageMap[seqNum] = msg + return nil +} + +func (store *memoryStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { + err := store.SaveMessage(seqNum, msg) + if err != nil { + return err + } + return store.IncrNextSenderMsgSeqNum() +} + +func (store *memoryStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { + var msgs [][]byte + for seqNum := beginSeqNum; seqNum <= endSeqNum; seqNum++ { + if m, ok := store.messageMap[seqNum]; ok { + msgs = append(msgs, m) + } + } + return msgs, nil +} + +type memoryStoreFactory struct{} + +func (f memoryStoreFactory) Create(sessionID SessionID) (MessageStore, error) { + m := new(memoryStore) + if err := m.Reset(); err != nil { + return m, errors.Wrap(err, "reset") + } + return m, nil +} + +// NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores. +func NewMemoryStoreFactory() MessageStoreFactory { return memoryStoreFactory{} } diff --git a/session_test.go b/session_test.go index 415013a88..b9a70c9b5 100644 --- a/session_test.go +++ b/session_test.go @@ -346,13 +346,15 @@ func (s *SessionSuite) TestCheckSessionTimeInRange() { s.session.State = test.before now := time.Now().UTC() - store := new(memoryStore) + memStore, memErr := NewMemoryStoreFactory().Create(s.sessionID) + s.Require().Nil(memErr) + if test.before.IsSessionTime() { - s.Require().Nil(store.Reset()) + s.Require().Nil(memStore.Reset()) } else { - store.creationTime = now.Add(time.Duration(-1) * time.Minute) + memStore.SetCreationTime(now.Add(time.Duration(-1) * time.Minute)) } - s.session.store = store + s.session.store = memStore s.IncrNextSenderMsgSeqNum() s.IncrNextTargetMsgSeqNum() diff --git a/store.go b/store.go index c56e1896e..c693a0c04 100644 --- a/store.go +++ b/store.go @@ -17,8 +17,6 @@ package quickfix import ( "time" - - "github.com/pkg/errors" ) // The MessageStore interface provides methods to record and retrieve messages for resend purposes. @@ -33,6 +31,8 @@ type MessageStore interface { SetNextTargetMsgSeqNum(next int) error CreationTime() time.Time + SetCreationTime(time.Time) + SaveMessage(seqNum int, msg []byte) error SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error @@ -48,98 +48,3 @@ type MessageStore interface { type MessageStoreFactory interface { Create(sessionID SessionID) (MessageStore, error) } - -type memoryStore struct { - senderMsgSeqNum, targetMsgSeqNum int - creationTime time.Time - messageMap map[int][]byte -} - -func (store *memoryStore) NextSenderMsgSeqNum() int { - return store.senderMsgSeqNum + 1 -} - -func (store *memoryStore) NextTargetMsgSeqNum() int { - return store.targetMsgSeqNum + 1 -} - -func (store *memoryStore) IncrNextSenderMsgSeqNum() error { - store.senderMsgSeqNum++ - return nil -} - -func (store *memoryStore) IncrNextTargetMsgSeqNum() error { - store.targetMsgSeqNum++ - return nil -} - -func (store *memoryStore) SetNextSenderMsgSeqNum(nextSeqNum int) error { - store.senderMsgSeqNum = nextSeqNum - 1 - return nil -} -func (store *memoryStore) SetNextTargetMsgSeqNum(nextSeqNum int) error { - store.targetMsgSeqNum = nextSeqNum - 1 - return nil -} - -func (store *memoryStore) CreationTime() time.Time { - return store.creationTime -} - -func (store *memoryStore) Reset() error { - store.senderMsgSeqNum = 0 - store.targetMsgSeqNum = 0 - store.creationTime = time.Now() - store.messageMap = nil - return nil -} - -func (store *memoryStore) Refresh() error { - // NOP, nothing to refresh. - return nil -} - -func (store *memoryStore) Close() error { - // NOP, nothing to close. - return nil -} - -func (store *memoryStore) SaveMessage(seqNum int, msg []byte) error { - if store.messageMap == nil { - store.messageMap = make(map[int][]byte) - } - - store.messageMap[seqNum] = msg - return nil -} - -func (store *memoryStore) SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error { - err := store.SaveMessage(seqNum, msg) - if err != nil { - return err - } - return store.IncrNextSenderMsgSeqNum() -} - -func (store *memoryStore) GetMessages(beginSeqNum, endSeqNum int) ([][]byte, error) { - var msgs [][]byte - for seqNum := beginSeqNum; seqNum <= endSeqNum; seqNum++ { - if m, ok := store.messageMap[seqNum]; ok { - msgs = append(msgs, m) - } - } - return msgs, nil -} - -type memoryStoreFactory struct{} - -func (f memoryStoreFactory) Create(sessionID SessionID) (MessageStore, error) { - m := new(memoryStore) - if err := m.Reset(); err != nil { - return m, errors.Wrap(err, "reset") - } - return m, nil -} - -// NewMemoryStoreFactory returns a MessageStoreFactory instance that created in-memory MessageStores. -func NewMemoryStoreFactory() MessageStoreFactory { return memoryStoreFactory{} } diff --git a/filestore.go b/store/file/filestore.go similarity index 93% rename from filestore.go rename to store/file/filestore.go index a843bf881..48cb42da9 100644 --- a/filestore.go +++ b/store/file/filestore.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package file import ( "fmt" @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" + "github.com/quickfixgo/quickfix" "github.com/quickfixgo/quickfix/config" ) @@ -35,12 +36,12 @@ type msgDef struct { } type fileStoreFactory struct { - settings *Settings + settings *quickfix.Settings } type fileStore struct { - sessionID SessionID - cache *memoryStore + sessionID quickfix.SessionID + cache quickfix.MessageStore offsets map[int]msgDef bodyFname string headerFname string @@ -56,12 +57,12 @@ type fileStore struct { } // NewFileStoreFactory returns a file-based implementation of MessageStoreFactory. -func NewFileStoreFactory(settings *Settings) MessageStoreFactory { +func NewFileStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { return fileStoreFactory{settings: settings} } // Create creates a new FileStore implementation of the MessageStore interface. -func (f fileStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { +func (f fileStoreFactory) Create(sessionID quickfix.SessionID) (msgStore quickfix.MessageStore, err error) { globalSettings := f.settings.GlobalSettings() dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) @@ -92,16 +93,21 @@ func (f fileStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, er return newFileStore(sessionID, dirname, fsync) } -func newFileStore(sessionID SessionID, dirname string, fileSync bool) (*fileStore, error) { +func newFileStore(sessionID quickfix.SessionID, dirname string, fileSync bool) (*fileStore, error) { if err := os.MkdirAll(dirname, os.ModePerm); err != nil { return nil, err } - sessionPrefix := sessionIDFilenamePrefix(sessionID) + sessionPrefix := createFilenamePrefix(sessionID) + + memStore, memErr := quickfix.NewMemoryStoreFactory().Create(sessionID) + if memErr != nil { + return nil, errors.Wrap(memErr, "cache creation") + } store := &fileStore{ sessionID: sessionID, - cache: &memoryStore{}, + cache: memStore, offsets: make(map[int]msgDef), bodyFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "body")), headerFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "header")), @@ -209,7 +215,7 @@ func (store *fileStore) populateCache() (creationTimePopulated bool, err error) if timeBytes, err := os.ReadFile(store.sessionFname); err == nil { var ctime time.Time if err := ctime.UnmarshalText(timeBytes); err == nil { - store.cache.creationTime = ctime + store.cache.SetCreationTime(ctime) creationTimePopulated = true } } @@ -315,6 +321,10 @@ func (store *fileStore) CreationTime() time.Time { return store.cache.CreationTime() } +// SetCreationTime is a no-op for FileStore. +func (store *fileStore) SetCreationTime(_ time.Time) { +} + func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { offset, err := store.bodyFile.Seek(0, io.SeekEnd) if err != nil { diff --git a/filestore_test.go b/store/file/filestore_test.go similarity index 82% rename from filestore_test.go rename to store/file/filestore_test.go index efb6a9283..d3dd07a18 100644 --- a/filestore_test.go +++ b/store/file/filestore_test.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package file import ( "fmt" @@ -24,6 +24,8 @@ import ( "testing" "time" + "github.com/quickfixgo/quickfix" + "github.com/quickfixgo/quickfix/internal/testsuite" assert2 "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -31,17 +33,17 @@ import ( // FileStoreTestSuite runs all tests in the MessageStoreTestSuite against the FileStore implementation. type FileStoreTestSuite struct { - MessageStoreTestSuite + testsuite.StoreTestSuite fileStoreRootPath string } func (suite *FileStoreTestSuite) SetupTest() { suite.fileStoreRootPath = path.Join(os.TempDir(), fmt.Sprintf("FileStoreTestSuite-%d", os.Getpid())) fileStorePath := path.Join(suite.fileStoreRootPath, fmt.Sprintf("%d", time.Now().UnixNano())) - sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + sessionID := quickfix.SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} // create settings - settings, err := ParseSettings(strings.NewReader(fmt.Sprintf(` + settings, err := quickfix.ParseSettings(strings.NewReader(fmt.Sprintf(` [DEFAULT] FileStorePath=%s @@ -52,12 +54,12 @@ TargetCompID=%s`, fileStorePath, sessionID.BeginString, sessionID.SenderCompID, require.Nil(suite.T(), err) // create store - suite.msgStore, err = NewFileStoreFactory(settings).Create(sessionID) + suite.MsgStore, err = NewFileStoreFactory(settings).Create(sessionID) require.Nil(suite.T(), err) } func (suite *FileStoreTestSuite) TearDownTest() { - suite.msgStore.Close() + suite.MsgStore.Close() os.RemoveAll(suite.fileStoreRootPath) } diff --git a/store/file/util.go b/store/file/util.go new file mode 100644 index 000000000..8eb071c11 --- /dev/null +++ b/store/file/util.go @@ -0,0 +1,80 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + +package file + +import ( + "fmt" + "os" + "strings" + + "github.com/pkg/errors" + "github.com/quickfixgo/quickfix" +) + + +func createFilenamePrefix(s quickfix.SessionID) string { + sender := []string{s.SenderCompID} + if s.SenderSubID != "" { + sender = append(sender, s.SenderSubID) + } + if s.SenderLocationID != "" { + sender = append(sender, s.SenderLocationID) + } + + target := []string{s.TargetCompID} + if s.TargetSubID != "" { + target = append(target, s.TargetSubID) + } + if s.TargetLocationID != "" { + target = append(target, s.TargetLocationID) + } + + fname := []string{s.BeginString, strings.Join(sender, "_"), strings.Join(target, "_")} + if s.Qualifier != "" { + fname = append(fname, s.Qualifier) + } + return strings.Join(fname, "-") +} + +// closeFile behaves like Close, except that no error is returned if the file does not exist. +func closeFile(f *os.File) error { + if f != nil { + if err := f.Close(); err != nil { + if !os.IsNotExist(err) { + return err + } + } + } + return nil +} + +// removeFile behaves like os.Remove, except that no error is returned if the file does not exist. +func removeFile(fname string) error { + if err := os.Remove(fname); (err != nil) && !os.IsNotExist(err) { + return errors.Wrapf(err, "remove %v", fname) + } + return nil +} + +// openOrCreateFile opens a file for reading and writing, creating it if necessary. +func openOrCreateFile(fname string, perm os.FileMode) (f *os.File, err error) { + if f, err = os.OpenFile(fname, os.O_RDWR, perm); err != nil { + if f, err = os.OpenFile(fname, os.O_RDWR|os.O_CREATE, perm); err != nil { + return nil, fmt.Errorf("error opening or creating file: %s: %s", fname, err.Error()) + } + } + return f, nil +} diff --git a/store/memory/memorystore_test.go b/store/memory/memorystore_test.go new file mode 100644 index 000000000..d51079dc8 --- /dev/null +++ b/store/memory/memorystore_test.go @@ -0,0 +1,40 @@ +// Copyright (c) quickfixengine.org All rights reserved. +// +// This file may be distributed under the terms of the quickfixengine.org +// license as defined by quickfixengine.org and appearing in the file +// LICENSE included in the packaging of this file. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE. +// +// See http://www.quickfixengine.org/LICENSE for licensing information. +// +// Contact ask@quickfixengine.org if any conditions of this licensing +// are not clear to you. + +package memory + +import ( + "testing" + + "github.com/quickfixgo/quickfix" + "github.com/quickfixgo/quickfix/internal/testsuite" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +// MemoryStoreTestSuite runs all tests in the MessageStoreTestSuite against the MemoryStore implementation. +type MemoryStoreTestSuite struct { + testsuite.StoreTestSuite +} + +func (suite *MemoryStoreTestSuite) SetupTest() { + var err error + suite.MsgStore, err = quickfix.NewMemoryStoreFactory().Create(quickfix.SessionID{}) + require.Nil(suite.T(), err) +} + +func TestMemoryStoreTestSuite(t *testing.T) { + suite.Run(t, new(MemoryStoreTestSuite)) +} diff --git a/mongostore.go b/store/mongo/mongostore.go similarity index 89% rename from mongostore.go rename to store/mongo/mongostore.go index 7c61ef29f..a7e98023d 100644 --- a/mongostore.go +++ b/store/mongo/mongostore.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package mongo import ( "context" @@ -25,18 +25,19 @@ import ( "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" + "github.com/quickfixgo/quickfix" "github.com/quickfixgo/quickfix/config" ) type mongoStoreFactory struct { - settings *Settings + settings *quickfix.Settings messagesCollection string sessionsCollection string } type mongoStore struct { - sessionID SessionID - cache *memoryStore + sessionID quickfix.SessionID + cache quickfix.MessageStore mongoURL string mongoDatabase string db *mongo.Client @@ -45,13 +46,13 @@ type mongoStore struct { allowTransactions bool } -// NewMongoStoreFactory returns a mongo-based implementation of MessageStoreFactory. -func NewMongoStoreFactory(settings *Settings) MessageStoreFactory { - return NewMongoStoreFactoryPrefixed(settings, "") +// NewStoreFactory returns a mongo-based implementation of MessageStoreFactory. +func NewStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { + return NewStoreFactoryPrefixed(settings, "") } -// NewMongoStoreFactoryPrefixed returns a mongo-based implementation of MessageStoreFactory, with prefix on collections. -func NewMongoStoreFactoryPrefixed(settings *Settings, collectionsPrefix string) MessageStoreFactory { +// NewStoreFactoryPrefixed returns a mongo-based implementation of MessageStoreFactory, with prefix on collections. +func NewStoreFactoryPrefixed(settings *quickfix.Settings, collectionsPrefix string) quickfix.MessageStoreFactory { return mongoStoreFactory{ settings: settings, messagesCollection: collectionsPrefix + "messages", @@ -60,7 +61,7 @@ func NewMongoStoreFactoryPrefixed(settings *Settings, collectionsPrefix string) } // Create creates a new MongoStore implementation of the MessageStore interface. -func (f mongoStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { +func (f mongoStoreFactory) Create(sessionID quickfix.SessionID) (msgStore quickfix.MessageStore, err error) { globalSettings := f.settings.GlobalSettings() dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) @@ -87,12 +88,18 @@ func (f mongoStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, e return newMongoStore(sessionID, mongoConnectionURL, mongoDatabase, mongoReplicaSet, f.messagesCollection, f.sessionsCollection) } -func newMongoStore(sessionID SessionID, mongoURL, mongoDatabase, mongoReplicaSet, messagesCollection, sessionsCollection string) (store *mongoStore, err error) { +func newMongoStore(sessionID quickfix.SessionID, mongoURL, mongoDatabase, mongoReplicaSet, messagesCollection, sessionsCollection string) (store *mongoStore, err error) { + + memStore, memErr := quickfix.NewMemoryStoreFactory().Create(sessionID) + if memErr != nil { + err = errors.Wrap(memErr, "cache creation") + return + } allowTransactions := len(mongoReplicaSet) > 0 store = &mongoStore{ sessionID: sessionID, - cache: &memoryStore{}, + cache: memStore, mongoURL: mongoURL, mongoDatabase: mongoDatabase, messagesCollection: messagesCollection, @@ -116,7 +123,7 @@ func newMongoStore(sessionID SessionID, mongoURL, mongoDatabase, mongoReplicaSet return } -func generateMessageFilter(s *SessionID) (messageFilter *mongoQuickFixEntryData) { +func generateMessageFilter(s *quickfix.SessionID) (messageFilter *mongoQuickFixEntryData) { messageFilter = &mongoQuickFixEntryData{ BeginString: s.BeginString, SessionQualifier: s.Qualifier, @@ -193,7 +200,7 @@ func (store *mongoStore) populateCache() error { return errors.Wrap(err, "decode") } - store.cache.creationTime = sessionData.CreationTime + store.cache.SetCreationTime(sessionData.CreationTime) if err := store.cache.SetNextTargetMsgSeqNum(sessionData.IncomingSeqNum); err != nil { return errors.Wrap(err, "cache set next target") } @@ -206,7 +213,7 @@ func (store *mongoStore) populateCache() error { } // session record not found, create it - msgFilter.CreationTime = store.cache.creationTime + msgFilter.CreationTime = store.cache.CreationTime() msgFilter.IncomingSeqNum = store.cache.NextTargetMsgSeqNum() msgFilter.OutgoingSeqNum = store.cache.NextSenderMsgSeqNum() @@ -273,6 +280,10 @@ func (store *mongoStore) CreationTime() time.Time { return store.cache.CreationTime() } +// SetCreationTime is a no-op for MongoStore. +func (store *mongoStore) SetCreationTime(_ time.Time) { +} + func (store *mongoStore) SaveMessage(seqNum int, msg []byte) (err error) { msgFilter := generateMessageFilter(&store.sessionID) msgFilter.Msgseq = seqNum diff --git a/mongostore_test.go b/store/mongo/mongostore_test.go similarity index 74% rename from mongostore_test.go rename to store/mongo/mongostore_test.go index 4a8089f1c..62c487ba7 100644 --- a/mongostore_test.go +++ b/store/mongo/mongostore_test.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package mongo import ( "fmt" @@ -22,13 +22,15 @@ import ( "strings" "testing" + "github.com/quickfixgo/quickfix" + "github.com/quickfixgo/quickfix/internal/testsuite" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) -// MongoStoreTestSuite runs all tests in the MessageStoreTestSuite against the MongoStore implementation. +// MongoStoreTestSuite runs all tests in the message.StoreTestSuite against the MongoStore implementation. type MongoStoreTestSuite struct { - MessageStoreTestSuite + testsuite.StoreTestSuite } func (suite *MongoStoreTestSuite) SetupTest() { @@ -41,8 +43,8 @@ func (suite *MongoStoreTestSuite) SetupTest() { mongoReplicaSet := "replicaset" // create settings - sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} - settings, err := ParseSettings(strings.NewReader(fmt.Sprintf(` + sessionID := quickfix.SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + settings, err := quickfix.ParseSettings(strings.NewReader(fmt.Sprintf(` [DEFAULT] MongoStoreConnection=%s MongoStoreDatabase=%s @@ -55,15 +57,15 @@ TargetCompID=%s`, mongoDbCxn, mongoDatabase, mongoReplicaSet, sessionID.BeginStr require.Nil(suite.T(), err) // create store - suite.msgStore, err = NewMongoStoreFactory(settings).Create(sessionID) + suite.MsgStore, err = NewStoreFactory(settings).Create(sessionID) require.Nil(suite.T(), err) - err = suite.msgStore.Reset() + err = suite.MsgStore.Reset() require.Nil(suite.T(), err) } func (suite *MongoStoreTestSuite) TearDownTest() { - if suite.msgStore != nil { - err := suite.msgStore.Close() + if suite.MsgStore != nil { + err := suite.MsgStore.Close() require.Nil(suite.T(), err) } } diff --git a/sqlstore.go b/store/sql/sqlstore.go similarity index 92% rename from sqlstore.go rename to store/sql/sqlstore.go index 4483973ff..0097d7f19 100644 --- a/sqlstore.go +++ b/store/sql/sqlstore.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package sql import ( "database/sql" @@ -23,16 +23,17 @@ import ( "github.com/pkg/errors" + "github.com/quickfixgo/quickfix" "github.com/quickfixgo/quickfix/config" ) type sqlStoreFactory struct { - settings *Settings + settings *quickfix.Settings } type sqlStore struct { - sessionID SessionID - cache *memoryStore + sessionID quickfix.SessionID + cache quickfix.MessageStore sqlDriver string sqlDataSourceName string sqlConnMaxLifetime time.Duration @@ -61,12 +62,12 @@ func postgresPlaceholder(i int) string { } // NewSQLStoreFactory returns a sql-based implementation of MessageStoreFactory. -func NewSQLStoreFactory(settings *Settings) MessageStoreFactory { +func NewSQLStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { return sqlStoreFactory{settings: settings} } // Create creates a new SQLStore implementation of the MessageStore interface. -func (f sqlStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err error) { +func (f sqlStoreFactory) Create(sessionID quickfix.SessionID) (msgStore quickfix.MessageStore, err error) { globalSettings := f.settings.GlobalSettings() dynamicSessions, _ := globalSettings.BoolSetting(config.DynamicSessions) @@ -97,10 +98,17 @@ func (f sqlStoreFactory) Create(sessionID SessionID) (msgStore MessageStore, err return newSQLStore(sessionID, sqlDriver, sqlDataSourceName, sqlConnMaxLifetime) } -func newSQLStore(sessionID SessionID, driver string, dataSourceName string, connMaxLifetime time.Duration) (store *sqlStore, err error) { +func newSQLStore(sessionID quickfix.SessionID, driver string, dataSourceName string, connMaxLifetime time.Duration) (store *sqlStore, err error) { + + memStore, memErr := quickfix.NewMemoryStoreFactory().Create(sessionID) + if memErr != nil { + err = errors.Wrap(memErr, "cache creation") + return + } + store = &sqlStore{ sessionID: sessionID, - cache: &memoryStore{}, + cache: memStore, sqlDriver: driver, sqlDataSourceName: dataSourceName, sqlConnMaxLifetime: connMaxLifetime, @@ -185,7 +193,7 @@ func (store *sqlStore) populateCache() error { // session record found, load it if err == nil { - store.cache.creationTime = creationTime + store.cache.SetCreationTime(creationTime) if err = store.cache.SetNextTargetMsgSeqNum(incomingSeqNum); err != nil { return errors.Wrap(err, "cache set next target") } @@ -207,7 +215,7 @@ func (store *sqlStore) populateCache() error { sendercompid, sendersubid, senderlocid, targetcompid, targetsubid, targetlocid) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, store.placeholder), - store.cache.creationTime, + store.cache.CreationTime(), store.cache.NextTargetMsgSeqNum(), store.cache.NextSenderMsgSeqNum(), s.BeginString, s.Qualifier, @@ -280,6 +288,10 @@ func (store *sqlStore) CreationTime() time.Time { return store.cache.CreationTime() } +// SetCreationTime is a no-op for SQLStore. +func (store *sqlStore) SetCreationTime(_ time.Time) { +} + func (store *sqlStore) SaveMessage(seqNum int, msg []byte) error { s := store.sessionID diff --git a/sqlstore_test.go b/store/sql/sqlstore_test.go similarity index 85% rename from sqlstore_test.go rename to store/sql/sqlstore_test.go index 0b498c10a..1b4c1b0b7 100644 --- a/sqlstore_test.go +++ b/store/sql/sqlstore_test.go @@ -13,7 +13,7 @@ // Contact ask@quickfixengine.org if any conditions of this licensing // are not clear to you. -package quickfix +package sql import ( "database/sql" @@ -26,13 +26,15 @@ import ( "time" _ "github.com/mattn/go-sqlite3" + "github.com/quickfixgo/quickfix" + "github.com/quickfixgo/quickfix/internal/testsuite" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) // SqlStoreTestSuite runs all tests in the MessageStoreTestSuite against the SqlStore implementation. type SQLStoreTestSuite struct { - MessageStoreTestSuite + testsuite.StoreTestSuite sqlStoreRootPath string } @@ -56,8 +58,8 @@ func (suite *SQLStoreTestSuite) SetupTest() { } // create settings - sessionID := SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} - settings, err := ParseSettings(strings.NewReader(fmt.Sprintf(` + sessionID := quickfix.SessionID{BeginString: "FIX.4.4", SenderCompID: "SENDER", TargetCompID: "TARGET"} + settings, err := quickfix.ParseSettings(strings.NewReader(fmt.Sprintf(` [DEFAULT] SQLStoreDriver=%s SQLStoreDataSourceName=%s @@ -70,7 +72,7 @@ TargetCompID=%s`, sqlDriver, sqlDsn, sessionID.BeginString, sessionID.SenderComp require.Nil(suite.T(), err) // create store - suite.msgStore, err = NewSQLStoreFactory(settings).Create(sessionID) + suite.MsgStore, err = NewSQLStoreFactory(settings).Create(sessionID) require.Nil(suite.T(), err) } @@ -80,7 +82,7 @@ func (suite *SQLStoreTestSuite) TestSqlPlaceholderReplacement() { } func (suite *SQLStoreTestSuite) TearDownTest() { - suite.msgStore.Close() + suite.MsgStore.Close() os.RemoveAll(suite.sqlStoreRootPath) } From f3e51cc82e497e487fabb5639a0a52c5ef1d3666 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 3 Nov 2023 01:56:54 +0000 Subject: [PATCH 2/9] Corrects pkg refs --- _test/test-server/main.go | 5 +++-- store/file/filestore.go | 4 ++-- store/file/filestore_test.go | 2 +- store/sql/sqlstore.go | 4 ++-- store/sql/sqlstore_test.go | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/_test/test-server/main.go b/_test/test-server/main.go index e8a0eff3c..635c461a4 100644 --- a/_test/test-server/main.go +++ b/_test/test-server/main.go @@ -15,6 +15,7 @@ import ( "github.com/quickfixgo/quickfix/config" field "github.com/quickfixgo/quickfix/gen/field" tag "github.com/quickfixgo/quickfix/gen/tag" + "github.com/quickfixgo/quickfix/store/file" ) var router *quickfix.MessageRouter = quickfix.NewMessageRouter() @@ -156,9 +157,9 @@ func main() { appSettings.GlobalSettings().Set(config.FileStorePath, fileStorePath) appSettings.GlobalSettings().Set(config.DynamicSessions, "Y") - acceptor, err = quickfix.NewAcceptor(app, quickfix.NewFileStoreFactory(appSettings), appSettings, fileLogFactory) + acceptor, err = quickfix.NewAcceptor(app, file.NewStoreFactory(appSettings), appSettings, fileLogFactory) case "MEMORY": - acceptor, err = quickfix.NewAcceptor(app, quickfix.NewMemoryStoreFactory(), appSettings, fileLogFactory) + fallthrough default: acceptor, err = quickfix.NewAcceptor(app, quickfix.NewMemoryStoreFactory(), appSettings, fileLogFactory) } diff --git a/store/file/filestore.go b/store/file/filestore.go index 48cb42da9..f96f785bc 100644 --- a/store/file/filestore.go +++ b/store/file/filestore.go @@ -56,8 +56,8 @@ type fileStore struct { fileSync bool } -// NewFileStoreFactory returns a file-based implementation of MessageStoreFactory. -func NewFileStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { +// NewStoreFactory returns a file-based implementation of MessageStoreFactory. +func NewStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { return fileStoreFactory{settings: settings} } diff --git a/store/file/filestore_test.go b/store/file/filestore_test.go index d3dd07a18..ee0497828 100644 --- a/store/file/filestore_test.go +++ b/store/file/filestore_test.go @@ -54,7 +54,7 @@ TargetCompID=%s`, fileStorePath, sessionID.BeginString, sessionID.SenderCompID, require.Nil(suite.T(), err) // create store - suite.MsgStore, err = NewFileStoreFactory(settings).Create(sessionID) + suite.MsgStore, err = NewStoreFactory(settings).Create(sessionID) require.Nil(suite.T(), err) } diff --git a/store/sql/sqlstore.go b/store/sql/sqlstore.go index 0097d7f19..beb0f4a35 100644 --- a/store/sql/sqlstore.go +++ b/store/sql/sqlstore.go @@ -61,8 +61,8 @@ func postgresPlaceholder(i int) string { return fmt.Sprintf("$%d", i+1) } -// NewSQLStoreFactory returns a sql-based implementation of MessageStoreFactory. -func NewSQLStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { +// NewStoreFactory returns a sql-based implementation of MessageStoreFactory. +func NewStoreFactory(settings *quickfix.Settings) quickfix.MessageStoreFactory { return sqlStoreFactory{settings: settings} } diff --git a/store/sql/sqlstore_test.go b/store/sql/sqlstore_test.go index 1b4c1b0b7..9b2e8e689 100644 --- a/store/sql/sqlstore_test.go +++ b/store/sql/sqlstore_test.go @@ -72,7 +72,7 @@ TargetCompID=%s`, sqlDriver, sqlDsn, sessionID.BeginString, sessionID.SenderComp require.Nil(suite.T(), err) // create store - suite.MsgStore, err = NewSQLStoreFactory(settings).Create(sessionID) + suite.MsgStore, err = NewStoreFactory(settings).Create(sessionID) require.Nil(suite.T(), err) } From baa0d5cf143a467f570cf281ac21d4f9ee0ba561 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Thu, 2 Nov 2023 21:55:17 -0500 Subject: [PATCH 3/9] Change test cmd --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2f7390932..9d2f26817 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ vet: go vet `go list ./... | grep -v quickfix/gen` test: - MONGODB_TEST_CXN=mongodb://db:27017 go test -v -cover . ./datadictionary ./internal + MONGODB_TEST_CXN=mongodb://db:27017 go test -v -cover `go list ./... | grep -v quickfix/gen` linters-install: @golangci-lint --version >/dev/null 2>&1 || { \ @@ -62,7 +62,7 @@ build-src: build: build-src build-test-srv test-ci: - go test -v -cover . ./datadictionary ./internal + go test -v -cover `go list ./... | grep -v quickfix/gen` generate-ci: clean mkdir -p gen; cd gen; go run ../cmd/generate-fix/generate-fix.go -pkg-root=github.com/quickfixgo/quickfix/gen ../spec/$(shell echo $(FIX_TEST) | tr '[:lower:]' '[:upper:]').xml; From f5aaf1549e45845ea1ac7f165fa6bc45ad3917c8 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Fri, 3 Nov 2023 17:32:01 -0500 Subject: [PATCH 4/9] Adds ignore file --- store/memory/ignore.go | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 store/memory/ignore.go diff --git a/store/memory/ignore.go b/store/memory/ignore.go new file mode 100644 index 000000000..e596c0fd7 --- /dev/null +++ b/store/memory/ignore.go @@ -0,0 +1,3 @@ +package memory + +// This is a test-only package. This ignore file is intentional. \ No newline at end of file From 2721cc47f51f27ef1a89597d302b63041085d7e6 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Sun, 5 Nov 2023 22:08:13 -0600 Subject: [PATCH 5/9] Formatting --- fileutil.go | 22 ---------------------- internal/testsuite/store_suite.go | 15 +++++++-------- memorystore.go | 1 - store.go | 3 +-- store/file/filestore.go | 6 +++--- store/file/util.go | 1 - store/memory/ignore.go | 2 +- store/mongo/mongostore.go | 4 ++-- store/sql/sqlstore.go | 4 ++-- 9 files changed, 16 insertions(+), 42 deletions(-) diff --git a/fileutil.go b/fileutil.go index 0698a3a97..73bc4a6b2 100644 --- a/fileutil.go +++ b/fileutil.go @@ -19,8 +19,6 @@ import ( "fmt" "os" "strings" - - "github.com/pkg/errors" ) func sessionIDFilenamePrefix(s SessionID) string { @@ -47,26 +45,6 @@ func sessionIDFilenamePrefix(s SessionID) string { return strings.Join(fname, "-") } -// closeFile behaves like Close, except that no error is returned if the file does not exist. -func closeFile(f *os.File) error { - if f != nil { - if err := f.Close(); err != nil { - if !os.IsNotExist(err) { - return err - } - } - } - return nil -} - -// removeFile behaves like os.Remove, except that no error is returned if the file does not exist. -func removeFile(fname string) error { - if err := os.Remove(fname); (err != nil) && !os.IsNotExist(err) { - return errors.Wrapf(err, "remove %v", fname) - } - return nil -} - // openOrCreateFile opens a file for reading and writing, creating it if necessary. func openOrCreateFile(fname string, perm os.FileMode) (f *os.File, err error) { if f, err = os.OpenFile(fname, os.O_RDWR, perm); err != nil { diff --git a/internal/testsuite/store_suite.go b/internal/testsuite/store_suite.go index 4881e67cf..0563a5861 100644 --- a/internal/testsuite/store_suite.go +++ b/internal/testsuite/store_suite.go @@ -29,8 +29,7 @@ type StoreTestSuite struct { MsgStore quickfix.MessageStore } - -func (s *StoreTestSuite) TestMessageStore_SetNextMsgSeqNum_Refresh_IncrNextMsgSeqNum() { +func (s *StoreTestSuite) TestMessageStoreSetNextMsgSeqNumRefreshIncrNextMsgSeqNum() { // Given a MessageStore with the following sender and target seqnums s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(867)) s.Require().Nil(s.MsgStore.SetNextTargetMsgSeqNum(5309)) @@ -58,7 +57,7 @@ func (s *StoreTestSuite) TestMessageStore_SetNextMsgSeqNum_Refresh_IncrNextMsgSe s.Equal(5310, s.MsgStore.NextTargetMsgSeqNum()) } -func (s *StoreTestSuite) TestMessageStore_Reset() { +func (s *StoreTestSuite) TestMessageStoreReset() { // Given a MessageStore with the following sender and target seqnums s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(1234)) s.Require().Nil(s.MsgStore.SetNextTargetMsgSeqNum(5678)) @@ -78,7 +77,7 @@ func (s *StoreTestSuite) TestMessageStore_Reset() { s.Equal(1, s.MsgStore.NextTargetMsgSeqNum()) } -func (s *StoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { +func (s *StoreTestSuite) TestMessageStoreSaveMessageGetMessage() { // Given the following saved messages expectedMsgsBySeqNum := map[int]string{ 1: "In the frozen land of Nador", @@ -113,7 +112,7 @@ func (s *StoreTestSuite) TestMessageStore_SaveMessage_GetMessage() { s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } -func (s *StoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() { +func (s *StoreTestSuite) TestMessageStoreSaveMessageAndIncrementGetMessage() { s.Require().Nil(s.MsgStore.SetNextSenderMsgSeqNum(420)) // Given the following saved messages @@ -153,7 +152,7 @@ func (s *StoreTestSuite) TestMessageStore_SaveMessage_AndIncrement_GetMessage() s.Equal(expectedMsgsBySeqNum[3], string(actualMsgs[2])) } -func (s *StoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { +func (s *StoreTestSuite) TestMessageStoreGetMessagesEmptyStore() { // When messages are retrieved from an empty store messages, err := s.MsgStore.GetMessages(1, 2) require.Nil(s.T(), err) @@ -162,7 +161,7 @@ func (s *StoreTestSuite) TestMessageStore_GetMessages_EmptyStore() { require.Empty(s.T(), messages, "Did not expect messages from empty store") } -func (s *StoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { +func (s *StoreTestSuite) TestMessageStoreGetMessagesVariousRanges() { t := s.T() // Given the following saved messages @@ -197,7 +196,7 @@ func (s *StoreTestSuite) TestMessageStore_GetMessages_VariousRanges() { } } -func (s *StoreTestSuite) TestMessageStore_CreationTime() { +func (s *StoreTestSuite) TestMessageStoreCreationTime() { s.False(s.MsgStore.CreationTime().IsZero()) t0 := time.Now() diff --git a/memorystore.go b/memorystore.go index 8ea694030..5773f09b5 100644 --- a/memorystore.go +++ b/memorystore.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" ) - type memoryStore struct { senderMsgSeqNum, targetMsgSeqNum int creationTime time.Time diff --git a/store.go b/store.go index c693a0c04..34e2570e4 100644 --- a/store.go +++ b/store.go @@ -31,8 +31,7 @@ type MessageStore interface { SetNextTargetMsgSeqNum(next int) error CreationTime() time.Time - SetCreationTime(time.Time) - + SetCreationTime(time.Time) SaveMessage(seqNum int, msg []byte) error SaveMessageAndIncrNextSenderMsgSeqNum(seqNum int, msg []byte) error diff --git a/store/file/filestore.go b/store/file/filestore.go index f96f785bc..ffc6bca8e 100644 --- a/store/file/filestore.go +++ b/store/file/filestore.go @@ -103,11 +103,11 @@ func newFileStore(sessionID quickfix.SessionID, dirname string, fileSync bool) ( memStore, memErr := quickfix.NewMemoryStoreFactory().Create(sessionID) if memErr != nil { return nil, errors.Wrap(memErr, "cache creation") - } + } store := &fileStore{ sessionID: sessionID, - cache: memStore, + cache: memStore, offsets: make(map[int]msgDef), bodyFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "body")), headerFname: path.Join(dirname, fmt.Sprintf("%s.%s", sessionPrefix, "header")), @@ -322,7 +322,7 @@ func (store *fileStore) CreationTime() time.Time { } // SetCreationTime is a no-op for FileStore. -func (store *fileStore) SetCreationTime(_ time.Time) { +func (store *fileStore) SetCreationTime(_ time.Time) { } func (store *fileStore) SaveMessage(seqNum int, msg []byte) error { diff --git a/store/file/util.go b/store/file/util.go index 8eb071c11..d181e8c27 100644 --- a/store/file/util.go +++ b/store/file/util.go @@ -24,7 +24,6 @@ import ( "github.com/quickfixgo/quickfix" ) - func createFilenamePrefix(s quickfix.SessionID) string { sender := []string{s.SenderCompID} if s.SenderSubID != "" { diff --git a/store/memory/ignore.go b/store/memory/ignore.go index e596c0fd7..0ba886d49 100644 --- a/store/memory/ignore.go +++ b/store/memory/ignore.go @@ -1,3 +1,3 @@ package memory -// This is a test-only package. This ignore file is intentional. \ No newline at end of file +// This is a test-only package. This ignore file is intentional. diff --git a/store/mongo/mongostore.go b/store/mongo/mongostore.go index a7e98023d..5af278e10 100644 --- a/store/mongo/mongostore.go +++ b/store/mongo/mongostore.go @@ -94,7 +94,7 @@ func newMongoStore(sessionID quickfix.SessionID, mongoURL, mongoDatabase, mongoR if memErr != nil { err = errors.Wrap(memErr, "cache creation") return - } + } allowTransactions := len(mongoReplicaSet) > 0 store = &mongoStore{ @@ -281,7 +281,7 @@ func (store *mongoStore) CreationTime() time.Time { } // SetCreationTime is a no-op for MongoStore. -func (store *mongoStore) SetCreationTime(_ time.Time) { +func (store *mongoStore) SetCreationTime(_ time.Time) { } func (store *mongoStore) SaveMessage(seqNum int, msg []byte) (err error) { diff --git a/store/sql/sqlstore.go b/store/sql/sqlstore.go index beb0f4a35..91261fdcd 100644 --- a/store/sql/sqlstore.go +++ b/store/sql/sqlstore.go @@ -104,7 +104,7 @@ func newSQLStore(sessionID quickfix.SessionID, driver string, dataSourceName str if memErr != nil { err = errors.Wrap(memErr, "cache creation") return - } + } store = &sqlStore{ sessionID: sessionID, @@ -289,7 +289,7 @@ func (store *sqlStore) CreationTime() time.Time { } // SetCreationTime is a no-op for SQLStore. -func (store *sqlStore) SetCreationTime(_ time.Time) { +func (store *sqlStore) SetCreationTime(_ time.Time) { } func (store *sqlStore) SaveMessage(seqNum int, msg []byte) error { From f74aa0fd7dafbc486449b132156fdc97efa8be5a Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Sun, 5 Nov 2023 22:23:37 -0600 Subject: [PATCH 6/9] goimports ormatting --- .golangci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index cf2a5fff9..b1bd0cccd 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,7 +22,5 @@ linters: linters-settings: gofmt: simplify: true - goimports: - local-prefixes: github.com/quickfixgo/quickfix dupl: threshold: 400 \ No newline at end of file From fdfb638a03055f21f10202b6ce21408f90a36ce3 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Sun, 5 Nov 2023 23:13:13 -0600 Subject: [PATCH 7/9] sql store test pathing --- store/sql/sqlstore_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/sql/sqlstore_test.go b/store/sql/sqlstore_test.go index 9b2e8e689..73c1d747a 100644 --- a/store/sql/sqlstore_test.go +++ b/store/sql/sqlstore_test.go @@ -48,7 +48,7 @@ func (suite *SQLStoreTestSuite) SetupTest() { // create tables db, err := sql.Open(sqlDriver, sqlDsn) require.Nil(suite.T(), err) - ddlFnames, err := filepath.Glob(fmt.Sprintf("_sql/%s/*.sql", sqlDriver)) + ddlFnames, err := filepath.Glob(fmt.Sprintf("../../_sql/%s/*.sql", sqlDriver)) require.Nil(suite.T(), err) for _, fname := range ddlFnames { sqlBytes, err := os.ReadFile(fname) From 147ca485be2d112a52b27da7cab3bd3b09e4f72f Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Wed, 8 Nov 2023 19:13:49 -0600 Subject: [PATCH 8/9] Corrects mongo pkg ref in test --- _test/test-server/main.go | 3 ++- store/file/filestore.go | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/_test/test-server/main.go b/_test/test-server/main.go index 635c461a4..b80bd4d6c 100644 --- a/_test/test-server/main.go +++ b/_test/test-server/main.go @@ -16,6 +16,7 @@ import ( field "github.com/quickfixgo/quickfix/gen/field" tag "github.com/quickfixgo/quickfix/gen/tag" "github.com/quickfixgo/quickfix/store/file" + "github.com/quickfixgo/quickfix/store/mongo" ) var router *quickfix.MessageRouter = quickfix.NewMessageRouter() @@ -150,7 +151,7 @@ func main() { appSettings.GlobalSettings().Set(config.MongoStoreReplicaSet, mongoReplicaSet) appSettings.GlobalSettings().Set(config.DynamicSessions, "Y") - acceptor, err = quickfix.NewAcceptor(app, quickfix.NewMongoStoreFactory(appSettings), appSettings, fileLogFactory) + acceptor, err = quickfix.NewAcceptor(app, mongo.NewStoreFactory(appSettings), appSettings, fileLogFactory) case "FILE": fileStoreRootPath := path.Join(os.TempDir(), fmt.Sprintf("FileStoreTestSuite-%d", os.Getpid())) fileStorePath := path.Join(fileStoreRootPath, fmt.Sprintf("%d", time.Now().UnixNano())) diff --git a/store/file/filestore.go b/store/file/filestore.go index ffc6bca8e..34aebb6e0 100644 --- a/store/file/filestore.go +++ b/store/file/filestore.go @@ -77,9 +77,7 @@ func (f fileStoreFactory) Create(sessionID quickfix.SessionID) (msgStore quickfi dirname, err := sessionSettings.Setting(config.FileStorePath) if err != nil { - if err != nil { return nil, err - } } var fsync bool if sessionSettings.HasSetting(config.FileStoreSync) { From 779361559c964a3ca8f6c30e03903401dc6e4798 Mon Sep 17 00:00:00 2001 From: Michael Ackley Date: Wed, 8 Nov 2023 19:46:01 -0600 Subject: [PATCH 9/9] Fmt fix --- store/file/filestore.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/file/filestore.go b/store/file/filestore.go index 34aebb6e0..4a3dadb5d 100644 --- a/store/file/filestore.go +++ b/store/file/filestore.go @@ -77,7 +77,7 @@ func (f fileStoreFactory) Create(sessionID quickfix.SessionID) (msgStore quickfi dirname, err := sessionSettings.Setting(config.FileStorePath) if err != nil { - return nil, err + return nil, err } var fsync bool if sessionSettings.HasSetting(config.FileStoreSync) {