1 /****************************************************************************
2 ** Copyright (c) 2001-2014
3 **
4 ** This file is part of the QuickFIX FIX Engine
5 **
6 ** This file may be distributed under the terms of the quickfixengine.org
7 ** license as defined by quickfixengine.org and appearing in the file
8 ** LICENSE included in the packaging of this file.
9 **
10 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 **
13 ** See http://www.quickfixengine.org/LICENSE for licensing information.
14 **
15 ** Contact ask@quickfixengine.org if any conditions of this licensing are
16 ** not clear to you.
17 **
18 ****************************************************************************/
19 
20 #ifdef _MSC_VER
21 #pragma warning( disable : 4503 4355 4786 )
22 #include "stdafx.h"
23 #else
24 #include "config.h"
25 #endif
26 
27 #include <UnitTest++.h>
28 #include <FieldNumbers.h>
29 #include <Values.h>
30 #include <fix40/TestRequest.h>
31 #include <fix42/TestRequest.h>
32 #include <fix42/NewOrderSingle.h>
33 #include <fix40/NewOrderSingle.h>
34 #include <fix44/NewOrderList.h>
35 #include <fix44/MarketDataRequest.h>
36 #include <fix44/MarketDataSnapshotFullRefresh.h>
37 #include <fstream>
38 
39 using namespace FIX;
40 
SUITE(DataDictionaryTests)41 SUITE(DataDictionaryTests)
42 {
43 
44 USER_DEFINE_STRING( TooHigh, 501 );
45 
46 TEST(addMsgType)
47 {
48   DataDictionary object;
49   CHECK( !object.isMsgType( "A" ) );
50   object.addMsgType( "A" );
51   CHECK( object.isMsgType( "A" ) );
52 }
53 
54 TEST(addMsgField)
55 {
56   DataDictionary object;
57   CHECK( !object.isMsgField( "A", 10 ) );
58   CHECK( !object.isMsgField( "Z", 50 ) );
59   object.addMsgField( "A", 10 );
60   object.addMsgField( "Z", 50 );
61   CHECK( object.isMsgField( "A", 10 ) );
62   CHECK( object.isMsgField( "Z", 50 ) );
63   CHECK( !object.isMsgField( "A", 50 ) );
64   CHECK( !object.isMsgField( "Z", 10 ) );
65 }
66 
67 TEST(addHeaderField)
68 {
69   DataDictionary object;
70   CHECK( !object.isHeaderField( 56 ) );
71   CHECK( !object.isHeaderField( 49 ) );
72   object.addHeaderField( 56, true );
73   object.addHeaderField( 49, true );
74   CHECK( object.isHeaderField( 56 ) );
75   CHECK( object.isHeaderField( 49 ) );
76 }
77 
78 TEST(addTrailerField)
79 {
80   DataDictionary object;
81   CHECK( !object.isTrailerField( 10 ) );
82   object.addTrailerField( 10, true );
83   CHECK( object.isTrailerField( 10 ) );
84 }
85 
86 TEST(addFieldType)
87 {
88   DataDictionary object;
89   TYPE::Type type;
90   CHECK( !object.getFieldType( 14, type ) );
91   CHECK( !object.getFieldType( 23, type ) );
92 
93   object.addFieldType( 14, TYPE::String );
94   object.addFieldType( 23, TYPE::Char );
95 
96   CHECK( object.getFieldType( 14, type ) );
97   CHECK_EQUAL( TYPE::String, type );
98   CHECK( object.getFieldType( 23, type ) );
99   CHECK_EQUAL( TYPE::Char, type );
100 }
101 
102 TEST(addRequiredField)
103 {
104   DataDictionary object;
105   CHECK( !object.isRequiredField( "A", 10 ) );
106   CHECK( !object.isRequiredField( "Z", 50 ) );
107   object.addRequiredField( "A", 10 );
108   object.addRequiredField( "Z", 50 );
109   CHECK( object.isRequiredField( "A", 10 ) );
110   CHECK( object.isRequiredField( "Z", 50 ) );
111   CHECK( !object.isRequiredField( "A", 50 ) );
112   CHECK( !object.isRequiredField( "Z", 10 ) );
113 }
114 
115 TEST(addFieldValue)
116 {
117   DataDictionary object;
118   CHECK( !object.isFieldValue( 12, "f" ) );
119   CHECK( !object.isFieldValue( 12, "g" ) );
120   CHECK( !object.isFieldValue( 15, "1" ) );
121   CHECK( !object.isFieldValue( 18, "2" ) );
122   CHECK( !object.isFieldValue( 167, "FUT" ) );
123 
124   object.addFieldValue( 12, "f" );
125   object.addFieldValue( 12, "g" );
126   object.addFieldValue( 15, "1" );
127   object.addFieldValue( 18, "2" );
128   object.addFieldValue( 167, "FUT" );
129 
130   CHECK( object.isFieldValue( 12, "f" ) );
131   CHECK( object.isFieldValue( 12, "g" ) );
132   CHECK( object.isFieldValue( 15, "1" ) );
133   CHECK( object.isFieldValue( 18, "2" ) );
134   CHECK( object.isFieldValue( 167, "FUT" ) );
135 }
136 
137 TEST(addGroup)
138 {
139   DataDictionary object;
140   object.setVersion( "FIX.4.2" );
141 
142   DataDictionary group1;
143   group1.addMsgType( "1" );
144   DataDictionary group2;
145   group2.addMsgType( "2" );
146   DataDictionary group3;
147   group3.addMsgType( "3" );
148 
149   object.addGroup( "A", 100, 101, group1 );
150   object.addGroup( "A", 200, 201, group2 );
151   object.addGroup( "A", 300, 301, group3 );
152 
153   int delim;
154   const DataDictionary* pDD = 0;
155 
156   CHECK( object.getGroup( "A", 100, delim, pDD ) );
157   CHECK_EQUAL( 101, delim );
158   CHECK( pDD->isMsgType( "1" ) );
159 
160   CHECK( object.getGroup( "A", 200, delim, pDD ) );
161   CHECK_EQUAL( 201, delim );
162   CHECK( pDD->isMsgType( "2" ) );
163 
164   CHECK( object.getGroup( "A", 300, delim, pDD ) );
165   CHECK_EQUAL( 301, delim );
166   CHECK( pDD->isMsgType( "3" ) );
167 }
168 
169 TEST(addFieldName)
170 {
171   DataDictionary object;
172   object.setVersion( "FIX.4.2" );
173 
174   object.addFieldName( 1, "Account" );
175   object.addFieldName( 11, "ClOrdID" );
176   object.addFieldName( 8, "BeginString" );
177 
178   std::string name;
179   int field;
180   CHECK( object.getFieldName( 1, name ) );
181   CHECK_EQUAL( "Account", name );
182   CHECK( object.getFieldTag( name, field ) );
183   CHECK_EQUAL( 1, field );
184   CHECK( object.getFieldName( 11, name ) );
185   CHECK_EQUAL( "ClOrdID", name );
186   CHECK( object.getFieldTag( name, field ) );
187   CHECK_EQUAL( 11, field );
188   CHECK( object.getFieldName( 8, name ) );
189   CHECK_EQUAL( "BeginString", name );
190   CHECK( object.getFieldTag( name, field ) );
191   CHECK_EQUAL( 8, field );
192 }
193 
194 TEST(addValueName)
195 {
196   DataDictionary object;
197   object.setVersion( "FIX.4.2" );
198 
199   object.addValueName( 12, "0", "VALUE_12_0" );
200   object.addValueName( 12, "B", "VALUE_12_B" );
201   object.addValueName( 23, "BOO", "VALUE_23_BOO" );
202 
203   std::string name;
204   CHECK( object.getValueName( 12, "0", name ) );
205   CHECK_EQUAL( "VALUE_12_0", name );
206   CHECK( object.getValueName( 12, "B", name ) );
207   CHECK_EQUAL( "VALUE_12_B", name );
208   CHECK( object.getValueName( 23, "BOO", name ) );
209   CHECK_EQUAL( "VALUE_23_BOO", name );
210 }
211 
212 struct checkValidTagNumberFixture
213 {
214   checkValidTagNumberFixture()
215   {
216     object.setVersion( BeginString_FIX40 );
217     object.addField( FIELD::BeginString );
218     object.addField( FIELD::BodyLength );
219     object.addField( FIELD::MsgType );
220     object.addField( FIELD::CheckSum );
221     object.addField( FIELD::TestReqID );
222     object.addMsgType( MsgType_TestRequest );
223     object.addMsgField( MsgType_TestRequest, FIELD::TestReqID );
224   }
225 
226   DataDictionary object;
227 };
228 
229 TEST_FIXTURE(checkValidTagNumberFixture, checkValidTagNumber)
230 {
231   TestReqID testReqID( "1" );
232   FIX40::TestRequest message( testReqID );
233   message.setField( TooHigh( "value" ) );
234   CHECK_THROW( object.validate( message ), InvalidTagNumber );
235 
236   object.allowUnknownMsgFields( true );
237   object.validate( message );
238   object.allowUnknownMsgFields( false );
239 
240   object.addField( 501 );
241   object.addMsgField( MsgType_TestRequest, 501 );
242   object.validate( message );
243 
244   message.setField( FIELD::UserMin, "value" );
245   CHECK_THROW( object.validate( message ), InvalidTagNumber );
246 
247   object.checkUserDefinedFields( false );
248   object.validate( message );
249 }
250 
251 TEST(checkHasValue)
252 {
253   DataDictionary object;
254   Message testReqID( "8=FIX.4.2\0019=12\00135=1\001112=\00110=007\001", false );
255   FIX42::TestRequest message( testReqID );
256 
257   CHECK_THROW( object.validate( message ), NoTagValue );
258 }
259 
260 struct checkIsInMessageFixture
261 {
262   checkIsInMessageFixture()
263   {
264     object.setVersion( BeginString_FIX40 );
265     object.addField( FIELD::BeginString );
266     object.addField( FIELD::BodyLength );
267     object.addField( FIELD::MsgType );
268     object.addField( FIELD::CheckSum );
269     object.addField( FIELD::TestReqID );
270     object.addField( FIELD::Symbol );
271     object.addMsgType( MsgType_TestRequest );
272     object.addMsgField( MsgType_TestRequest, FIELD::TestReqID );
273   }
274 
275   DataDictionary object;
276 };
277 
278 TEST_FIXTURE(checkIsInMessageFixture, checkIsInMessage)
279 {
280   TestReqID testReqID( "1" );
281 
282   FIX40::TestRequest message( testReqID );
283   object.validate( message );
284 
285   message.setField( Symbol( "MSFT" ) );
286   CHECK_THROW( object.validate( message ), TagNotDefinedForMessage );
287 }
288 
289 struct checkHasRequiredFixture
290 {
291   checkHasRequiredFixture()
292   {
293     object.setVersion( BeginString_FIX40 );
294     object.addField( FIELD::BeginString );
295     object.addField( FIELD::BodyLength );
296     object.addField( FIELD::MsgType );
297     object.addField( FIELD::SenderCompID );
298     object.addField( FIELD::TargetCompID );
299     object.addHeaderField( FIELD::SenderCompID, true );
300     object.addHeaderField( FIELD::TargetCompID, false );
301     object.addField( FIELD::CheckSum );
302     object.addField( FIELD::TestReqID );
303     object.addMsgType( MsgType_TestRequest );
304     object.addMsgField( MsgType_TestRequest, FIELD::TestReqID );
305     object.addRequiredField( MsgType_TestRequest, FIELD::TestReqID );
306   }
307 
308   DataDictionary object;
309 };
310 
311 TEST_FIXTURE(checkHasRequiredFixture, checkHasRequired)
312 {
313   FIX40::TestRequest message;
314   CHECK_THROW( object.validate( message ), RequiredTagMissing );
315 
316   message.getHeader().setField( SenderCompID( "SENDER" ) );
317   CHECK_THROW( object.validate( message ), RequiredTagMissing );
318 
319   message.setField( TestReqID( "1" ) );
320   object.validate( message );
321 
322   message.getHeader().removeField( FIELD::SenderCompID );
323   message.setField( SenderCompID( "SENDER" ) );
324   CHECK_THROW( object.validate( message ), RequiredTagMissing );
325 }
326 
327 struct checkValidFormatFixture
328 {
329   checkValidFormatFixture()
330   {
331     object.setVersion( BeginString_FIX40 );
332     object.addField( FIELD::BeginString );
333     object.addField( FIELD::BodyLength );
334     object.addField( FIELD::MsgType );
335     object.addField( FIELD::CheckSum );
336     object.addField( FIELD::TestReqID );
337     object.addMsgType( MsgType_TestRequest );
338     object.addMsgField( MsgType_TestRequest, FIELD::TestReqID );
339     object.addFieldType( FIELD::TestReqID, TYPE::Int );
340   }
341 
342   DataDictionary object;
343 };
344 
345 TEST_FIXTURE( checkValidFormatFixture, checkValidFormat )
346 {
347   FIX40::TestRequest message;
348   message.setField( TestReqID( "+200" ) );
349   CHECK_THROW( object.validate( message ), IncorrectDataFormat );
350 }
351 
352 struct checkValueFixture
353 {
354   checkValueFixture()
355   {
356     object.setVersion( BeginString_FIX40 );
357     object.addField( FIELD::BeginString );
358     object.addField( FIELD::BodyLength );
359     object.addField( FIELD::MsgType );
360     object.addField( FIELD::CheckSum );
361     object.addField( FIELD::OrdType );
362     object.addField( FIELD::OrderRestrictions );
363     object.addMsgType( MsgType_NewOrderSingle );
364     object.addMsgField( MsgType_NewOrderSingle, FIELD::OrdType );
365     object.addMsgField( MsgType_NewOrderSingle, FIELD::OrderRestrictions );
366     object.addFieldType( FIELD::OrdType, TYPE::Char );
367     object.addFieldValue( FIELD::OrdType, "1" );
368     object.addFieldType( FIELD::OrderRestrictions, TYPE::MultipleValueString );
369     object.addFieldValue( FIELD::OrderRestrictions, "1" );
370     object.addFieldValue( FIELD::OrderRestrictions, "2" );
371     object.addFieldValue( FIELD::OrderRestrictions, "3" );
372   }
373 
374   DataDictionary object;
375 };
376 
377 TEST_FIXTURE( checkValueFixture, checkValue )
378 {
379   DataDictionary object;
380   FIX40::NewOrderSingle message;
381   message.setField( OrdType( '1' ) );
382   object.validate( message );
383 
384   message.setField( OrdType( '2' ) );
385   object.validate( message );
386 
387   message.setField( OrdType( '1' ) );
388   message.setField( OrderRestrictions("1 2 3") );
389   object.validate( message );
390 
391   message.setField( OrderRestrictions("1 4 3") );
392   object.validate( message );
393 }
394 
395 TEST( checkRepeatedTag )
396 {
397   DataDictionary object;
398   FIX40::NewOrderSingle message;
399   message.setField( OrdType('1') );
400   message.setField( OrdType('1'), false );
401   CHECK_THROW( object.validate(message), RepeatedTag );
402 }
403 
404 struct checkGroupCountFixture
405 {
406   checkGroupCountFixture()
407   {
408     object.setVersion( BeginString_FIX42 );
409     object.addField( FIELD::BeginString );
410     object.addField( FIELD::BodyLength );
411     object.addField( FIELD::MsgType );
412     object.addField( FIELD::CheckSum );
413     object.addField( FIELD::NoAllocs );
414     DataDictionary groupDD;
415     groupDD.addField( FIELD::AllocAccount );
416     object.addGroup( "D", FIELD::NoAllocs, FIELD::AllocAccount, groupDD );
417     object.addMsgType( MsgType_NewOrderSingle );
418     object.addMsgField( MsgType_NewOrderSingle, FIELD::NoAllocs );
419   }
420 
421   DataDictionary object;
422 };
423 
424 TEST_FIXTURE( checkGroupCountFixture, checkGroupCount )
425 {
426   FIX42::NewOrderSingle message;
427   FIX42::NewOrderSingle::NoAllocs group;
428   group.setField( AllocAccount("account") );
429   message.addGroup( group );
430   message.set( NoAllocs(2) );
431   CHECK_THROW( object.validate( message ), RepeatingGroupCountMismatch );
432 }
433 
434 TEST( checkGroupRequiredFields )
435 {
436   DataDictionary object( "../spec/FIX44.xml" );
437   FIX44::NewOrderList newOrderList;
438   newOrderList.setString("8=FIX.4.49=18635=E49=FIXTEST56=TW128=SS134=252=20050225-16:54:3266=WMListOrID000000362394=368=173=111=SE102354=155=IBM67=163=021=381=060=20050225-16:54:3238=1000040=115=USD10=119", false, &object);
439   object.validate( newOrderList );
440 
441   newOrderList.setString("8=FIX.4.49=15835=E49=FIXTEST56=TW128=SS134=252=20050225-16:54:3266=WMListOrID000000362394=368=173=163=021=381=060=20050225-16:54:3238=1000040=115=USD10=036", false, &object);
442   CHECK_THROW( object.validate( newOrderList ), RequiredTagMissing );
443 
444   newOrderList.setString("8=FIX.4.49=26935=E49=FIXTEST56=TW128=SS134=252=20050225-16:54:3266=WMListOrID000000362394=368=173=211=SE102354=155=IBM67=163=021=381=060=20050225-16:54:3238=1000040=115=USD11=SE104555=MSFT67=163=021=381=060=20050225-16:54:3238=1000040=115=USD47=A10=109", false, &object);
445   CHECK_THROW( object.validate( newOrderList ), RequiredTagMissing );
446 
447   FIX44::MarketDataRequest marketDataRequest(
448     MDReqID("1"),
449     SubscriptionRequestType( SubscriptionRequestType_SNAPSHOT_PLUS_UPDATES ),
450     MarketDepth( 9999 ) );
451 
452   marketDataRequest.set( MDUpdateType( MDUpdateType_INCREMENTAL_REFRESH ) );
453   marketDataRequest.set( AggregatedBook( true ) );
454   marketDataRequest.set( MDImplicitDelete( true ) );
455 
456   FIX44::MarketDataRequest::NoRelatedSym noRelatedSym;
457 
458   noRelatedSym.set( Symbol( "QQQQ" ) );
459   marketDataRequest.addGroup( noRelatedSym );
460 
461   FIX44::MarketDataRequest::NoMDEntryTypes noMDEntryTypes;
462 
463   noMDEntryTypes.set( MDEntryType( MDEntryType_BID ) );
464   marketDataRequest.addGroup( noMDEntryTypes );
465 
466   noMDEntryTypes.set( MDEntryType( MDEntryType_OFFER ) );
467   marketDataRequest.addGroup( noMDEntryTypes );
468 
469   noMDEntryTypes.set( MDEntryType( MDEntryType_TRADE ) );
470   marketDataRequest.addGroup( noMDEntryTypes );
471 
472   object.validate( marketDataRequest );
473 
474   noMDEntryTypes.removeField( FIELD::MDEntryType );
475   marketDataRequest.addGroup( noMDEntryTypes );
476   CHECK_THROW( object.validate( marketDataRequest ), RequiredTagMissing );
477 
478   FIX44::MarketDataSnapshotFullRefresh md;
479   md.set( MDReqID("1") );
480   md.set( Symbol("QQQQ") );
481 
482   FIX44::MarketDataSnapshotFullRefresh::NoMDEntries entry;
483 
484   entry.set( MDEntryType( MDEntryType_OFFER ) );
485   entry.set( MDEntryPx( 41.48 ) );
486   entry.set( MDEntrySize( 500 ) );
487   md.addGroup( entry );
488 
489   entry.set( MDEntryType( MDEntryType_BID ) );
490   entry.set( MDEntryPx( 41.2 ) );
491   entry.set( MDEntrySize( 300 ) );
492   md.addGroup( entry );
493 
494   Message message( md.toString(), object );
495   object.validate( message );
496   //object.validate( md );
497 }
498 
499 TEST( readFromFile )
500 {
501   DataDictionary object( "../spec/FIX43.xml" );
502   CHECK( object.isHeaderField( 56 ) );
503   CHECK( !object.isHeaderField( 38 ) );
504   CHECK( !object.isHeaderField( 10 ) );
505 
506   CHECK( object.isTrailerField( 10 ) );
507   CHECK( !object.isTrailerField( 38 ) );
508   CHECK( !object.isTrailerField( 56 ) );
509 
510   CHECK( object.isMsgType( "A" ) );
511   CHECK( object.isMsgField( "A", 383 ) );
512 
513   TYPE::Type type = TYPE::Unknown;
514   CHECK( object.getFieldType( 383, type ) );
515   CHECK_EQUAL( TYPE::Length, type );
516 
517   CHECK( object.isRequiredField( "A", 108 ) );
518   CHECK( !object.isRequiredField( "A", 383 ) );
519   CHECK( object.isRequiredField( "6", 28 ) );
520   CHECK( !object.isRequiredField( "B", 55 ) );
521 
522   CHECK( object.isFieldValue( 40, "A" ) );
523   CHECK( !object.isFieldValue( 40, "Z" ) );
524 
525   std::string name;
526   CHECK( object.getFieldName( 1, name ) );
527   CHECK_EQUAL( "Account", name );
528   CHECK( object.getFieldName( 11, name ) );
529   CHECK_EQUAL( "ClOrdID", name );
530   CHECK( object.getFieldName( 8, name ) );
531   CHECK_EQUAL( "BeginString", name );
532 
533   CHECK( object.getValueName( 18, "1", name ) );
534   CHECK_EQUAL( "NOTHELD", name );
535   CHECK( object.getValueName( 18, "2", name ) );
536   CHECK_EQUAL( "WORK", name );
537   CHECK( object.getValueName( 18, "W", name ) );
538   CHECK_EQUAL( "PEGVWAP", name );
539 
540   const DataDictionary* pDD = 0;
541   int delim = 0;
542   CHECK( object.getGroup( "b", 296, delim, pDD ) );
543   CHECK_EQUAL( 302, delim );
544   CHECK( pDD->isField( 295 ) );
545   CHECK( pDD->isField( 310 ) );
546   CHECK( !pDD->isField( 55 ) );
547   CHECK( pDD->getGroup( "b", 295, delim, pDD ) );
548   CHECK_EQUAL( 299, delim );
549   CHECK( pDD->isField( 55 ) );
550   CHECK( !pDD->isField( 310 ) );
551   CHECK( object.getGroup( "8", 453, delim, pDD ) );
552   CHECK_EQUAL( 448, delim );
553   CHECK( object.getGroup( "y", 146, delim, pDD ) );
554   CHECK_EQUAL( 55, delim );
555 }
556 
557 TEST( readFromStream )
558 {
559   std::fstream stream( "../spec/FIX43.xml" );
560   DataDictionary object( stream );
561 }
562 
563 struct copyFixture
564 {
565   copyFixture()
566   {
567     object.setVersion( BeginString_FIX40 );
568     object.addMsgType( MsgType_NewOrderSingle );
569     object.addMsgField( MsgType_NewOrderSingle, FIELD::OrdType );
570     object.addFieldType( FIELD::OrdType, TYPE::Char );
571     object.addFieldValue( FIELD::OrdType, "1" );
572 
573     DataDictionary dataDictionary1;
574     dataDictionary1.addFieldType( FIELD::HeartBtInt, TYPE::String );
575     DataDictionary dataDictionary2;
576     dataDictionary2.addFieldType( FIELD::MsgType, TYPE::Char );
577     dataDictionary1.addGroup( "A", 1, 2, dataDictionary2 );
578     object.addGroup( "A", 10, 20, dataDictionary1 );
579   }
580 
581   DataDictionary object;
582 };
583 
584 TEST_FIXTURE( copyFixture, copy )
585 {
586   DataDictionary dataDictionary = object;
587   TYPE::Type type;
588   int delim;
589 
590   CHECK_EQUAL( BeginString_FIX40, dataDictionary.getVersion() );
591   CHECK( dataDictionary.isMsgType( MsgType_NewOrderSingle ) );
592   CHECK( dataDictionary.isMsgField( MsgType_NewOrderSingle, FIELD::OrdType ) );
593   CHECK( dataDictionary.getFieldType( FIELD::OrdType, type ) );
594   CHECK_EQUAL( TYPE::Char, type );
595   CHECK( dataDictionary.isFieldValue( FIELD::OrdType, "1" ) );
596 
597   const DataDictionary* pDD = 0;
598   CHECK( dataDictionary.getGroup( "A", 10, delim, pDD ) );
599   CHECK( pDD->getFieldType( FIELD::HeartBtInt, type ) );
600   CHECK_EQUAL( TYPE::String, type );
601   CHECK_EQUAL( 20, delim );
602 
603   CHECK( pDD->getGroup( "A", 1, delim, pDD ) );
604   CHECK( pDD->getFieldType( FIELD::MsgType, type ) );
605   CHECK_EQUAL( TYPE::Char, type );
606   CHECK_EQUAL( 2, delim );
607 }
608 
609 }
610 
611