1919
2020package quickfix ;
2121
22+ import org .junit .Test ;
23+
2224import java .io .ByteArrayInputStream ;
2325import java .io .ByteArrayOutputStream ;
2426import java .io .IOException ;
2830import java .util .Iterator ;
2931import java .util .Properties ;
3032import java .util .Set ;
31-
32- import junit .framework .TestCase ;
33-
34- public class SessionSettingsTest extends TestCase {
35-
36- public SessionSettingsTest (String name ) {
37- super (name );
38- }
39-
33+ import java .util .Map ;
34+ import java .util .HashMap ;
35+ import java .util .Random ;
36+ import java .util .concurrent .CountDownLatch ;
37+ import java .util .concurrent .atomic .AtomicBoolean ;
38+
39+ import static org .junit .Assert .assertEquals ;
40+ import static org .junit .Assert .assertTrue ;
41+ import static org .junit .Assert .assertFalse ;
42+ import static org .junit .Assert .assertNotNull ;
43+ import static org .junit .Assert .assertNull ;
44+ import static org .junit .Assert .fail ;
45+
46+ public class SessionSettingsTest {
47+
48+ @ Test
4049 public void testExtendedSettings () throws ConfigError {
4150 String settingsString = "" ;
4251 settingsString += "[SESSION]\n " ;
@@ -59,6 +68,7 @@ public void testExtendedSettings() throws ConfigError {
5968 assertEquals ("NYC" , id .getTargetLocationID ());
6069 }
6170
71+ @ Test
6272 public void testSettings () throws Exception {
6373 final SessionSettings settings = setUpSession ();
6474
@@ -119,6 +129,7 @@ public void testSettings() throws Exception {
119129 assertFalse (sectionIterator .hasNext ());
120130 }
121131
132+ @ Test
122133 public void testMergedProperties () throws Exception {
123134 final SessionSettings settings = setUpSession ();
124135 final SessionID sessionID = new SessionID ("FIX.4.2" , "TW" , "CLIENT1" );
@@ -172,6 +183,7 @@ private static SessionSettings createSettingsFromString(String settingsString)
172183 return new SessionSettings (cfg );
173184 }
174185
186+ @ Test
175187 public void testSessionKeyIterator () throws Exception {
176188 final SessionSettings settings = setUpSession ();
177189 final Iterator <SessionID > itr = settings .sectionIterator ();
@@ -182,6 +194,7 @@ public void testSessionKeyIterator() throws Exception {
182194 }
183195 }
184196
197+ @ Test
185198 public void testMethodsForDefaults () throws Exception {
186199 final SessionSettings settings = setUpSession ();
187200 assertEquals ("acceptor" , settings .getString ("ConnectionType" ));
@@ -192,6 +205,7 @@ public void testMethodsForDefaults() throws Exception {
192205 assertFalse (settings .isSetting ("bogus" ));
193206 }
194207
208+ @ Test
195209 public void testDefaultsSet () throws Exception {
196210 final SessionSettings settings = setUpSession ();
197211 final Properties defaults = new Properties ();
@@ -205,27 +219,31 @@ public void testDefaultsSet() throws Exception {
205219 assertEquals ("bargle" , settings .getString ("FileStorePath" ));
206220 }
207221
222+ @ Test
208223 public void testSpecialCharactersInKeys () throws Exception {
209224 final SessionSettings settings = setUpSession ("$$$foo bar.baz@@@=value\n " );
210225 final SessionID sessionID2 = new SessionID ("FIX.4.2" , "TW" , "CLIENT2" );
211226
212227 assertEquals ("value" , settings .getString (sessionID2 , "$$$foo bar.baz@@@" ));
213228 }
214229
230+ @ Test
215231 public void testStrangeCharactersInValues () throws Exception {
216232 final SessionSettings settings = setUpSession ("label= This is a test? Yes, it is.\n " );
217233 final SessionID sessionID2 = new SessionID ("FIX.4.2" , "TW" , "CLIENT2" );
218234
219235 assertEquals ("This is a test? Yes, it is." , settings .getString (sessionID2 , "label" ));
220236 }
221237
238+ @ Test
222239 public void testFinalCommentWithoutTrailingNewline () throws Exception {
223240 final SessionSettings settings = setUpSession ("label=no trailing newline\n # a comment without trailing newline" );
224241 final SessionID sessionID2 = new SessionID ("FIX.4.2" , "TW" , "CLIENT2" );
225242
226243 assertEquals ("no trailing newline" , settings .getString (sessionID2 , "label" ));
227244 }
228245
246+ @ Test
229247 public void testDefaultSetters () throws Exception {
230248 final SessionSettings settings = setUpSession ();
231249 settings .setBool ("bool" , true );
@@ -238,6 +256,7 @@ public void testDefaultSetters() throws Exception {
238256 assertEquals ("wrong default value" , "xyz" , settings .getString ("string" ));
239257 }
240258
259+ @ Test
241260 public void testVariableInterpolationWithDefaultValueSource () throws Exception {
242261 System .setProperty ("test.1" , "FOO" );
243262 System .setProperty ("test.2" , "BAR" );
@@ -251,6 +270,7 @@ public void testVariableInterpolationWithDefaultValueSource() throws Exception {
251270 }
252271
253272 // QFJ-204
273+ @ Test
254274 public void testVariableInterpolationInDefaultSection () throws Exception {
255275 System .setProperty ("sender" , "SENDER" );
256276 System .setProperty ("target" , "TARGET" );
@@ -267,6 +287,7 @@ public void testVariableInterpolationInDefaultSection() throws Exception {
267287 assertEquals ("wrong value" , "TARGET" , settings .getString (sessionID , "TargetCompID" ));
268288 }
269289
290+ @ Test
270291 public void testVariableInterpolationWithNoSysProps () throws Exception {
271292 System .setProperty ("test.1" , "FOO" );
272293 System .setProperty ("test.2" , "BAR" );
@@ -277,6 +298,7 @@ public void testVariableInterpolationWithNoSysProps() throws Exception {
277298 settings .getString ("VariableTest" ));
278299 }
279300
301+ @ Test
280302 public void testVariableInterpolationWithProps () throws Exception {
281303 System .setProperty ("test.2" , "BAR" );
282304 final Properties properties = new Properties (System .getProperties ());
@@ -291,11 +313,13 @@ public void testVariableInterpolationWithProps() throws Exception {
291313 settings .getString ("VariableTest" ));
292314 }
293315
316+ @ Test
294317 public void testDefaultConstructor () {
295318 new SessionSettings ();
296319 // Passes if no exception is thrown
297320 }
298321
322+ @ Test
299323 public void testConfigError () throws Exception {
300324 final InputStream cfg = new InputStream () {
301325
@@ -313,6 +337,7 @@ public synchronized int read() throws IOException {
313337 }
314338 }
315339
340+ @ Test
316341 public void testSettingsToStream () throws Exception {
317342 final SessionSettings expectedSettings = setUpSession ();
318343 final ByteArrayOutputStream out = new ByteArrayOutputStream ();
@@ -345,12 +370,14 @@ private void assertSectionEquals(Properties expectedProperties, Properties actua
345370 }
346371 }
347372
373+ @ Test
348374 public void testToString () throws Exception {
349375 final SessionSettings expectedSettings = setUpSession ();
350376 final String actualString = expectedSettings .toString ();
351377 assertSettingsEqual (expectedSettings , actualString );
352378 }
353379
380+ @ Test
354381 public void testParseSettingReconnectInterval () {
355382 assertTrue (Arrays .equals (null , SessionSettings .parseSettingReconnectInterval ("" )));
356383 assertTrue (Arrays .equals (null , SessionSettings .parseSettingReconnectInterval (null )));
@@ -390,4 +417,124 @@ public void testParseSettingReconnectInterval() {
390417 }
391418 }
392419
420+ @ Test
421+ public void testConcurrentAccess () throws ConfigError , InterruptedException {
422+ final Map <Object , Object > defaultSettings = createDefaultSettings ();
423+
424+ final Map <Object , Object > pricingSection = createPricingSection ();
425+ final SessionID pricingSessionID = new SessionID ("FIX.4.2:FOOBAR_PRICING->*" );
426+
427+ final Map <Object , Object > tradingSection = createTradingSection ();
428+ final SessionID tradingSessionID = new SessionID ("FIX.4.2:FOOBAR_TRADING->*" );
429+
430+ final SessionSettings sessionSettings = new SessionSettings ();
431+ sessionSettings .set (new Dictionary (null , defaultSettings ));
432+ sessionSettings .set (pricingSessionID , new Dictionary ("sessions" , pricingSection ));
433+ sessionSettings .set (tradingSessionID , new Dictionary ("sessions" , tradingSection ));
434+
435+
436+ final int numClients = 500 ;
437+ final CountDownLatch startLatch = new CountDownLatch (1 );
438+ final CountDownLatch countDownLatch = new CountDownLatch (numClients );
439+
440+ final AtomicBoolean testHasPassed = new AtomicBoolean (true );
441+ final Random random = new Random ();
442+
443+ for (int i = 0 ; i < numClients ; i ++) {
444+ final String clientPricingSessionIDString = "FIX.4.2:FOOBAR_PRICING->CLIENT" + i ;
445+ final String clientTradingSessionIDString = "FIX.4.2:FOOBAR_TRADING->CLIENT" + i ;
446+ final Thread clientThread = new Thread (() -> {
447+ final Map <Object , Object > expectedClientPricingSettings = new HashMap <>();
448+ expectedClientPricingSettings .putAll (defaultSettings );
449+ expectedClientPricingSettings .putAll (pricingSection );
450+
451+ final Map <Object , Object > expectedClientTradingSettings = new HashMap <>();
452+ expectedClientTradingSettings .putAll (defaultSettings );
453+ expectedClientTradingSettings .putAll (tradingSection );
454+
455+ int randomSleep = random .nextInt (20 );
456+ try {
457+ // wait for everyone to be ready
458+ startLatch .await ();
459+
460+ // individual thread to sleep at random interval, to simulate spread connection attempt
461+ Thread .sleep (randomSleep );
462+
463+ final SessionID clientPricingSessionID = new SessionID (clientPricingSessionIDString );
464+ sessionSettings .set (clientPricingSessionID , new Dictionary (clientPricingSessionIDString , expectedClientPricingSettings ));
465+
466+ final SessionID clientTradingSessionID = new SessionID (clientTradingSessionIDString );
467+ sessionSettings .set (clientTradingSessionID , new Dictionary (clientTradingSessionIDString , expectedClientTradingSettings ));
468+
469+ // sleep at the end, before we verify the outcome
470+ Thread .sleep (randomSleep );
471+
472+ assertEquals ("Default settings must be correct" , defaultSettings , sessionSettings .get ().toMap ());
473+ assertEquals ("Client pricing settings must be correct" , expectedClientPricingSettings , sessionSettings .get (clientPricingSessionID ).toMap ());
474+ assertEquals ("Client trading settings must be correct" , expectedClientTradingSettings , sessionSettings .get (clientTradingSessionID ).toMap ());
475+ } catch (final Throwable throwable ) {
476+ testHasPassed .set (false );
477+ throwable .printStackTrace ();
478+ } finally {
479+ countDownLatch .countDown ();
480+ }
481+ }, "CLIENT_THREAD_" + i );
482+ clientThread .setDaemon (true );
483+ clientThread .start ();
484+ }
485+
486+ // go go go , everyone!
487+ startLatch .countDown ();
488+
489+ // ok.. wait for everyone to finish
490+ countDownLatch .await ();
491+
492+ // verify test has passed
493+ assertTrue (testHasPassed .get ());
494+ }
495+
496+ private Map <Object , Object > createTradingSection () {
497+ final Map <Object , Object > tradingSection = new HashMap <>();
498+ tradingSection .put ("PersistMessages" ,"Y" );
499+ tradingSection .put ("SocketAcceptPort" ,"7566" );
500+ tradingSection .put ("DataDictionary" ,"fix/FIX42-TRADING-2.4.xml" );
501+ tradingSection .put ("ResetOnLogon" ,"N" );
502+ tradingSection .put ("MaxLatency" ,"1" );
503+ return tradingSection ;
504+ }
505+
506+ private Map <Object , Object > createPricingSection () {
507+ final Map <Object , Object > pricingSection = new HashMap <>();
508+ pricingSection .put ("PersistMessages" ,"N" );
509+ pricingSection .put ("SocketAcceptPort" ,"7565" );
510+ pricingSection .put ("DataDictionary" ,"fix/FIX42-PRICING-2.4.xml" );
511+ pricingSection .put ("ResetOnLogon" ,"Y" );
512+ pricingSection .put ("MaxLatency" ,"120" );
513+ return pricingSection ;
514+ }
515+
516+ private Map <Object , Object > createDefaultSettings () {
517+ final Map <Object , Object > defaultSettings = new HashMap <>();
518+ defaultSettings .put ("TimeZone" , "UTC" );
519+ defaultSettings .put ("StartDay" , "Sunday" );
520+ defaultSettings .put ("StartTime" , "7:00:00" );
521+ defaultSettings .put ("EndDay" , "Friday" );
522+ defaultSettings .put ("EndTime" , "17:00:00" );
523+ defaultSettings .put ("NonStopSession" , "N" );
524+ defaultSettings .put ("ConnectionType" , "acceptor" );
525+ defaultSettings .put ("HeartBtInt" , "30" );
526+ defaultSettings .put ("UseDataDictionary" , "Y" );
527+ defaultSettings .put ("ThreadModel" , "ThreadPerSession" );
528+ defaultSettings .put ("UseJmx" , "Y" );
529+ defaultSettings .put ("FileStorePath" , "/home/wibowoa/var/lib/myApp" );
530+ defaultSettings .put ("FileLogPath" , "logs/fixlog" );
531+ defaultSettings .put ("FileIncludeTimeStampForMessages" , "Y" );
532+ defaultSettings .put ("FileIncludeMilliseconds" , "Y" );
533+ defaultSettings .put ("CheckLatency" , "Y" );
534+ defaultSettings .put ("BeginString" , "FIX.4.2" );
535+ defaultSettings .put ("AcceptorTemplate" , "Y" );
536+ defaultSettings .put ("TargetCompID" , "*" );
537+ return defaultSettings ;
538+ }
539+
393540}
0 commit comments