// 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 ( "bytes" "fmt" "testing" "github.com/stretchr/testify/suite" ) type MessageRouterTestSuite struct { suite.Suite *MessageRouter msg *Message sessionID SessionID returnReject MessageRejectError routedBy string routedSessionID SessionID routedMessage *Message } func TestMessageRouterTestSuite(t *testing.T) { suite.Run(t, new(MessageRouterTestSuite)) } func (suite *MessageRouterTestSuite) givenTheRoute(beginString, msgType string) { suite.AddRoute( beginString, msgType, func(msg *Message, sessionID SessionID) MessageRejectError { suite.routedBy = fmt.Sprintf("%v:%v", beginString, msgType) suite.routedSessionID = sessionID suite.routedMessage = msg return suite.returnReject }, ) } func (suite *MessageRouterTestSuite) givenTheMessage(msgBytes []byte) { err := ParseMessage(suite.msg, bytes.NewBuffer(msgBytes)) suite.Nil(err) var beginString FIXString suite.Require().Nil(suite.msg.Header.GetField(tagBeginString, &beginString)) var senderCompID FIXString suite.Require().Nil(suite.msg.Header.GetField(tagSenderCompID, &senderCompID)) var targetCompID FIXString suite.Require().Nil(suite.msg.Header.GetField(tagTargetCompID, &targetCompID)) suite.sessionID = SessionID{BeginString: string(beginString), SenderCompID: string(targetCompID), TargetCompID: string(senderCompID)} } func (suite *MessageRouterTestSuite) givenTargetDefaultApplVerIDForSession(defaultApplVerID string, sessionID SessionID) { s := &session{ sessionID: sessionID, targetDefaultApplVerID: defaultApplVerID, } suite.Nil(registerSession(s)) } func (suite *MessageRouterTestSuite) givenAFIX42NewOrderSingle() { suite.givenTheMessage([]byte("8=FIX.4.29=8735=D49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235")) } func (suite *MessageRouterTestSuite) givenAFIXTLogonMessage() { suite.givenTheMessage([]byte("8=FIXT.1.19=6335=A34=149=TW52=20160420-21:21:4956=ISLD98=0108=21137=810=105")) } func (suite *MessageRouterTestSuite) anticipateReject(rej MessageRejectError) { suite.returnReject = rej } func (suite *MessageRouterTestSuite) verifyMessageNotRouted() { suite.Equal("", suite.routedBy, "Message should not be routed") } func (suite *MessageRouterTestSuite) verifyMessageRoutedBy(beginString, msgType string) { suite.NotEqual("", suite.routedBy, "Message expected to be routed") suite.Equal(fmt.Sprintf("%v:%v", beginString, msgType), suite.routedBy) suite.Equal(suite.sessionID, suite.routedSessionID) suite.Equal(suite.msg.String(), suite.routedMessage.String()) } func (suite *MessageRouterTestSuite) resetRouter() { suite.MessageRouter = NewMessageRouter() suite.routedBy = "" suite.routedSessionID = SessionID{} suite.routedMessage = &Message{} suite.returnReject = nil } func (suite *MessageRouterTestSuite) SetupTest() { suite.resetRouter() sessionsLock.Lock() defer sessionsLock.Unlock() sessions = make(map[SessionID]*session) suite.msg = NewMessage() } func (suite *MessageRouterTestSuite) TestNoRoute() { suite.givenTheMessage([]byte("8=FIX.4.39=8735=D49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235")) rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageNotRouted() suite.Equal(NewBusinessMessageRejectError("Unsupported Message Type", 3, nil), rej) } func (suite *MessageRouterTestSuite) TestNoRouteWhitelistedMessageTypes() { var tests = []string{"0", "A", "1", "2", "3", "4", "5", "j"} for _, test := range tests { suite.SetupTest() msg := fmt.Sprintf("8=FIX.4.39=8735=%v49=TW34=356=ISLD52=20160421-14:43:5040=160=20160421-14:43:5054=121=311=id10=235", test) suite.givenTheMessage([]byte(msg)) rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageNotRouted() suite.Nil(rej, "Message type '%v' should not be rejected by the MessageRouter", test) } } func (suite *MessageRouterTestSuite) TestSimpleRoute() { suite.givenTheRoute(string(BeginStringFIX42), "D") suite.givenTheRoute(string(BeginStringFIXT11), "A") suite.givenAFIX42NewOrderSingle() rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(string(BeginStringFIX42), "D") suite.Nil(rej) } func (suite *MessageRouterTestSuite) TestSimpleRouteWithReject() { suite.givenTheRoute(string(BeginStringFIX42), "D") suite.givenTheRoute(string(BeginStringFIXT11), "A") suite.anticipateReject(NewMessageRejectError("some error", 5, nil)) suite.givenAFIX42NewOrderSingle() rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(string(BeginStringFIX42), "D") suite.Equal(suite.returnReject, rej) } func (suite *MessageRouterTestSuite) TestRouteFIXTAdminMessage() { suite.givenTheRoute(string(BeginStringFIX42), "D") suite.givenTheRoute(string(BeginStringFIXT11), "A") suite.givenAFIXTLogonMessage() rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(string(BeginStringFIXT11), "A") suite.Nil(rej) } func (suite *MessageRouterTestSuite) TestRouteFIXT50AppWithApplVerID() { suite.givenTheRoute(BeginStringFIX42, "D") suite.givenTheRoute(ApplVerIDFIX50, "D") suite.givenTheRoute(ApplVerIDFIX50SP1, "D") suite.givenTheMessage([]byte("8=FIXT.1.19=8935=D49=TW34=356=ISLD52=20160424-16:48:261128=740=160=20160424-16:48:2611=id21=310=120")) rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(ApplVerIDFIX50, "D") suite.Nil(rej) } func (suite *MessageRouterTestSuite) TestRouteFIXTAppWithApplVerID() { suite.givenTheRoute(BeginStringFIX42, "D") suite.givenTheRoute(ApplVerIDFIX50, "D") suite.givenTheRoute(ApplVerIDFIX50SP1, "D") suite.givenTheMessage([]byte("8=FIXT.1.19=8935=D49=TW34=356=ISLD52=20160424-16:48:261128=840=160=20160424-16:48:2611=id21=310=120")) rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(ApplVerIDFIX50SP1, "D") suite.Nil(rej) } func (suite *MessageRouterTestSuite) TestRouteFIXTAppWithDefaultApplVerID() { suite.givenTheRoute(BeginStringFIX42, "D") suite.givenTheRoute(ApplVerIDFIX50, "D") suite.givenTheRoute(ApplVerIDFIX50SP1, "D") suite.givenTargetDefaultApplVerIDForSession( "8", SessionID{BeginString: string(BeginStringFIXT11), SenderCompID: "ISLD", TargetCompID: "TW"}, ) suite.givenTheMessage([]byte("8=FIXT.1.19=8235=D49=TW34=356=ISLD52=20160424-16:48:2640=160=20160424-16:48:2611=id21=310=120")) rej := suite.Route(suite.msg, suite.sessionID) suite.verifyMessageRoutedBy(ApplVerIDFIX50SP1, "D") suite.Nil(rej) }