diff --git a/validation.go b/validation.go index 82b535aca..29cd9534e 100644 --- a/validation.go +++ b/validation.go @@ -16,6 +16,8 @@ package quickfix import ( + "bytes" + "github.com/quickfixgo/quickfix/datadictionary" ) @@ -385,10 +387,21 @@ func validateField(d *datadictionary.DataDictionary, return nil } - allowedValues := d.FieldTypeByTag[int(field.tag)].Enums + allowedValues := fieldType.Enums if len(allowedValues) != 0 { - if _, validValue := allowedValues[string(field.value)]; !validValue { - return ValueIsIncorrect(field.tag) + switch fieldType.Type { + case "MULTIPLESTRINGVALUE", "MULTIPLEVALUESTRING", "MULTIPLECHARVALUE": + // These fields carry a space-delimited set of enum tokens, each of + // which must be individually valid (e.g. ExecInst "1 5" = two enums). + for _, component := range bytes.Split(field.value, []byte{' '}) { + if _, validValue := allowedValues[string(component)]; !validValue { + return ValueIsIncorrect(field.tag) + } + } + default: + if _, validValue := allowedValues[string(field.value)]; !validValue { + return ValueIsIncorrect(field.tag) + } } } diff --git a/validation_test.go b/validation_test.go index 7973464d1..7c1360ab2 100644 --- a/validation_test.go +++ b/validation_test.go @@ -86,6 +86,8 @@ func TestValidate(t *testing.T) { tcCheckUserDefinedFieldsDisabled(), tcCheckUserDefinedFieldsDisabledFixT(), tcMultipleRepeatingGroupFields(), + tcMultiValueEnumValid(), + tcMultiValueEnumInvalidComponent(), } msg := NewMessage() @@ -662,6 +664,42 @@ func tcValueIsIncorrectFixT() validateTest { } } +func tcMultiValueEnumValid() validateTest { + dict, _ := datadictionary.Parse("spec/FIX43.xml") + validator := NewValidator(defaultValidatorSettings, dict, nil) + + // ExecInst (tag 18) is a MULTIPLEVALUESTRING: a space-delimited set of + // individually-valid enum tokens (e.g. "Y M") must be accepted. + builder := createFIX43NewOrderSingle() + builder.Body.SetField(Tag(18), FIXString("Y M")) + msgBytes := builder.build() + + return validateTest{ + TestName: "Multi-value enum valid", + Validator: validator, + MessageBytes: msgBytes, + DoNotExpectReject: true, + } +} + +func tcMultiValueEnumInvalidComponent() validateTest { + dict, _ := datadictionary.Parse("spec/FIX43.xml") + validator := NewValidator(defaultValidatorSettings, dict, nil) + + tag := Tag(18) + builder := createFIX43NewOrderSingle() + builder.Body.SetField(tag, FIXString("Y ZZ")) // ZZ is not a valid ExecInst enum + msgBytes := builder.build() + + return validateTest{ + TestName: "Multi-value enum invalid component", + Validator: validator, + MessageBytes: msgBytes, + ExpectedRejectReason: rejectReasonValueIsIncorrect, + ExpectedRefTagID: &tag, + } +} + func tcIncorrectDataFormatForValue() validateTest { dict, _ := datadictionary.Parse("spec/FIX40.xml") validator := NewValidator(defaultValidatorSettings, dict, nil)