Files
qfixdpl/quickfix/validation_test.go
2026-03-09 15:35:32 -03:00

1270 lines
42 KiB
Go
Raw Permalink 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"
"testing"
"time"
"github.com/stretchr/testify/assert"
"quantex.com/qfixdpl/quickfix/datadictionary"
)
type validateTest struct {
TestName string
Validator Validator
MessageBytes []byte
ExpectedRejectReason int
ExpectedRefTagID *Tag
DoNotExpectReject bool
}
func TestValidate(t *testing.T) {
var tests = []validateTest{
tcInvalidTagNumberHeader(),
tcInvalidTagNumberHeaderFixT(),
tcInvalidTagNumberBody(),
tcInvalidTagNumberBodyFixT(),
tcInvalidTagNumberTrailer(),
tcInvalidTagNumberTrailerFixT(),
tcTagSpecifiedWithoutAValue(),
tcTagSpecifiedWithoutAValueFixT(),
tcTagSpecifiedWithoutAValueValidateHasValues(),
tcTagSpecifiedWithoutAValueFixTValidateHasValues(),
tcTagSpecifiedWithoutAValueValidateHasValuesNoDataDictionary(),
tcInvalidMsgType(),
tcInvalidMsgTypeFixT(),
tcValueIsIncorrect(),
tcValueIsIncorrectFixT(),
tcIncorrectDataFormatForValue(),
tcIncorrectDataFormatForValueFixT(),
tcTagSpecifiedOutOfRequiredOrderHeader(),
tcTagSpecifiedOutOfRequiredOrderHeaderFixT(),
tcTagSpecifiedOutOfRequiredOrderTrailer(),
tcTagSpecifiedOutOfRequiredOrderTrailerFixT(),
tcTagSpecifiedOutOfRequiredOrderDisabledHeader(),
tcTagSpecifiedOutOfRequiredOrderDisabledHeaderFixT(),
tcTagSpecifiedOutOfRequiredOrderDisabledTrailer(),
tcTagSpecifiedOutOfRequiredOrderDisabledTrailerFixT(),
tcTagAppearsMoreThanOnce(),
tcTagAppearsMoreThanOnceFixT(),
tcFloatValidation(),
tcFloatValidationFixT(),
tcTagNotDefinedForMessage(),
tcTagNotDefinedForMessageFixT(),
tcTagIsDefinedForMessage(),
tcTagIsDefinedForMessageFixT(),
tcFieldNotFoundBody(),
tcFieldNotFoundBodyFixT(),
tcFieldNotFoundHeader(),
tcFieldNotFoundHeaderFixT(),
tcInvalidTagCheckDisabled(),
tcInvalidTagCheckDisabledFixT(),
tcInvalidTagCheckEnabled(),
tcInvalidTagCheckEnabledFixT(),
tcAllowUnknownMessageFieldsEnabled(),
tcAllowUnknownMessageFieldsEnabledFixT(),
tcAllowUnknownMessageFieldsDisabled(),
tcAllowUnknownMessageFieldsDisabledFixT(),
tcCheckUserDefinedFieldsEnabled(),
tcCheckUserDefinedFieldsEnabledFixT(),
tcCheckUserDefinedFieldsDisabled(),
tcCheckUserDefinedFieldsDisabledFixT(),
tcMultipleRepeatingGroupFields(),
}
msg := NewMessage()
for _, test := range tests {
assert.Nil(t, ParseMessage(msg, bytes.NewBuffer(test.MessageBytes)))
reject := test.Validator.Validate(msg)
switch {
case reject == nil && test.DoNotExpectReject:
continue
case reject != nil && test.DoNotExpectReject:
t.Errorf("%v: Unexpected reject: %v", test.TestName, reject)
continue
case reject == nil:
t.Errorf("%v: Expected reject", test.TestName)
continue
}
if reject.RejectReason() != test.ExpectedRejectReason {
t.Errorf("%v: Expected reason %v got %v", test.TestName, test.ExpectedRejectReason, reject.RejectReason())
}
switch {
case reject.RefTagID() == nil && test.ExpectedRefTagID == nil:
// OK, expected and actual ref tag not set.
case reject.RefTagID() != nil && test.ExpectedRefTagID == nil:
t.Errorf("%v: Unexpected RefTag '%v'", test.TestName, *reject.RefTagID())
case reject.RefTagID() == nil && test.ExpectedRefTagID != nil:
t.Errorf("%v: Expected RefTag '%v'", test.TestName, *test.ExpectedRefTagID)
case *reject.RefTagID() == *test.ExpectedRefTagID:
// OK, tags equal.
default:
t.Errorf("%v: Expected RefTag '%v' got '%v'", test.TestName, *test.ExpectedRefTagID, *reject.RefTagID())
}
}
}
func createFIX40NewOrderSingle() *Message {
msg := NewMessage()
msg.Header.SetField(tagMsgType, FIXString("D"))
msg.Header.SetField(tagBeginString, FIXString("FIX.4.0"))
msg.Header.SetField(tagBodyLength, FIXString("0"))
msg.Header.SetField(tagSenderCompID, FIXString("0"))
msg.Header.SetField(tagTargetCompID, FIXString("0"))
msg.Header.SetField(tagMsgSeqNum, FIXString("0"))
msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()})
msg.Body.SetField(Tag(11), FIXString("A"))
msg.Body.SetField(Tag(21), FIXString("1"))
msg.Body.SetField(Tag(55), FIXString("A"))
msg.Body.SetField(Tag(54), FIXString("1"))
msg.Body.SetField(Tag(40), FIXString("1"))
msg.Body.SetField(Tag(38), FIXInt(5))
msg.Body.SetField(Tag(100), FIXString("0"))
msg.Trailer.SetField(tagCheckSum, FIXString("000"))
return msg
}
func createFIX43NewOrderSingle() *Message {
msg := NewMessage()
msg.Header.SetField(tagMsgType, FIXString("D"))
msg.Header.SetField(tagBeginString, FIXString("FIX.4.3"))
msg.Header.SetField(tagBodyLength, FIXString("0"))
msg.Header.SetField(tagSenderCompID, FIXString("0"))
msg.Header.SetField(tagTargetCompID, FIXString("0"))
msg.Header.SetField(tagMsgSeqNum, FIXString("0"))
msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()})
msg.Body.SetField(Tag(11), FIXString("A"))
msg.Body.SetField(Tag(21), FIXString("1"))
msg.Body.SetField(Tag(55), FIXString("A"))
msg.Body.SetField(Tag(54), FIXString("1"))
msg.Body.SetField(Tag(38), FIXInt(5))
msg.Body.SetField(Tag(40), FIXString("1"))
msg.Body.SetField(Tag(60), FIXUTCTimestamp{Time: time.Now()})
msg.Trailer.SetField(tagCheckSum, FIXString("000"))
return msg
}
func createFIX50SP2NewOrderSingle() *Message {
msg := NewMessage()
msg.Header.SetField(tagMsgType, FIXString("D"))
msg.Header.SetField(tagBeginString, FIXString("FIXT.1.1"))
msg.Header.SetField(tagBodyLength, FIXString("0"))
msg.Header.SetField(tagSenderCompID, FIXString("0"))
msg.Header.SetField(tagTargetCompID, FIXString("0"))
msg.Header.SetField(tagMsgSeqNum, FIXString("0"))
msg.Header.SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()})
msg.Body.SetField(Tag(11), FIXString("A"))
msg.Body.SetField(Tag(21), FIXString("1"))
msg.Body.SetField(Tag(55), FIXString("A"))
msg.Body.SetField(Tag(54), FIXString("1"))
msg.Body.SetField(Tag(40), FIXString("1"))
msg.Body.SetField(Tag(38), FIXInt(5))
msg.Body.SetField(Tag(60), FIXUTCTimestamp{Time: time.Now(), Precision: Micros})
msg.Body.SetField(Tag(100), FIXString("0"))
msg.Trailer.SetField(tagCheckSum, FIXString("000"))
return msg
}
func tcInvalidTagNumberHeader() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidHeaderFieldMessage := createFIX40NewOrderSingle()
tag := Tag(9999)
invalidHeaderFieldMessage.Header.SetField(tag, FIXString("hello"))
msgBytes := invalidHeaderFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Header",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagNumberHeaderFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidHeaderFieldMessage := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
invalidHeaderFieldMessage.Header.SetField(tag, FIXString("hello"))
msgBytes := invalidHeaderFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Header FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagNumberBody() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidBodyFieldMessage := createFIX40NewOrderSingle()
tag := Tag(9999)
invalidBodyFieldMessage.Body.SetField(tag, FIXString("hello"))
msgBytes := invalidBodyFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Body",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagNumberBodyFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidBodyFieldMessage := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
invalidBodyFieldMessage.Body.SetField(tag, FIXString("hello"))
msgBytes := invalidBodyFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Body FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagNumberTrailer() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidTrailerFieldMessage := createFIX40NewOrderSingle()
tag := Tag(9999)
invalidTrailerFieldMessage.Trailer.SetField(tag, FIXString("hello"))
msgBytes := invalidTrailerFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Trailer",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagNumberTrailerFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidTrailerFieldMessage := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
invalidTrailerFieldMessage.Trailer.SetField(tag, FIXString("hello"))
msgBytes := invalidTrailerFieldMessage.build()
return validateTest{
TestName: "Invalid Tag Number Trailer FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidTagNumber,
ExpectedRefTagID: &tag,
}
}
func tcTagNotDefinedForMessage() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidMsg := createFIX40NewOrderSingle()
tag := Tag(41)
invalidMsg.Body.SetField(tag, FIXString("hello"))
msgBytes := invalidMsg.build()
return validateTest{
TestName: "Tag Not Defined For Message",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagNotDefinedForThisMessageType,
ExpectedRefTagID: &tag,
}
}
func tcTagNotDefinedForMessageFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidMsg := createFIX50SP2NewOrderSingle()
tag := Tag(41)
invalidMsg.Body.SetField(tag, FIXString("hello"))
msgBytes := invalidMsg.build()
return validateTest{
TestName: "Tag Not Defined For Message FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagNotDefinedForThisMessageType,
ExpectedRefTagID: &tag,
}
}
func tcTagIsDefinedForMessage() validateTest {
// Compare to `tcTagIsNotDefinedForMessage`.
dict, _ := datadictionary.Parse("spec/FIX43.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
validMsg := createFIX43NewOrderSingle()
msgBytes := validMsg.build()
return validateTest{
TestName: "TagIsDefinedForMessage",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagIsDefinedForMessageFixT() validateTest {
// Compare to `tcTagIsNotDefinedForMessage`.
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
validMsg := createFIX50SP2NewOrderSingle()
msgBytes := validMsg.build()
return validateTest{
TestName: "TagIsDefinedForMessage FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcFieldNotFoundBody() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidMsg1 := NewMessage()
invalidMsg1.Header.SetField(tagMsgType, FIXString("D")).
SetField(tagBeginString, FIXString("FIX.4.0")).
SetField(tagBodyLength, FIXString("0")).
SetField(tagSenderCompID, FIXString("0")).
SetField(tagTargetCompID, FIXString("0")).
SetField(tagMsgSeqNum, FIXString("0")).
SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()})
invalidMsg1.Trailer.SetField(tagCheckSum, FIXString("000"))
invalidMsg1.Body.SetField(Tag(11), FIXString("A")).
SetField(Tag(21), FIXString("A")).
SetField(Tag(55), FIXString("A")).
SetField(Tag(54), FIXString("A")).
SetField(Tag(38), FIXString("A"))
tag := Tag(40)
// Ord type is required. invalidMsg1.Body.SetField(Tag(40), "A")).
msgBytes := invalidMsg1.build()
return validateTest{
TestName: "FieldNotFoundBody",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonRequiredTagMissing,
ExpectedRefTagID: &tag,
}
}
func tcFieldNotFoundBodyFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidMsg1 := NewMessage()
invalidMsg1.Header.SetField(tagMsgType, FIXString("D")).
SetField(tagBeginString, FIXString("FIXT.1.1")).
SetField(tagBodyLength, FIXString("0")).
SetField(tagSenderCompID, FIXString("0")).
SetField(tagTargetCompID, FIXString("0")).
SetField(tagMsgSeqNum, FIXString("0")).
SetField(tagSendingTime, FIXUTCTimestamp{Time: time.Now()})
invalidMsg1.Trailer.SetField(tagCheckSum, FIXString("000"))
invalidMsg1.Body.SetField(Tag(11), FIXString("A")).
SetField(Tag(21), FIXString("A")).
SetField(Tag(55), FIXString("A")).
SetField(Tag(54), FIXString("A")).
SetField(Tag(38), FIXString("A")).
SetField(Tag(60), FIXUTCTimestamp{Time: time.Now()})
tag := Tag(40)
// Ord type is required. invalidMsg1.Body.SetField(Tag(40), "A")).
msgBytes := invalidMsg1.build()
return validateTest{
TestName: "FieldNotFoundBody FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonRequiredTagMissing,
ExpectedRefTagID: &tag,
}
}
func tcFieldNotFoundHeader() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
invalidMsg2 := NewMessage()
invalidMsg2.Trailer.SetField(tagCheckSum, FIXString("000"))
invalidMsg2.Body.SetField(Tag(11), FIXString("A")).
SetField(Tag(21), FIXString("A")).
SetField(Tag(55), FIXString("A")).
SetField(Tag(54), FIXString("A")).
SetField(Tag(38), FIXString("A"))
invalidMsg2.Header.SetField(tagMsgType, FIXString("D")).
SetField(tagBeginString, FIXString("FIX.4.0")).
SetField(tagBodyLength, FIXString("0")).
SetField(tagSenderCompID, FIXString("0")).
SetField(tagTargetCompID, FIXString("0")).
SetField(tagMsgSeqNum, FIXString("0"))
// Sending time is required. invalidMsg2.Header.FieldMap.SetField(tag.SendingTime, "0")).
tag := tagSendingTime
msgBytes := invalidMsg2.build()
return validateTest{
TestName: "FieldNotFoundHeader",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonRequiredTagMissing,
ExpectedRefTagID: &tag,
}
}
func tcFieldNotFoundHeaderFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
invalidMsg2 := NewMessage()
invalidMsg2.Trailer.SetField(tagCheckSum, FIXString("000"))
invalidMsg2.Body.SetField(Tag(11), FIXString("A")).
SetField(Tag(21), FIXString("A")).
SetField(Tag(55), FIXString("A")).
SetField(Tag(54), FIXString("A")).
SetField(Tag(38), FIXString("A"))
invalidMsg2.Header.SetField(tagMsgType, FIXString("D")).
SetField(tagBeginString, FIXString("FIXT.1.1")).
SetField(tagBodyLength, FIXString("0")).
SetField(tagSenderCompID, FIXString("0")).
SetField(tagTargetCompID, FIXString("0")).
SetField(tagMsgSeqNum, FIXString("0"))
// Sending time is required. invalidMsg2.Header.FieldMap.SetField(tag.SendingTime, "0")).
tag := tagSendingTime
msgBytes := invalidMsg2.build()
return validateTest{
TestName: "FieldNotFoundHeader FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonRequiredTagMissing,
ExpectedRefTagID: &tag,
}
}
func tcTagSpecifiedWithoutAValue() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
bogusTag := Tag(109)
builder.Body.SetField(bogusTag, FIXString(""))
msgBytes := builder.build()
return validateTest{
TestName: "Tag SpecifiedWithoutAValue",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue,
ExpectedRefTagID: &bogusTag,
}
}
func tcTagSpecifiedWithoutAValueValidateHasValues() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
settings := defaultValidatorSettings
settings.RejectInvalidMessage = false
settings.CheckFieldsHaveValues = true
validator := NewValidator(settings, dict, nil)
builder := createFIX40NewOrderSingle()
bogusTag := Tag(109)
builder.Body.SetField(bogusTag, FIXString(""))
msgBytes := builder.build()
return validateTest{
TestName: "Tag SpecifiedWithoutAValue",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue,
ExpectedRefTagID: &bogusTag,
}
}
func tcTagSpecifiedWithoutAValueValidateHasValuesNoDataDictionary() validateTest {
settings := defaultValidatorSettings
settings.RejectInvalidMessage = false
settings.CheckFieldsHaveValues = true
validator := NewValidator(settings, nil, nil)
builder := createFIX40NewOrderSingle()
bogusTag := Tag(109)
builder.Body.SetField(bogusTag, FIXString(""))
msgBytes := builder.build()
return validateTest{
TestName: "Tag SpecifiedWithoutAValue",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue,
ExpectedRefTagID: &bogusTag,
}
}
func tcTagSpecifiedWithoutAValueFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
bogusTag := Tag(109)
builder.Body.SetField(bogusTag, FIXString(""))
msgBytes := builder.build()
return validateTest{
TestName: "Tag SpecifiedWithoutAValue FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue,
ExpectedRefTagID: &bogusTag,
}
}
func tcTagSpecifiedWithoutAValueFixTValidateHasValues() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
bogusTag := Tag(109)
builder.Body.SetField(bogusTag, FIXString(""))
msgBytes := builder.build()
return validateTest{
TestName: "Tag SpecifiedWithoutAValue FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedWithoutAValue,
ExpectedRefTagID: &bogusTag,
}
}
func tcInvalidMsgType() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
builder.Header.SetField(tagMsgType, FIXString("z"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid MsgType",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidMsgType,
}
}
func tcInvalidMsgTypeFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
builder.Header.SetField(tagMsgType, FIXString("zz"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid MsgType FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonInvalidMsgType,
}
}
func tcValueIsIncorrect() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
tag := Tag(21)
builder := createFIX40NewOrderSingle()
builder.Body.SetField(tag, FIXString("4"))
msgBytes := builder.build()
return validateTest{
TestName: "ValueIsIncorrect",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonValueIsIncorrect,
ExpectedRefTagID: &tag,
}
}
func tcValueIsIncorrectFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
tag := Tag(21)
builder := createFIX50SP2NewOrderSingle()
builder.Body.SetField(tag, FIXString("4"))
msgBytes := builder.build()
return validateTest{
TestName: "ValueIsIncorrect FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonValueIsIncorrect,
ExpectedRefTagID: &tag,
}
}
func tcIncorrectDataFormatForValue() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(38)
builder.Body.SetField(tag, FIXString("+200.00"))
msgBytes := builder.build()
return validateTest{
TestName: "IncorrectDataFormatForValue",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue,
ExpectedRefTagID: &tag,
}
}
func tcIncorrectDataFormatForValueFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(38)
builder.Body.SetField(tag, FIXString("+200.00"))
msgBytes := builder.build()
return validateTest{
TestName: "IncorrectDataFormatForValue FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue,
ExpectedRefTagID: &tag,
}
}
func tcTagSpecifiedOutOfRequiredOrderHeader() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := tagOnBehalfOfCompID
// Should be in header.
builder.Body.SetField(tag, FIXString("CWB"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Header",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder,
ExpectedRefTagID: &tag,
}
}
func tcTagSpecifiedOutOfRequiredOrderHeaderFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := tagOnBehalfOfCompID
// Should be in header.
builder.Body.SetField(tag, FIXString("CWB"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Header FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder,
ExpectedRefTagID: &tag,
}
}
func tcTagSpecifiedOutOfRequiredOrderTrailer() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := tagSignature
// Should be in trailer.
builder.Body.SetField(tag, FIXString("SIG"))
msgBytes := builder.build()
refTag := Tag(100)
return validateTest{
TestName: "Tag specified out of required order in Trailer",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder,
ExpectedRefTagID: &refTag,
}
}
func tcTagSpecifiedOutOfRequiredOrderTrailerFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := tagSignature
// Should be in trailer.
builder.Body.SetField(tag, FIXString("SIG"))
msgBytes := builder.build()
refTag := Tag(100)
return validateTest{
TestName: "Tag specified out of required order in Trailer FIXT",
Validator: validator,
MessageBytes: msgBytes,
ExpectedRejectReason: rejectReasonTagSpecifiedOutOfRequiredOrder,
ExpectedRefTagID: &refTag,
}
}
func tcInvalidTagCheckDisabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = false
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid Tag Check - Disabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcInvalidTagCheckDisabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = false
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid Tag Check - Disabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcInvalidTagCheckEnabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = true
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid Tag Check - Enabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRefTagID: &tag,
}
}
func tcInvalidTagCheckEnabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = true
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Invalid Tag Check - Enabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRefTagID: &tag,
}
}
func tcAllowUnknownMessageFieldsEnabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.AllowUnknownMessageFields = true
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(41)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Allow Unknown Message Fields - Enabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcAllowUnknownMessageFieldsEnabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.AllowUnknownMessageFields = true
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(41)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Allow Unknown Message Fields - Enabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcAllowUnknownMessageFieldsDisabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.AllowUnknownMessageFields = false
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(41)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Allow Unknown Message Fields - Disabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRejectReason: rejectReasonTagNotDefinedForThisMessageType,
ExpectedRefTagID: &tag,
}
}
func tcAllowUnknownMessageFieldsDisabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = true
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(41)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Allow Unknown Message Fields - Disabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRejectReason: rejectReasonTagNotDefinedForThisMessageType,
ExpectedRefTagID: &tag,
}
}
func tcCheckUserDefinedFieldsEnabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckUserDefinedFields = true
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Check User Defined Fields - Enabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRefTagID: &tag,
}
}
func tcCheckUserDefinedFieldsEnabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.RejectInvalidMessage = true
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Check User Defined Fields - Enabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: false,
ExpectedRefTagID: &tag,
}
}
func tcCheckUserDefinedFieldsDisabled() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckUserDefinedFields = false
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Check User Defined Fields - Disabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcCheckUserDefinedFieldsDisabledFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckUserDefinedFields = false
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := Tag(9999)
builder.Body.SetField(tag, FIXString("hello"))
msgBytes := builder.build()
return validateTest{
TestName: "Check User Defined Fields - Disabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagSpecifiedOutOfRequiredOrderDisabledHeader() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckFieldsOutOfOrder = false
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := tagOnBehalfOfCompID
// Should be in header.
builder.Body.SetField(tag, FIXString("CWB"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Header - Disabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagSpecifiedOutOfRequiredOrderDisabledHeaderFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckFieldsOutOfOrder = false
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := tagOnBehalfOfCompID
// Should be in header.
builder.Body.SetField(tag, FIXString("CWB"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Header - Disabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagSpecifiedOutOfRequiredOrderDisabledTrailer() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckFieldsOutOfOrder = false
validator := NewValidator(customValidatorSettings, dict, nil)
builder := createFIX40NewOrderSingle()
tag := tagSignature
// Should be in trailer.
builder.Body.SetField(tag, FIXString("SIG"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Trailer - Disabled",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagSpecifiedOutOfRequiredOrderDisabledTrailerFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
customValidatorSettings := defaultValidatorSettings
customValidatorSettings.CheckFieldsOutOfOrder = false
validator := NewValidator(customValidatorSettings, appDict, tDict)
builder := createFIX50SP2NewOrderSingle()
tag := tagSignature
// Should be in trailer.
builder.Body.SetField(tag, FIXString("SIG"))
msgBytes := builder.build()
return validateTest{
TestName: "Tag specified out of required order in Trailer - Disabled FIXT",
Validator: validator,
MessageBytes: msgBytes,
DoNotExpectReject: true,
}
}
func tcTagAppearsMoreThanOnce() validateTest {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
tag := Tag(40)
return validateTest{
TestName: "Tag appears more than once",
Validator: validator,
MessageBytes: []byte("8=FIX.4.09=10735=D34=249=TW52=20060102-15:04:0556=ISLD11=ID21=140=140=254=138=20055=INTC60=20060102-15:04:0510=234"),
ExpectedRejectReason: rejectReasonTagAppearsMoreThanOnce,
ExpectedRefTagID: &tag,
}
}
func tcTagAppearsMoreThanOnceFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
tag := Tag(40)
return validateTest{
TestName: "Tag appears more than once FIXT",
Validator: validator,
MessageBytes: []byte("8=FIXT.1.19=10735=D34=249=TW52=20060102-15:04:0556=ISLD11=ID21=140=140=254=138=20055=INTC60=20060102-15:04:0510=234"),
ExpectedRejectReason: rejectReasonTagAppearsMoreThanOnce,
ExpectedRefTagID: &tag,
}
}
func tcFloatValidation() validateTest {
dict, _ := datadictionary.Parse("spec/FIX42.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
tag := Tag(38)
return validateTest{
TestName: "FloatValidation",
Validator: validator,
MessageBytes: []byte("8=FIX.4.29=10635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID21=140=154=138=+200.0055=INTC60=20140329-22:38:4510=178"),
ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue,
ExpectedRefTagID: &tag,
}
}
func tcFloatValidationFixT() validateTest {
tDict, _ := datadictionary.Parse("spec/FIXT11.xml")
appDict, _ := datadictionary.Parse("spec/FIX50SP2.xml")
validator := NewValidator(defaultValidatorSettings, appDict, tDict)
tag := Tag(38)
return validateTest{
TestName: "FloatValidation FIXT",
Validator: validator,
MessageBytes: []byte("8=FIXT.1.19=10635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID21=140=154=138=+200.0055=INTC60=20140329-22:38:4510=178"),
ExpectedRejectReason: rejectReasonIncorrectDataFormatForValue,
ExpectedRefTagID: &tag,
}
}
func tcMultipleRepeatingGroupFields() validateTest {
dict, _ := datadictionary.Parse("spec/FIX43.xml")
validator := NewValidator(defaultValidatorSettings, dict, nil)
return validateTest{
TestName: "Multiple repeating group fields in a message",
Validator: validator,
MessageBytes: []byte("8=FIX.4.39=17635=D34=249=TW52=20140329-22:38:4556=ISLD11=ID453=2448=PARTYID452=3523=SUBID448=PARTYID2452=378=179=ACCOUNT80=121=140=154=138=20055=INTC60=20140329-22:38:4510=178"),
DoNotExpectReject: true,
}
}
func TestValidateVisitField(t *testing.T) {
fieldType0 := datadictionary.NewFieldType("myfield", 11, "STRING")
fieldDef0 := &datadictionary.FieldDef{FieldType: fieldType0}
fieldType1 := datadictionary.NewFieldType("myfield", 2, "STRING")
fieldDef1 := &datadictionary.FieldDef{FieldType: fieldType1, Fields: []*datadictionary.FieldDef{}}
fieldType2 := datadictionary.NewFieldType("myfield", 3, "STRING")
fieldDef2 := &datadictionary.FieldDef{FieldType: fieldType2, Fields: []*datadictionary.FieldDef{}}
groupFieldType := datadictionary.NewFieldType("mygroupfield", 1, "INT")
groupFieldDef := &datadictionary.FieldDef{FieldType: groupFieldType, Fields: []*datadictionary.FieldDef{fieldDef1, fieldDef2}}
var field TagValue
field.init(Tag(11), []byte("value"))
var repField1 TagValue
var repField2 TagValue
repField1.init(Tag(2), []byte("a"))
repField2.init(Tag(3), []byte("a"))
var groupID TagValue
groupID.init(Tag(1), []byte("1"))
var groupID2 TagValue
groupID2.init(Tag(1), []byte("2"))
var groupID3 TagValue
groupID3.init(Tag(1), []byte("3"))
var tests = []struct {
fieldDef *datadictionary.FieldDef
fields []TagValue
expectedRemFields int
expectReject bool
expectedRejectReason int
}{
// Non-repeating.
{expectedRemFields: 0,
fieldDef: fieldDef0,
fields: []TagValue{field}},
// Single field group.
{expectedRemFields: 0,
fieldDef: groupFieldDef,
fields: []TagValue{groupID, repField1}},
// Multiple field group.
{expectedRemFields: 0,
fieldDef: groupFieldDef,
fields: []TagValue{groupID, repField1, repField2}},
// Test with trailing tag not in group.
{expectedRemFields: 1,
fieldDef: groupFieldDef,
fields: []TagValue{groupID, repField1, repField2, field}},
// Repeats.
{expectedRemFields: 1,
fieldDef: groupFieldDef,
fields: []TagValue{groupID2, repField1, repField2, repField1, repField2, field}},
// REJECT: group size declared > actual group size.
{expectReject: true,
fieldDef: groupFieldDef,
fields: []TagValue{groupID3, repField1, repField2, repField1, repField2, field},
expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup,
},
{expectReject: true,
fieldDef: groupFieldDef,
fields: []TagValue{groupID3, repField1, repField1, field},
expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup,
},
// REJECT: group size declared < actual group size.
{expectReject: true,
fieldDef: groupFieldDef,
fields: []TagValue{groupID, repField1, repField2, repField1, repField2, field},
expectedRejectReason: rejectReasonIncorrectNumInGroupCountForRepeatingGroup,
},
}
for _, test := range tests {
remFields, reject := validateVisitField(test.fieldDef, test.fields)
if test.expectReject {
if reject == nil {
t.Error("Expected Reject")
}
if reject.RejectReason() != test.expectedRejectReason {
t.Errorf("Expected reject reason %v got %v", test.expectedRejectReason, reject.RejectReason())
}
continue
}
if reject != nil {
t.Errorf("Unexpected reject: %v", reject)
}
if len(remFields) != test.expectedRemFields {
t.Errorf("Expected len %v got %v", test.expectedRemFields, len(remFields))
}
}
}