Files
qfixpt/quickfix/message_test.go
2026-03-12 12:08:34 -03:00

548 lines
24 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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"
"reflect"
"testing"
"github.com/stretchr/testify/suite"
"github.com/quickfixgo/quickfix/datadictionary"
)
func BenchmarkParseMessage(b *testing.B) {
rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039")
msg := NewMessage()
for i := 0; i < b.N; i++ {
_ = ParseMessage(msg, rawMsg)
}
}
type MessageSuite struct {
QuickFIXSuite
msg *Message
}
func TestMessageSuite(t *testing.T) {
suite.Run(t, new(MessageSuite))
}
func (s *MessageSuite) SetupTest() {
s.msg = NewMessage()
}
func TestXMLNonFIX(t *testing.T) {
rawMsg := bytes.NewBufferString("8=FIX.4.29=37235=n34=25512369=148152=20200522-07:05:33.75649=CME50=G56=OAEAAAN57=TRADE_CAPTURE143=US,IL212=261213=<RTRF>8=FIX.4.29=22535=BZ34=6549369=651852=20200522-07:05:33.74649=CME50=G56=9Q5000N57=DUMMY143=US,IL11=ACP159013113373460=20200522-07:05:33.734533=0893=Y1028=Y1300=991369=99612:325081373=31374=91375=15979=159013113373461769710=167</RTRF>10=245\"")
msg := NewMessage()
_ = ParseMessage(msg, rawMsg)
if !msg.Header.Has(tagXMLData) {
t.Error("Expected xmldata tag")
}
}
func (s *MessageSuite) TestParseMessageEmpty() {
rawMsg := bytes.NewBufferString("")
err := ParseMessage(s.msg, rawMsg)
s.NotNil(err)
}
func (s *MessageSuite) TestParseMessage() {
rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039")
err := ParseMessage(s.msg, rawMsg)
s.Nil(err)
s.True(bytes.Equal(rawMsg.Bytes(), s.msg.rawMessage.Bytes()), "Expected msg bytes to equal raw bytes")
expectedBodyBytes := []byte("11=10021=140=154=155=TSLA60=00010101-00:00:00.000")
s.True(bytes.Equal(s.msg.bodyBytes, expectedBodyBytes), "Incorrect body bytes, got %s", string(s.msg.bodyBytes))
s.Equal(14, len(s.msg.fields))
msgType, err := s.msg.MsgType()
s.Nil(err)
s.Equal("D", msgType)
s.True(s.msg.IsMsgTypeOf("D"))
s.False(s.msg.IsMsgTypeOf("A"))
}
func (s *MessageSuite) TestParseMessageWithDataDictionary() {
dict := new(datadictionary.DataDictionary)
dict.Header = &datadictionary.MessageDef{
Fields: map[int]*datadictionary.FieldDef{
10030: nil,
},
}
dict.Trailer = &datadictionary.MessageDef{
Fields: map[int]*datadictionary.FieldDef{
5050: nil,
},
}
rawMsg := bytes.NewBufferString("8=FIX.4.29=12635=D34=249=TW52=20140515-19:49:56.65956=ISLD10030=CUST11=10021=140=154=155=TSLA60=00010101-00:00:00.0005050=HELLO10=039")
err := ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict)
s.Nil(err)
s.FieldEquals(Tag(10030), "CUST", s.msg.Header)
s.FieldEquals(Tag(5050), "HELLO", s.msg.Trailer)
}
func (s *MessageSuite) TestParseOutOfOrder() {
// Allow fields out of order, save for validation.
rawMsg := bytes.NewBufferString("8=FIX.4.09=8135=D11=id21=338=10040=154=155=MSFT34=249=TW52=20140521-22:07:0956=ISLD10=250")
s.Nil(ParseMessage(s.msg, rawMsg))
}
func (s *MessageSuite) TestBuild() {
s.msg.Header.SetField(tagBeginString, FIXString(BeginStringFIX44))
s.msg.Header.SetField(tagMsgType, FIXString("A"))
s.msg.Header.SetField(tagSendingTime, FIXString("20140615-19:49:56"))
s.msg.Body.SetField(Tag(553), FIXString("my_user"))
s.msg.Body.SetField(Tag(554), FIXString("secret"))
expectedBytes := []byte("8=FIX.4.49=4935=A52=20140615-19:49:56553=my_user554=secret10=072")
result := s.msg.build()
s.True(bytes.Equal(expectedBytes, result), "Unexpected bytes, got %s", string(result))
}
func (s *MessageSuite) TestReBuild() {
rawMsg := bytes.NewBufferString("8=FIX.4.29=10435=D34=249=TW52=20140515-19:49:56.65956=ISLD11=10021=140=154=155=TSLA60=00010101-00:00:00.00010=039")
s.Nil(ParseMessage(s.msg, rawMsg))
s.msg.Header.SetField(tagOrigSendingTime, FIXString("20140515-19:49:56.659"))
s.msg.Header.SetField(tagSendingTime, FIXString("20140615-19:49:56"))
s.msg.Header.SetField(tagPossDupFlag, FIXBoolean(true))
rebuildBytes := s.msg.build()
expectedBytes := []byte("8=FIX.4.29=13135=D34=243=Y49=TW52=20140615-19:49:5656=ISLD122=20140515-19:49:56.65911=10021=140=154=155=TSLA60=00010101-00:00:00.00010=122")
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n +%s\n -%s", rebuildBytes, expectedBytes)
expectedBodyBytes := []byte("11=10021=140=154=155=TSLA60=00010101-00:00:00.000")
s.True(bytes.Equal(s.msg.bodyBytes, expectedBodyBytes), "Incorrect body bytes, got %s", string(s.msg.bodyBytes))
}
func (s *MessageSuite) TestRebuildOneRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 453 repeating group.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=16535=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41453=1448=4501447=D452=28" +
"10=026")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=16535=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41453=1448=4501447=D452=28" +
"10=026")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildTwoRepeatingGroupsWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 386 repeating group and a 453 repeating group.
rawMsg := bytes.NewBufferString("8=FIX.4.49=21035=D34=2347=UTF-852=20231231-20:19:4149=0100150=01001a56=TEST44=1211=139761=1010040021=1386=1336=NOPL55=SYMABC54=160=20231231-20:19:4138=140=259=0453=1448=4501447=D452=28354=6355=Public10=104")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte("8=FIX.4.49=21035=D34=249=0100150=01001a52=20231231-20:19:4156=TEST347=UTF-81=1010040011=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41354=6355=Public386=1336=NOPL453=1448=4501447=D452=2810=104")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildOneRepeatingGroupWithTwoMembersWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 453 repeating group that has 2 child groups.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=18735=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41453=2448=4501447=D452=28448=4502447=D452=28" +
"10=044")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=18735=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41453=2448=4501447=D452=28448=4502447=D452=28" +
"10=044")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildTwoSequentialRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with both a 78 and 453 repeating group that each have 2 child groups.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=21035=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=279=acct179=acct2453=2448=4501447=D452=28448=4502447=D452=28" +
"10=243")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=21035=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=279=acct179=acct2453=2448=4501447=D452=28448=4502447=D452=28" +
"10=243")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildNestedRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 78 repeating group that has
// a nested 539 group and then another 80 tag in the 78 group
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=17735=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid80=100" +
"10=206")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=17735=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid80=100" +
"10=206")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildDoubleNestedRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 78 repeating group that has a
// double nested 539 and then 804 groups and then another 80 tag in the 78 group
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=20235=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid80=100" +
"10=117")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=20235=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid80=100" +
"10=117")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildDoubleNestedThenAnotherRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 78 repeating group that has a double nested 539 and then 804 groups
// and then another repeating group 453 with two children.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=24535=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid453=2448=4501447=D452=28448=4502447=D452=28" +
"10=106")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=24535=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid453=2448=4501447=D452=28448=4502447=D452=28" +
"10=106")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildDoubleNestedThenBodyTagThenAnotherRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 78 repeating group that has a double nested 539 and then 804 groups
// then a 376 body tag and then another repeating group 453 with two children.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=25635=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid376=compid453=2448=4501447=D452=28448=4502447=D452=28" +
"10=198")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=25635=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:4178=179=acct1539=1524=nestedid804=1545=doublenestedid376=compid453=2448=4501447=D452=28448=4502447=D452=28" +
"10=198")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestRebuildDoubleNestedWithTwoMembersRepeatingGroupWithDictionary() {
dict, dictErr := datadictionary.Parse("spec/FIX44.xml")
s.Nil(dictErr)
// Given message bytes from a valid string with a 78 repeating group that
// has a double nested 539 and then 804 groups all with two children.
rawMsg := bytes.NewBufferString(
"8=FIX.4.49=40635=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41" +
"78=179=acct1" +
"539=2" +
"524=nestedid" +
"804=2" +
"545=doublenestedid" +
"545=doublenestedid2" +
"524=nestedid2" +
"804=2" +
"545=doublenestedid" +
"545=doublenestedid2" +
"79=acct2" +
"539=2" +
"524=nestedid" +
"804=2" +
"545=doublenestedid" +
"545=doublenestedid2" +
"524=nestedid2" +
"804=2" +
"545=doublenestedid" +
"545=doublenestedid2" +
"10=046")
// When we parse it into a message
s.Nil(ParseMessageWithDataDictionary(s.msg, rawMsg, dict, dict))
// And then rebuild the message bytes
rebuildBytes := s.msg.build()
expectedBytes := []byte(
"8=FIX.4.49=40635=D34=249=0100150=01001a52=20231231-20:19:4156=TEST" +
"1=acct111=1397621=138=140=244=1254=155=SYMABC59=060=20231231-20:19:41" +
"78=179=acct1539=2524=nestedid804=2545=doublenestedid545=doublenestedid2524=nestedid2804=2545=doublenestedid545=doublenestedid2" +
"79=acct2539=2524=nestedid804=2545=doublenestedid545=doublenestedid2524=nestedid2804=2545=doublenestedid545=doublenestedid2" +
"10=046")
// Then the bytes should have repeating groups properly ordered
s.True(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but got: %s", expectedBytes, rebuildBytes)
}
func (s *MessageSuite) TestReBuildWithRepeatingGroupForResend() {
// Given the following message with a repeating group
origHeader := "8=FIXT.1.19=16135=834=349=ISLD52=20240415-03:43:17.92356=TW"
origBody := "6=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=1448=xyzzy447=D452=1"
origTrailer := "10=014"
rawMsg := bytes.NewBufferString(origHeader + origBody + origTrailer)
// When I reparse the message from the store during a resend request
s.Nil(ParseMessage(s.msg, rawMsg))
// And I update the headers for resend
s.msg.Header.SetField(tagOrigSendingTime, FIXString("20240415-03:43:17.923"))
s.msg.Header.SetField(tagSendingTime, FIXString("20240415-14:41:23.456"))
s.msg.Header.SetField(tagPossDupFlag, FIXBoolean(true))
// When I rebuild the message
rebuildBytes := s.msg.build()
// Then the repeating groups will not be in the correct order in the rebuilt message (note tags 447, 448, 452, 453)
expectedBytes := []byte("8=FIXT.1.19=19235=834=343=Y49=ISLD52=20240415-14:41:23.45656=TW122=20240415-03:43:17.9236=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=1448=xyzzy447=D452=110=018")
s.False(bytes.Equal(expectedBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedBytes, rebuildBytes)
expectedOutOfOrderBytes := []byte("8=FIXT.1.19=19235=834=343=Y49=ISLD52=20240415-14:41:23.45656=TW122=20240415-03:43:17.9236=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00447=D448=xyzzy452=1453=110=018")
s.True(bytes.Equal(expectedOutOfOrderBytes, rebuildBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedOutOfOrderBytes, rebuildBytes)
// But the bodyBytes will still be correct
origBodyBytes := []byte(origBody)
s.True(bytes.Equal(origBodyBytes, s.msg.bodyBytes), "Incorrect body bytes, \n expected: %s\n but was: %s", origBodyBytes, s.msg.bodyBytes)
// So when I combine the updated header + the original bodyBytes + the as-is trailer
resendBytes := s.msg.buildWithBodyBytes(s.msg.bodyBytes)
// Then the reparsed, rebuilt message will retain the correct ordering of repeating group tags during resend
s.True(bytes.Equal(expectedBytes, resendBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedBytes, resendBytes)
}
func (s *MessageSuite) TestReBuildWithRepeatingGroupMultipleEntriesInGroupForResend() {
// Given the following message with a repeating group that has 2 entries
origHeader := "8=FIXT.1.19=18435=834=349=ISLD52=20240415-03:43:17.92356=TW"
origBody := "6=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=2448=xyzzy447=D452=1448=foobar447=D452=3"
origTrailer := "10=152"
rawMsg := bytes.NewBufferString(origHeader + origBody + origTrailer)
// When I reparse the message from the store during a resend request
s.Nil(ParseMessage(s.msg, rawMsg))
// And I update the headers for resend
s.msg.Header.SetField(tagOrigSendingTime, FIXString("20240415-03:43:17.923"))
s.msg.Header.SetField(tagSendingTime, FIXString("20240415-14:41:23.456"))
s.msg.Header.SetField(tagPossDupFlag, FIXBoolean(true))
// The bodyBytes will still be correct
origBodyBytes := []byte(origBody)
s.True(bytes.Equal(origBodyBytes, s.msg.bodyBytes), "Incorrect body bytes, \n expected: %s\n but was: %s", origBodyBytes, s.msg.bodyBytes)
// So when I combine the updated header + the original bodyBytes + the as-is trailer
resendBytes := s.msg.buildWithBodyBytes(origBodyBytes)
// Then the reparsed, rebuilt message will retain the correct ordering of repeating group tags during resend
expectedResendHeader := "8=FIXT.1.19=21535=834=343=Y49=ISLD52=20240415-14:41:23.45656=TW122=20240415-03:43:17.923"
expectedResendBody := "6=1.0011=114=1.0017=131=1.0032=1.0037=138=1.0039=254=155=1150=2151=0.00453=2448=xyzzy447=D452=1448=foobar447=D452=3"
expectedResendTrailer := "10=147"
expectedResendBytes := []byte(expectedResendHeader + expectedResendBody + expectedResendTrailer)
s.True(bytes.Equal(expectedResendBytes, resendBytes), "Unexpected bytes,\n expected: %s\n but was: %s", expectedResendBytes, resendBytes)
}
func (s *MessageSuite) TestReverseRoute() {
s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.29=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123")))
builder := s.msg.reverseRoute()
var testCases = []struct {
tag Tag
expectedValue string
}{
{tagTargetCompID, "TW"},
{tagTargetSubID, "KK"},
{tagTargetLocationID, "JV"},
{tagSenderCompID, "ISLD"},
{tagSenderSubID, "AP"},
{tagSenderLocationID, "RY"},
{tagDeliverToCompID, "JCD"},
{tagDeliverToSubID, "CS"},
{tagDeliverToLocationID, "BB"},
{tagOnBehalfOfCompID, "MG"},
{tagOnBehalfOfSubID, "CB"},
{tagOnBehalfOfLocationID, "BH"},
}
for _, tc := range testCases {
var field FIXString
s.Nil(builder.Header.GetField(tc.tag, &field))
s.Equal(tc.expectedValue, string(field))
}
}
func (s *MessageSuite) TestReverseRouteIgnoreEmpty() {
s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.09=12835=D34=249=TW52=20060102-15:04:0556=ISLD115=116=CS128=MG129=CB11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123")))
builder := s.msg.reverseRoute()
s.False(builder.Header.Has(tagDeliverToCompID), "Should not reverse if empty")
}
func (s *MessageSuite) TestReverseRouteFIX40() {
// The onbehalfof/deliverto location id not supported in fix 4.0.
s.Nil(ParseMessage(s.msg, bytes.NewBufferString("8=FIX.4.09=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123")))
builder := s.msg.reverseRoute()
s.False(builder.Header.Has(tagDeliverToLocationID), "delivertolocation id not supported in fix40")
s.False(builder.Header.Has(tagOnBehalfOfLocationID), "onbehalfof location id not supported in fix40")
}
func (s *MessageSuite) TestCopyIntoMessage() {
msgString := "8=FIX.4.29=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP144=BB115=JCD116=CS128=MG129=CB142=JV143=RY145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=123"
msgBuf := bytes.NewBufferString(msgString)
s.Nil(ParseMessage(s.msg, msgBuf))
dest := NewMessage()
s.msg.CopyInto(dest)
checkFieldInt(s, dest.Header.FieldMap, int(tagMsgSeqNum), 2)
checkFieldInt(s, dest.Body.FieldMap, 21, 3)
checkFieldString(s, dest.Body.FieldMap, 11, "ID")
s.Equal(len(dest.bodyBytes), len(s.msg.bodyBytes))
// copying decouples the message from its input buffer, so the raw message will be re-rendered
renderedString := "8=FIX.4.29=17135=D34=249=TW50=KK52=20060102-15:04:0556=ISLD57=AP115=JCD116=CS128=MG129=CB142=JV143=RY144=BB145=BH11=ID21=338=10040=w54=155=INTC60=20060102-15:04:0510=033"
s.Equal(dest.String(), renderedString)
s.True(reflect.DeepEqual(s.msg.bodyBytes, dest.bodyBytes))
s.True(s.msg.IsMsgTypeOf("D"))
s.Equal(s.msg.ReceiveTime, dest.ReceiveTime)
s.True(reflect.DeepEqual(s.msg.fields, dest.fields))
// update the source message to validate the copy is truly deep
newMsgString := "8=FIX.4.49=4935=A52=20140615-19:49:56553=my_user554=secret10=072"
s.Nil(ParseMessage(s.msg, bytes.NewBufferString(newMsgString)))
s.True(s.msg.IsMsgTypeOf("A"))
s.Equal(s.msg.String(), newMsgString)
s.Equal(string(s.msg.Bytes()), newMsgString)
// clear the source buffer also
msgBuf.Reset()
s.True(dest.IsMsgTypeOf("D"))
s.Equal(dest.String(), renderedString)
s.Equal(string(dest.Bytes()), renderedString)
}
func checkFieldInt(s *MessageSuite, fields FieldMap, tag, expected int) {
toCheck, _ := fields.GetInt(Tag(tag))
s.Equal(expected, toCheck)
}
func checkFieldString(s *MessageSuite, fields FieldMap, tag int, expected string) {
toCheck, err := fields.GetString(Tag(tag))
s.NoError(err)
s.Equal(expected, toCheck)
}