34
34
import quickfix .field .MsgType ;
35
35
import quickfix .field .NoHops ;
36
36
import quickfix .field .NoPartyIDs ;
37
+ import quickfix .field .NoPartySubIDs ;
37
38
import quickfix .field .NoRelatedSym ;
38
39
import quickfix .field .OrdType ;
39
40
import quickfix .field .OrderQty ;
41
+ import quickfix .field .PartyID ;
42
+ import quickfix .field .PartyIDSource ;
43
+ import quickfix .field .PartyRole ;
44
+ import quickfix .field .PartySubID ;
45
+ import quickfix .field .PartySubIDType ;
40
46
import quickfix .field .Price ;
41
47
import quickfix .field .QuoteReqID ;
42
48
import quickfix .field .SenderCompID ;
55
61
import java .math .BigDecimal ;
56
62
import java .net .URL ;
57
63
import java .net .URLClassLoader ;
64
+ import java .util .ArrayList ;
65
+ import java .util .List ;
66
+ import java .util .concurrent .Callable ;
67
+ import java .util .concurrent .Future ;
68
+ import java .util .concurrent .TimeUnit ;
58
69
59
70
import static org .hamcrest .CoreMatchers .is ;
60
71
import static org .hamcrest .Matchers .hasProperty ;
72
+ import static org .junit .Assert .assertArrayEquals ;
61
73
import static org .junit .Assert .assertEquals ;
62
74
import static org .junit .Assert .assertFalse ;
63
75
import static org .junit .Assert .assertNotNull ;
@@ -973,6 +985,8 @@ public void testCopy() throws Exception {
973
985
assertEquals (ddCopy .isCheckFieldsOutOfOrder (),dataDictionary .isCheckFieldsOutOfOrder ());
974
986
assertEquals (ddCopy .isCheckUnorderedGroupFields (),dataDictionary .isCheckUnorderedGroupFields ());
975
987
assertEquals (ddCopy .isCheckUserDefinedFields (),dataDictionary .isCheckUserDefinedFields ());
988
+ assertArrayEquals (getDictionary ().getOrderedFields (),ddCopy .getOrderedFields ());
989
+ assertArrayEquals (getDictionary ().getOrderedFields (),dataDictionary .getOrderedFields ());
976
990
977
991
DataDictionary .GroupInfo groupFromDDCopy = ddCopy .getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD );
978
992
assertTrue (groupFromDDCopy .getDataDictionary ().isAllowUnknownMessageFields ());
@@ -984,6 +998,31 @@ public void testCopy() throws Exception {
984
998
assertTrue (ddCopy .isAllowUnknownMessageFields ());
985
999
groupFromDDCopy = ddCopy .getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD );
986
1000
assertTrue (groupFromDDCopy .getDataDictionary ().isAllowUnknownMessageFields ());
1001
+
1002
+ DataDictionary originalGroupDictionary = getDictionary ().getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD ).getDataDictionary ();
1003
+ DataDictionary groupDictionary = dataDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD ).getDataDictionary ();
1004
+ DataDictionary copyGroupDictionary = ddCopy .getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD ).getDataDictionary ();
1005
+ assertArrayEquals (originalGroupDictionary .getOrderedFields (), groupDictionary .getOrderedFields ());
1006
+ assertArrayEquals (originalGroupDictionary .getOrderedFields (), copyGroupDictionary .getOrderedFields ());
1007
+
1008
+ DataDictionary originalNestedGroupDictionary = originalGroupDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartySubIDs .FIELD ).getDataDictionary ();
1009
+ DataDictionary nestedGroupDictionary = groupDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartySubIDs .FIELD ).getDataDictionary ();
1010
+ DataDictionary copyNestedGroupDictionary = copyGroupDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartySubIDs .FIELD ).getDataDictionary ();
1011
+ assertArrayEquals (originalNestedGroupDictionary .getOrderedFields (), nestedGroupDictionary .getOrderedFields ());
1012
+ assertArrayEquals (originalNestedGroupDictionary .getOrderedFields (), copyNestedGroupDictionary .getOrderedFields ());
1013
+ }
1014
+
1015
+ @ Test
1016
+ public void testOrderedFields () throws Exception {
1017
+ final DataDictionary dataDictionary = getDictionary ();
1018
+
1019
+ final DataDictionary partyIDsDictionary = dataDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartyIDs .FIELD ).getDataDictionary ();
1020
+ int [] expectedPartyIDsFieldOrder = new int [] {PartyID .FIELD , PartyIDSource .FIELD , PartyRole .FIELD , NoPartySubIDs .FIELD };
1021
+ assertArrayEquals (expectedPartyIDsFieldOrder , partyIDsDictionary .getOrderedFields ());
1022
+
1023
+ final DataDictionary partySubIDsDictionary = partyIDsDictionary .getGroup (NewOrderSingle .MSGTYPE , NoPartySubIDs .FIELD ).getDataDictionary ();
1024
+ int [] expectedPartySubIDsFieldOrder = new int [] {PartySubID .FIELD , PartySubIDType .FIELD };
1025
+ assertArrayEquals (expectedPartySubIDsFieldOrder , partySubIDsDictionary .getOrderedFields ());
987
1026
}
988
1027
989
1028
/**
@@ -1299,6 +1338,52 @@ public void testAllowingBlankValuesDisablesFieldValidation() throws Exception {
1299
1338
dictionary .validate (newSingle , true );
1300
1339
}
1301
1340
1341
+
1342
+ // QFJ-971
1343
+ @ Test
1344
+ public void testConcurrentValidationFailure () throws Exception {
1345
+ final String data = "8=FIX.4.4|9=284|35=F|49=TEST_49|56=TEST_56|34=420|52=20190302-07:31:57.079|"
1346
+ + "115=TEST3|116=TEST_116|11=TEST_11|41=TEST_41|55=TEST_55|48=TEST_48|22=4|54=2|"
1347
+ + "60=20190302-07:31:56.933|38=100|207=TEST_207|453=1|448=TEST_448|447=D|452=3|10=204|" ;
1348
+ final String msgString = data .replace ('|' , (char ) 1 );
1349
+
1350
+ // use some more threads to make it more likely that the problem will occur
1351
+ final int noOfThreads = 8 ;
1352
+ final int noOfIterations = 500 ;
1353
+
1354
+ for (int i = 0 ; i < noOfIterations ; i ++) {
1355
+ final DataDictionary dd = new DataDictionary ("FIX44.xml" );
1356
+ final MessageFactory messageFactory = new quickfix .fix44 .MessageFactory ();
1357
+ PausableThreadPoolExecutor ptpe = new PausableThreadPoolExecutor (noOfThreads );
1358
+ // submit threads to pausable executor and try to let them start at the same time
1359
+ ptpe .pause ();
1360
+ List <Future > resultList = new ArrayList <>();
1361
+ for (int j = 0 ; j < noOfThreads ; j ++) {
1362
+ final Callable messageParser = (Callable ) () -> {
1363
+ Message msg = MessageUtils .parse (messageFactory , dd , msgString );
1364
+ Group partyGroup = msg .getGroups (quickfix .field .NoPartyIDs .FIELD ).get (0 );
1365
+ char partyIdSource = partyGroup .getChar (PartyIDSource .FIELD );
1366
+ assertEquals (PartyIDSource .PROPRIETARY_CUSTOM_CODE , partyIdSource );
1367
+ return msg ;
1368
+ };
1369
+ resultList .add (ptpe .submit (messageParser ));
1370
+ }
1371
+
1372
+ // start all threads
1373
+ ptpe .resume ();
1374
+ ptpe .shutdown ();
1375
+ ptpe .awaitTermination (10 , TimeUnit .MILLISECONDS );
1376
+
1377
+ // validate results
1378
+ for (Future future : resultList ) {
1379
+ // if unsuccessful, this will throw an ExecutionException
1380
+ future .get ();
1381
+ }
1382
+ }
1383
+ }
1384
+
1385
+
1386
+
1302
1387
//
1303
1388
// Group Validation Tests in RepeatingGroupTest
1304
1389
//
0 commit comments