forked from quickfixgo/quickfix
/
validation_test.go
335 lines (274 loc) · 13.1 KB
/
validation_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
package quickfix
import (
"github.com/quickfixgo/quickfix/datadictionary"
"github.com/quickfixgo/quickfix/fix"
"github.com/quickfixgo/quickfix/fix/tag"
. "gopkg.in/check.v1"
"time"
)
var _ = Suite(&ValidationTests{})
type ValidationTests struct{}
func (s *ValidationTests) createFIX40NewOrderSingle() MessageBuilder {
msg := NewMessageBuilder()
msg.Header().Set(fix.NewStringField(tag.MsgType, "D"))
msg.Header().Set(fix.NewStringField(tag.BeginString, "FIX.4.0"))
msg.Header().Set(fix.NewStringField(tag.BodyLength, "0"))
msg.Header().Set(fix.NewStringField(tag.SenderCompID, "0"))
msg.Header().Set(fix.NewStringField(tag.TargetCompID, "0"))
msg.Header().Set(fix.NewStringField(tag.MsgSeqNum, "0"))
msg.Header().Set(fix.NewUTCTimestampField(tag.SendingTime, time.Now()))
msg.Body().Set(fix.NewStringField(tag.ClOrdID, "A"))
msg.Body().Set(fix.NewStringField(tag.HandlInst, "1"))
msg.Body().Set(fix.NewStringField(tag.Symbol, "A"))
msg.Body().Set(fix.NewStringField(tag.Side, "1"))
msg.Body().Set(fix.NewStringField(tag.OrdType, "1"))
msg.Body().Set(fix.NewIntField(tag.OrderQty, 5))
msg.Trailer().Set(fix.NewStringField(tag.CheckSum, "000"))
return msg
}
func (s *ValidationTests) createFIX43NewOrderSingle() MessageBuilder {
msg := NewMessageBuilder()
msg.Header().Set(fix.NewStringField(tag.MsgType, "D"))
msg.Header().Set(fix.NewStringField(tag.BeginString, "FIX.4.3"))
msg.Header().Set(fix.NewStringField(tag.BodyLength, "0"))
msg.Header().Set(fix.NewStringField(tag.SenderCompID, "0"))
msg.Header().Set(fix.NewStringField(tag.TargetCompID, "0"))
msg.Header().Set(fix.NewStringField(tag.MsgSeqNum, "0"))
msg.Header().Set(fix.NewUTCTimestampField(tag.SendingTime, time.Now()))
msg.Body().Set(fix.NewStringField(tag.ClOrdID, "A"))
msg.Body().Set(fix.NewStringField(tag.HandlInst, "1"))
msg.Body().Set(fix.NewStringField(tag.Symbol, "A"))
msg.Body().Set(fix.NewStringField(tag.Side, "1"))
msg.Body().Set(fix.NewIntField(tag.OrderQty, 5))
msg.Body().Set(fix.NewStringField(tag.OrdType, "1"))
msg.Body().Set(fix.NewUTCTimestampField(tag.TransactTime, time.Now()))
msg.Trailer().Set(fix.NewStringField(tag.CheckSum, "000"))
return msg
}
func (s *ValidationTests) TestValidateInvalidTagNumber(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Header().Set(fix.NewStringField(9999, "hello"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonInvalidTagNumber)
c.Check(*reject.RefTagID(), Equals, fix.Tag(9999))
builder = s.createFIX40NewOrderSingle()
builder.Trailer().Set(fix.NewStringField(9999, "hello"))
msgBytes, _ = builder.Build()
msg, _ = parseMessage(msgBytes)
reject = validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonInvalidTagNumber)
c.Check(*reject.RefTagID(), Equals, fix.Tag(9999))
builder = s.createFIX40NewOrderSingle()
builder.Body().Set(fix.NewStringField(9999, "hello"))
msgBytes, _ = builder.Build()
msg, _ = parseMessage(msgBytes)
reject = validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonInvalidTagNumber)
c.Check(*reject.RefTagID(), Equals, fix.Tag(9999))
}
func (s *ValidationTests) TestValidateTagNotDefinedForMessage(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Body().Set(fix.NewStringField(41, "hello"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonTagNotDefinedForThisMessageType)
c.Check(*reject.RefTagID(), Equals, fix.Tag(41))
}
func (s *ValidationTests) TestValidateTagNotDefinedForMessageComponent(c *C) {
dict, err := datadictionary.Parse("spec/FIX43.xml")
c.Check(err, IsNil)
builder := s.createFIX43NewOrderSingle()
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, IsNil)
}
func (s *ValidationTests) TestValidateFieldNotFound(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := NewMessageBuilder()
builder.Header().Set(fix.NewStringField(tag.MsgType, "D"))
builder.Header().Set(fix.NewStringField(tag.BeginString, "FIX.4.0"))
builder.Header().Set(fix.NewStringField(tag.BodyLength, "0"))
builder.Header().Set(fix.NewStringField(tag.SenderCompID, "0"))
builder.Header().Set(fix.NewStringField(tag.TargetCompID, "0"))
builder.Header().Set(fix.NewStringField(tag.MsgSeqNum, "0"))
builder.Header().Set(fix.NewUTCTimestampField(tag.SendingTime, time.Now()))
builder.Trailer().Set(fix.NewStringField(tag.CheckSum, "000"))
builder.Body().Set(fix.NewStringField(tag.ClOrdID, "A"))
builder.Body().Set(fix.NewStringField(tag.HandlInst, "A"))
builder.Body().Set(fix.NewStringField(tag.Symbol, "A"))
builder.Body().Set(fix.NewStringField(tag.Side, "A"))
builder.Body().Set(fix.NewStringField(tag.OrderQty, "A"))
//ord type is required
//builder.Body().Set(fix.NewStringField(tag.OrdType, "A"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonRequiredTagMissing)
c.Check(*reject.RefTagID(), Equals, tag.OrdType)
builder = NewMessageBuilder()
builder.Trailer().Set(fix.NewStringField(tag.CheckSum, "000"))
builder.Body().Set(fix.NewStringField(tag.ClOrdID, "A"))
builder.Body().Set(fix.NewStringField(tag.HandlInst, "A"))
builder.Body().Set(fix.NewStringField(tag.Symbol, "A"))
builder.Body().Set(fix.NewStringField(tag.Side, "A"))
builder.Body().Set(fix.NewStringField(tag.OrderQty, "A"))
builder.Header().Set(fix.NewStringField(tag.MsgType, "D"))
builder.Header().Set(fix.NewStringField(tag.BeginString, "FIX.4.0"))
builder.Header().Set(fix.NewStringField(tag.BodyLength, "0"))
builder.Header().Set(fix.NewStringField(tag.SenderCompID, "0"))
builder.Header().Set(fix.NewStringField(tag.TargetCompID, "0"))
builder.Header().Set(fix.NewStringField(tag.MsgSeqNum, "0"))
//sending time is required
//msg.Header.FieldMap.Set(fix.NewStringField(tag.SendingTime, "0"))
msgBytes, _ = builder.Build()
msg, _ = parseMessage(msgBytes)
reject = validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonRequiredTagMissing)
c.Check(*reject.RefTagID(), Equals, tag.SendingTime)
}
func (s *ValidationTests) TestValidateTagSpecifiedWithoutAValue(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Body().Set(fix.NewStringField(tag.ClientID, ""))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonTagSpecifiedWithoutAValue)
c.Check(*reject.RefTagID(), Equals, tag.ClientID)
}
func (s *ValidationTests) TestValidateInvalidMsgType(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Header().Set(fix.NewStringField(tag.MsgType, "z"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonInvalidMsgType)
}
func (s *ValidationTests) TestValidateValueIsIncorrect(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Body().Set(fix.NewStringField(tag.HandlInst, "4"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonValueIsIncorrect)
c.Check(*reject.RefTagID(), Equals, tag.HandlInst)
}
func (s *ValidationTests) TestValidateIncorrectDataFormatForValue(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
builder.Body().Set(fix.NewStringField(tag.OrderQty, "+200.00"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonIncorrectDataFormatForValue)
c.Check(*reject.RefTagID(), Equals, tag.OrderQty)
}
func (s *ValidationTests) TestValidateTagSpecifiedOutOfRequiredOrder(c *C) {
dict, _ := datadictionary.Parse("spec/FIX40.xml")
builder := s.createFIX40NewOrderSingle()
//should be in header
builder.Body().Set(fix.NewStringField(tag.OnBehalfOfCompID, "CWB"))
msgBytes, _ := builder.Build()
msg, _ := parseMessage(msgBytes)
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonTagSpecifiedOutOfRequiredOrder)
c.Check(*reject.RefTagID(), Equals, tag.OnBehalfOfCompID)
}
func (s *ValidationTests) TestValidateTagAppearsMoreThanOnce(c *C) {
msg, err := parseMessage([]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"))
c.Check(err, IsNil)
dict, _ := datadictionary.Parse("spec/FIX40.xml")
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonTagAppearsMoreThanOnce)
c.Check(*reject.RefTagID(), Equals, tag.OrdType)
}
func (s *ValidationTests) TestFloatValidation(c *C) {
msg, err := parseMessage([]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"))
c.Check(err, IsNil)
dict, _ := datadictionary.Parse("spec/FIX42.xml")
reject := validate(dict, *msg)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonIncorrectDataFormatForValue)
}
func (s *ValidationTests) TestValidateVisitField(c *C) {
fieldType := &datadictionary.FieldType{Name: "myfield", Tag: tag.ClOrdID, Type: "STRING"}
fieldDef := &datadictionary.FieldDef{FieldType: fieldType}
fields := []fieldBytes{*newFieldBytes(tag.ClOrdID, []byte("value"))}
remFields, reject := validateVisitField(fieldDef, fields)
c.Check(len(remFields), Equals, 0)
c.Check(reject, IsNil)
}
func (s *ValidationTests) TestValidateVisitFieldGroup(c *C) {
fieldType1 := &datadictionary.FieldType{Name: "myfield", Tag: fix.Tag(2), Type: "STRING"}
fieldDef1 := &datadictionary.FieldDef{FieldType: fieldType1, ChildFields: []*datadictionary.FieldDef{}}
fieldType2 := &datadictionary.FieldType{Name: "myfield", Tag: fix.Tag(3), Type: "STRING"}
fieldDef2 := &datadictionary.FieldDef{FieldType: fieldType2, ChildFields: []*datadictionary.FieldDef{}}
groupFieldType := &datadictionary.FieldType{Name: "mygroupfield", Tag: fix.Tag(1), Type: "INT"}
groupFieldDef := &datadictionary.FieldDef{FieldType: groupFieldType, ChildFields: []*datadictionary.FieldDef{fieldDef1, fieldDef2}}
repField1 := newFieldBytes(fix.Tag(2), []byte("a"))
repField2 := newFieldBytes(fix.Tag(3), []byte("a"))
//non-repeating
groupID := newFieldBytes(fix.Tag(1), []byte("1"))
fields := []fieldBytes{*groupID, *repField1}
remFields, reject := validateVisitGroupField(groupFieldDef, fields)
c.Check(len(remFields), Equals, 0)
c.Check(reject, IsNil)
fields = []fieldBytes{*groupID, *repField1, *repField2}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(len(remFields), Equals, 0)
c.Check(reject, IsNil)
//test with trailing tag not in group
otherField := newFieldBytes(fix.Tag(500), []byte("blah"))
fields = []fieldBytes{*groupID, *repField1, *repField2, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(len(remFields), Equals, 1)
c.Check(reject, IsNil)
//repeats
groupID = newFieldBytes(fix.Tag(1), []byte("2"))
fields = []fieldBytes{*groupID, *repField1, *repField2, *repField1, *repField2, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(len(remFields), Equals, 1)
c.Check(reject, IsNil)
groupID = newFieldBytes(fix.Tag(1), []byte("3"))
fields = []fieldBytes{*groupID, *repField1, *repField2, *repField1, *repField2, *repField1, *repField2, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(len(remFields), Equals, 1)
c.Check(reject, IsNil)
//REJECT: group size declared > actual group size
groupID = newFieldBytes(fix.Tag(1), []byte("3"))
fields = []fieldBytes{*groupID, *repField1, *repField2, *repField1, *repField2, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonIncorrectNumInGroupCountForRepeatingGroup)
groupID = newFieldBytes(fix.Tag(1), []byte("3"))
fields = []fieldBytes{*groupID, *repField1, *repField1, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonIncorrectNumInGroupCountForRepeatingGroup)
//REJECT: group size declared < actual group size
groupID = newFieldBytes(fix.Tag(1), []byte("1"))
fields = []fieldBytes{*groupID, *repField1, *repField2, *repField1, *repField2, *otherField}
remFields, reject = validateVisitGroupField(groupFieldDef, fields)
c.Check(reject, NotNil)
c.Check(reject.RejectReason(), Equals, rejectReasonIncorrectNumInGroupCountForRepeatingGroup)
}