From 1ca1fb045c72211f5216c06bb420edbfaaa23a07 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Thu, 15 Feb 2024 16:20:22 -0600 Subject: [PATCH] address #639 bug; rename Dictionary->SessionDict; cleanup/nullableize resolves #639 issue (QuickFix Dictionary .ctor overload doesn't capitalize keys) Breaking changes: * rename Dictionary to SettingsDictionary to reduce name confusion with System.Collections.Generic.Dictionary * privatize a ctor that takes a generic Dictionary; apps shouldn't use it * remove the copy ctor that takes only a SessionDictionary; replace it with one that explicitly requires a name also --- QuickFIXn/AbstractInitiator.cs | 8 +- QuickFIXn/AcceptorSocketDescriptor.cs | 2 +- QuickFIXn/ClientHandlerThread.cs | 2 +- QuickFIXn/Dictionary.cs | 292 ------------------------- QuickFIXn/IAcceptor.cs | 2 +- QuickFIXn/IInitiator.cs | 2 +- QuickFIXn/Logger/ScreenLogFactory.cs | 2 +- QuickFIXn/SessionFactory.cs | 10 +- QuickFIXn/SessionSchedule.cs | 2 +- QuickFIXn/SessionSettings.cs | 34 +-- QuickFIXn/Settings.cs | 14 +- QuickFIXn/SettingsDictionary.cs | 277 +++++++++++++++++++++++ QuickFIXn/SocketSettings.cs | 64 +++--- QuickFIXn/ThreadedSocketAcceptor.cs | 8 +- QuickFIXn/ThreadedSocketReactor.cs | 6 +- QuickFIXn/Transport/SocketInitiator.cs | 4 +- RELEASE_NOTES.md | 5 + UnitTests/DictionaryTest.cs | 166 -------------- UnitTests/FileStoreTests.cs | 2 +- UnitTests/Logger/FileLogTests.cs | 4 +- UnitTests/SessionDynamicTest.cs | 6 +- UnitTests/SessionFactoryTest.cs | 10 +- UnitTests/SessionScheduleTests.cs | 62 +++--- UnitTests/SessionSettingsTest.cs | 14 +- UnitTests/SessionStateTest.cs | 2 +- UnitTests/SessionTest.cs | 4 +- UnitTests/SettingsDictionaryTests.cs | 179 +++++++++++++++ UnitTests/SettingsTest.cs | 10 +- UnitTests/SocketSettingsTest.cs | 6 +- 29 files changed, 601 insertions(+), 598 deletions(-) delete mode 100755 QuickFIXn/Dictionary.cs create mode 100755 QuickFIXn/SettingsDictionary.cs delete mode 100755 UnitTests/DictionaryTest.cs create mode 100755 UnitTests/SettingsDictionaryTests.cs diff --git a/QuickFIXn/AbstractInitiator.cs b/QuickFIXn/AbstractInitiator.cs index 915fef9fb..fda3f2b35 100644 --- a/QuickFIXn/AbstractInitiator.cs +++ b/QuickFIXn/AbstractInitiator.cs @@ -52,7 +52,7 @@ public void Start() // create all sessions foreach (SessionID sessionId in _settings.GetSessions()) { - Dictionary dict = _settings.Get(sessionId); + SettingsDictionary dict = _settings.Get(sessionId); CreateSession(sessionId, dict); } @@ -72,7 +72,7 @@ public void Start() /// ID of new session /// config settings for new session /// true if session added successfully, false if session already exists or is not an initiator - public bool AddSession(SessionID sessionId, Dictionary dict) + public bool AddSession(SessionID sessionId, SettingsDictionary dict) { lock (_settings) if (!_settings.Has(sessionId)) // session won't be in settings if ad-hoc creation after startup @@ -94,7 +94,7 @@ public bool AddSession(SessionID sessionId, Dictionary dict) /// ID of new session /// config settings for new session /// true if session added successfully, false if session already exists or is not an initiator - private bool CreateSession(SessionID sessionId, Dictionary dict) + private bool CreateSession(SessionID sessionId, SettingsDictionary dict) { if (dict.GetString(SessionSettings.CONNECTION_TYPE) == "initiator" && !_sessionIDs.Contains(sessionId)) { @@ -273,7 +273,7 @@ protected virtual void OnRemove(SessionID sessionId) /// /// /// - protected abstract void DoConnect(Session session, QuickFix.Dictionary settings); + protected abstract void DoConnect(Session session, QuickFix.SettingsDictionary settings); #endregion diff --git a/QuickFIXn/AcceptorSocketDescriptor.cs b/QuickFIXn/AcceptorSocketDescriptor.cs index 0fe5f0b56..e20eec943 100644 --- a/QuickFIXn/AcceptorSocketDescriptor.cs +++ b/QuickFIXn/AcceptorSocketDescriptor.cs @@ -20,7 +20,7 @@ internal class AcceptorSocketDescriptor #endregion - public AcceptorSocketDescriptor(IPEndPoint socketEndPoint, SocketSettings socketSettings, QuickFix.Dictionary sessionDict) + public AcceptorSocketDescriptor(IPEndPoint socketEndPoint, SocketSettings socketSettings, QuickFix.SettingsDictionary sessionDict) { Address = socketEndPoint; SocketReactor = new ThreadedSocketReactor(Address, socketSettings, sessionDict, this); diff --git a/QuickFIXn/ClientHandlerThread.cs b/QuickFIXn/ClientHandlerThread.cs index 365d0372a..f0a64284b 100755 --- a/QuickFIXn/ClientHandlerThread.cs +++ b/QuickFIXn/ClientHandlerThread.cs @@ -33,7 +33,7 @@ public ExitedEventArgs(ClientHandlerThread clientHandlerThread) private readonly SocketReader _socketReader; private readonly FileLog _log; - internal ClientHandlerThread(TcpClient tcpClient, long clientId, QuickFix.Dictionary settingsDict, + internal ClientHandlerThread(TcpClient tcpClient, long clientId, QuickFix.SettingsDictionary settingsDict, SocketSettings socketSettings, AcceptorSocketDescriptor? acceptorDescriptor) { string debugLogFilePath = "log"; diff --git a/QuickFIXn/Dictionary.cs b/QuickFIXn/Dictionary.cs deleted file mode 100755 index c8c45bf55..000000000 --- a/QuickFIXn/Dictionary.cs +++ /dev/null @@ -1,292 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Globalization; -using QuickFix.Fields.Converters; - -namespace QuickFix -{ - /// - /// Name/value pairs used for specifying groups of settings - /// - public class Dictionary : System.Collections.IEnumerable - { - #region Private Members - - private string name_; - private System.Collections.Generic.Dictionary data_ = new System.Collections.Generic.Dictionary(); - - #endregion - - #region Properties - - public string Name - { - get { return name_; } - private set { name_ = value; } - } - - public int Count - { - get { return data_.Count; } - } - - /// - /// Alias for Count - /// - public int Size - { - get { return Count; } - } - - #endregion - - #region Public Methods - public Dictionary() - { } - - public Dictionary(string name) - : this(name, new System.Collections.Generic.Dictionary()) - { } - - public Dictionary(Dictionary d) - : this(d.name_, d.data_) - { } - - public Dictionary(string name, System.Collections.Generic.Dictionary data) - { - name_ = name; - data_ = new System.Collections.Generic.Dictionary(data); - } - - public string GetString(string key) - { - string val = ""; - if (!data_.TryGetValue(key.ToUpper(), out val)) - throw new ConfigError("No value for key: " + key); - return val; - } - - public String GetString(string key, bool capitalize) - { - string s = GetString(key); - return capitalize ? s.ToUpper() : s; - } - - public int GetInt(string key) - { - try - { - return Convert.ToInt32(GetString(key)); - } - catch (FormatException) - { - throw new ConfigError("Incorrect data type"); - } - catch (QuickFIXException) - { - throw new ConfigError("No value for key: " + key); - } - } - - public long GetLong(string key) - { - try - { - return Convert.ToInt64(GetString(key)); - } - catch(FormatException) - { - throw new ConfigError("Incorrect data type"); - } - catch(QuickFIXException) - { - throw new ConfigError("No value for key: " + key); - } - } - - public ulong GetULong(string key) - { - try - { - return Convert.ToUInt64(GetString(key)); - } - catch(FormatException) - { - throw new ConfigError("Incorrect data type"); - } - catch(QuickFIXException) - { - throw new ConfigError("No value for key: " + key); - } - } - - public double GetDouble(string key) - { - try - { - return Convert.ToDouble(GetString(key), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); - } - catch (FormatException) - { - throw new ConfigError("Incorrect data type"); - } - catch (QuickFIXException) - { - throw new ConfigError("No value for key: " + key); - } - } - - public bool GetBool(string key) - { - try - { - return Fields.Converters.BoolConverter.Convert(GetString(key)); - } - catch (FormatException) - { - throw new ConfigError("Incorrect data type"); - } - catch (QuickFIXException) - { - throw new ConfigError("No value for key: " + key); - } - } - - public System.DayOfWeek GetDay(string key) - { - string abbr = GetString(key).Substring(0, 2).ToUpper(); - switch(abbr) - { - case "SU": return System.DayOfWeek.Sunday; - case "MO": return System.DayOfWeek.Monday; - case "TU": return System.DayOfWeek.Tuesday; - case "WE": return System.DayOfWeek.Wednesday; - case "TH": return System.DayOfWeek.Thursday; - case "FR": return System.DayOfWeek.Friday; - case "SA": return System.DayOfWeek.Saturday; - default: throw new ConfigError("Illegal value " + GetString(key) + " for " + key); - } - } - - public TimeStampPrecision GetTimeStampPrecision( string key ) - { - string precision = GetString( key ).ToUpper(); - switch( precision ) - { - case "SECOND": - return TimeStampPrecision.Second; - case "MILLISECOND": - case "MILLI": - return TimeStampPrecision.Millisecond; - case "MICROSECOND": - case "MICRO": - return TimeStampPrecision.Microsecond; - case "NANOSECOND": - case "NANO": - return TimeStampPrecision.Nanosecond; - default: throw new ConfigError( "Illegal value " + GetString( key ) + " for " + key ); - } - } - - public void SetString(string key, string val) - { - data_[key.ToUpper()] = val; - } - - public void SetLong(string key, long val) - { - SetString(key, Convert.ToString(val)); - } - - public void SetDouble(string key, double val) - { - SetString(key, Convert.ToString(val, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)); - } - - public void SetBool(string key, bool val) - { - SetString(key, Fields.Converters.BoolConverter.Convert(val)); - } - - public void SetDay(string key, System.DayOfWeek val) - { - switch(val) - { - case System.DayOfWeek.Sunday: SetString(key, "SU"); break; - case System.DayOfWeek.Monday: SetString(key, "MO"); break; - case System.DayOfWeek.Tuesday: SetString(key, "TU"); break; - case System.DayOfWeek.Wednesday: SetString(key, "WE"); break; - case System.DayOfWeek.Thursday: SetString(key, "TH"); break; - case System.DayOfWeek.Friday: SetString(key, "FR"); break; - case System.DayOfWeek.Saturday: SetString(key, "SA"); break; - default: throw new ConfigError("Illegal value " + val + " for " + key); - } - } - - public bool Has(string key) - { - return data_.ContainsKey(key.ToUpper()); - } - - public void Merge(Dictionary toMerge) - { - foreach (System.Collections.Generic.KeyValuePair entry in toMerge.data_) - if(!data_.ContainsKey(entry.Key)) - data_[entry.Key] = entry.Value; - } - #endregion - - #region Public Overrides - /// - /// Test Dictionary objects for equality. - /// Dictionaries are deemed to be equal if their names and dictionary contents are the same - /// - /// Dictionary to compare against - /// true if the two Dictionary objects are the same in terms of contents, else false - public override bool Equals(object other) - { - //Check whether the compared objects reference the same data. - if (Object.ReferenceEquals(this, other)) - return true; - - //Check whether the compared object is null. - if (Object.ReferenceEquals(other, null)) - return false; - - //Check whether the names and dictionary contents are the same - var otherDict = (Dictionary)other; - if (Name != otherDict.Name || Count != otherDict.Count) - return false; - - // Could use LINQ query here, but this is probably faster! - string otherDictValue = null; - foreach (var kvp in data_) - if (!otherDict.data_.TryGetValue(kvp.Key, out otherDictValue) || otherDictValue != kvp.Value) - return false; - return true; - } - - /// - /// Generate hash code for the Dictionary. - /// If Equals() returns true for a compared object, - /// then GetHashCode() must return the same value for this object and the compared object. - /// - /// hash code - public override int GetHashCode() - { - int nameHash = Object.ReferenceEquals(Name, null) ? 1 : Name.GetHashCode(); - return nameHash + 100 * Count; - } - #endregion - - #region IEnumerable Members - - public System.Collections.IEnumerator GetEnumerator() - { - return data_.GetEnumerator(); - } - - #endregion - } -} diff --git a/QuickFIXn/IAcceptor.cs b/QuickFIXn/IAcceptor.cs index 7fe14de15..ab91b6486 100644 --- a/QuickFIXn/IAcceptor.cs +++ b/QuickFIXn/IAcceptor.cs @@ -49,7 +49,7 @@ public interface IAcceptor : IDisposable /// ID of session to be added /// session settings /// >true if session added successfully, false if session already exists or is not an acceptor - bool AddSession(SessionID sessionID, QuickFix.Dictionary dict); + bool AddSession(SessionID sessionID, QuickFix.SettingsDictionary dict); /// /// Remove an existing session after acceptor has been started diff --git a/QuickFIXn/IInitiator.cs b/QuickFIXn/IInitiator.cs index 6837d5a61..873f8d4d3 100644 --- a/QuickFIXn/IInitiator.cs +++ b/QuickFIXn/IInitiator.cs @@ -48,7 +48,7 @@ public interface IInitiator : IDisposable /// ID of session to be added /// session settings /// true if session added successfully, false if session already exists or is not an initiator - bool AddSession(SessionID sessionID, QuickFix.Dictionary dict); + bool AddSession(SessionID sessionID, QuickFix.SettingsDictionary dict); /// /// Remove an existing session after initiator has been started diff --git a/QuickFIXn/Logger/ScreenLogFactory.cs b/QuickFIXn/Logger/ScreenLogFactory.cs index 15d13ca03..0581f4c8f 100755 --- a/QuickFIXn/Logger/ScreenLogFactory.cs +++ b/QuickFIXn/Logger/ScreenLogFactory.cs @@ -24,7 +24,7 @@ public ILog Create(SessionID sessionId) { if(_settings.Has(sessionId)) { - Dictionary dict = _settings.Get(sessionId); + SettingsDictionary dict = _settings.Get(sessionId); if (dict.Has(SCREEN_LOG_SHOW_INCOMING)) logIncoming = dict.GetBool(SCREEN_LOG_SHOW_INCOMING); if (dict.Has(SCREEN_LOG_SHOW_OUTGOING)) diff --git a/QuickFIXn/SessionFactory.cs b/QuickFIXn/SessionFactory.cs index bd7055e8b..c8a245634 100755 --- a/QuickFIXn/SessionFactory.cs +++ b/QuickFIXn/SessionFactory.cs @@ -36,7 +36,7 @@ public SessionFactory( _messageFactory = messageFactory ?? new DefaultMessageFactory(); } - private static bool DetectIfInitiator(QuickFix.Dictionary settings) + private static bool DetectIfInitiator(QuickFix.SettingsDictionary settings) { switch (settings.GetString(SessionSettings.CONNECTION_TYPE)) { @@ -46,7 +46,7 @@ private static bool DetectIfInitiator(QuickFix.Dictionary settings) throw new ConfigError("Invalid ConnectionType"); } - public Session Create(SessionID sessionId, QuickFix.Dictionary settings) + public Session Create(SessionID sessionId, QuickFix.SettingsDictionary settings) { bool isInitiator = SessionFactory.DetectIfInitiator(settings); @@ -158,7 +158,7 @@ public Session Create(SessionID sessionId, QuickFix.Dictionary settings) return session; } - protected DataDictionary.DataDictionary CreateDataDictionary(SessionID sessionId, QuickFix.Dictionary settings, string settingsKey, string beginString) + protected DataDictionary.DataDictionary CreateDataDictionary(SessionID sessionId, QuickFix.SettingsDictionary settings, string settingsKey, string beginString) { string path; if (settings.Has(settingsKey)) @@ -189,7 +189,7 @@ protected DataDictionary.DataDictionary CreateDataDictionary(SessionID sessionId return ddCopy; } - protected void ProcessFixTDataDictionaries(SessionID sessionId, Dictionary settings, DataDictionaryProvider provider) + protected void ProcessFixTDataDictionaries(SessionID sessionId, SettingsDictionary settings, DataDictionaryProvider provider) { provider.AddTransportDataDictionary(sessionId.BeginString, CreateDataDictionary(sessionId, settings, SessionSettings.TRANSPORT_DATA_DICTIONARY, sessionId.BeginString)); @@ -218,7 +218,7 @@ protected void ProcessFixTDataDictionaries(SessionID sessionId, Dictionary setti } } - protected void ProcessFixDataDictionary(SessionID sessionId, Dictionary settings, DataDictionaryProvider provider) + protected void ProcessFixDataDictionary(SessionID sessionId, SettingsDictionary settings, DataDictionaryProvider provider) { DataDictionary.DataDictionary dataDictionary = CreateDataDictionary(sessionId, settings, SessionSettings.DATA_DICTIONARY, sessionId.BeginString); provider.AddTransportDataDictionary(sessionId.BeginString, dataDictionary); diff --git a/QuickFIXn/SessionSchedule.cs b/QuickFIXn/SessionSchedule.cs index ebb8390df..909209c59 100755 --- a/QuickFIXn/SessionSchedule.cs +++ b/QuickFIXn/SessionSchedule.cs @@ -186,7 +186,7 @@ private bool CheckTime(TimeSpan time) /// /// /// - public SessionSchedule(QuickFix.Dictionary settings) + public SessionSchedule(QuickFix.SettingsDictionary settings) { if (settings.Has(SessionSettings.NON_STOP_SESSION)) NonStopSession = settings.GetBool(SessionSettings.NON_STOP_SESSION); diff --git a/QuickFIXn/SessionSettings.cs b/QuickFIXn/SessionSettings.cs index 093e51029..c1075064c 100755 --- a/QuickFIXn/SessionSettings.cs +++ b/QuickFIXn/SessionSettings.cs @@ -85,8 +85,8 @@ public class SessionSettings #region Private Members - private QuickFix.Dictionary _defaults = new(); - private readonly System.Collections.Generic.Dictionary _settings = new(); + private SettingsDictionary _defaults = new(); + private readonly Dictionary _settings = new(); #endregion @@ -121,15 +121,15 @@ protected void Load(TextReader conf) Settings settings = new Settings(conf); //---- load the DEFAULT section - LinkedList section = settings.Get("DEFAULT"); - QuickFix.Dictionary def = new(); - if (section.Count > 0) - def = section.First!.Value; + LinkedList section = settings.Get("DEFAULT"); + SettingsDictionary def = section.Count > 0 + ? section.First!.Value + : new SettingsDictionary(name: "DEFAULT"); Set(def); //---- load each SESSION section section = settings.Get("SESSION"); - foreach (QuickFix.Dictionary dict in section) + foreach (SettingsDictionary dict in section) { dict.Merge(def); @@ -163,7 +163,7 @@ public bool Has(SessionID sessionId) /// Get global default settings /// /// Dictionary of settings from the [DEFAULT] section - public QuickFix.Dictionary Get() + public QuickFix.SettingsDictionary Get() { return _defaults; } @@ -173,17 +173,17 @@ public QuickFix.Dictionary Get() /// /// the ID of the session /// Dictionary of settings from the [SESSION] section for the given SessionID - public Dictionary Get(SessionID sessionId) + public SettingsDictionary Get(SessionID sessionId) { if (!_settings.TryGetValue(sessionId, out var dict)) throw new ConfigError($"Session '{sessionId}' not found"); return dict; } - public void Set(QuickFix.Dictionary defaults) + public void Set(QuickFix.SettingsDictionary defaults) { _defaults = defaults; - foreach (KeyValuePair entry in _settings) + foreach (KeyValuePair entry in _settings) entry.Value.Merge(_defaults); } @@ -202,7 +202,7 @@ public bool Remove(SessionID sessionId) /// /// ID of session for which to add config /// session config - public void Set(SessionID sessionId, QuickFix.Dictionary settings) + public void Set(SessionID sessionId, QuickFix.SettingsDictionary settings) { if (Has(sessionId)) throw new ConfigError($"Duplicate Session {sessionId}"); @@ -225,7 +225,7 @@ public void Set(SessionID sessionId, QuickFix.Dictionary settings) public HashSet GetSessions() { HashSet result = new HashSet(); - foreach (KeyValuePair entry in _settings) + foreach (KeyValuePair entry in _settings) result.Add(entry.Key); return result; } @@ -238,7 +238,7 @@ public override string ToString() foreach (System.Collections.Generic.KeyValuePair entry in _defaults) s.Append(entry.Key).Append('=').AppendLine(entry.Value); - foreach (KeyValuePair entry in _settings) + foreach (KeyValuePair entry in _settings) { s.AppendLine().AppendLine("[SESSION]"); foreach (System.Collections.Generic.KeyValuePair kvp in entry.Value) @@ -252,9 +252,9 @@ public override string ToString() return s.ToString(); } - protected void Validate(QuickFix.Dictionary dictionary) + protected void Validate(QuickFix.SettingsDictionary settingsDictionary) { - string beginString = dictionary.GetString(BEGINSTRING); + string beginString = settingsDictionary.GetString(BEGINSTRING); if (beginString != Values.BeginString_FIX40 && beginString != Values.BeginString_FIX41 && beginString != Values.BeginString_FIX42 && @@ -265,7 +265,7 @@ protected void Validate(QuickFix.Dictionary dictionary) throw new ConfigError($"{BEGINSTRING} ({beginString}) must be FIX.4.0 to FIX.4.4 or FIXT.1.1"); } - string connectionType = dictionary.GetString(CONNECTION_TYPE); + string connectionType = settingsDictionary.GetString(CONNECTION_TYPE); if (!"initiator".Equals(connectionType) && !"acceptor".Equals(connectionType)) { throw new ConfigError($"{CONNECTION_TYPE} must be 'initiator' or 'acceptor'"); diff --git a/QuickFIXn/Settings.cs b/QuickFIXn/Settings.cs index 1cd517ea1..1175ec2f3 100755 --- a/QuickFIXn/Settings.cs +++ b/QuickFIXn/Settings.cs @@ -5,11 +5,11 @@ namespace QuickFix { public class Settings { - private readonly LinkedList _sections = new(); + private readonly LinkedList _sections = new(); public Settings(System.IO.TextReader conf) { - QuickFix.Dictionary? currentSection = null; + QuickFix.SettingsDictionary? currentSection = null; string? line; while ((line = conf.ReadLine()) != null) @@ -22,7 +22,7 @@ public Settings(System.IO.TextReader conf) if (IsSection(line)) { - currentSection = Add(new Dictionary(SplitSection(line))); + currentSection = Add(new SettingsDictionary(SplitSection(line))); } else if (IsKeyValue(line) && currentSection != null) { @@ -61,7 +61,7 @@ public static bool IsSection(string s) return s[0] == '[' && s[^1] == ']'; } - public QuickFix.Dictionary Add(QuickFix.Dictionary section) + public QuickFix.SettingsDictionary Add(QuickFix.SettingsDictionary section) { _sections.AddLast(section); return section; @@ -73,10 +73,10 @@ public QuickFix.Dictionary Add(QuickFix.Dictionary section) /// /// (case is ignored) /// - public LinkedList Get(string sectionName) + public LinkedList Get(string sectionName) { - LinkedList result = new(); - foreach (QuickFix.Dictionary dict in _sections) + LinkedList result = new(); + foreach (QuickFix.SettingsDictionary dict in _sections) if (sectionName.ToUpperInvariant() == dict.Name.ToUpperInvariant()) result.AddLast(dict); return result; diff --git a/QuickFIXn/SettingsDictionary.cs b/QuickFIXn/SettingsDictionary.cs new file mode 100755 index 000000000..547cbcd7f --- /dev/null +++ b/QuickFIXn/SettingsDictionary.cs @@ -0,0 +1,277 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Linq; +using QuickFix.Fields.Converters; + +namespace QuickFix; + +/// +/// Name/value pairs used for specifying groups of settings. +/// All keys usages are case-insensitive (internally all are converted to upper-case). +/// +public class SettingsDictionary : System.Collections.IEnumerable +{ + private readonly Dictionary _data; + + public string Name { get; } + public int Count => _data.Count; + + /// + /// Alias for Count + /// + public int Size => Count; + + public SettingsDictionary() + : this("unnamed") + { } + + public SettingsDictionary(string name) + : this(name, new Dictionary()) + { } + + /// + /// Create a new SettingsDictionary with specified name but data copied from + /// the dataSource SettingsDictionary + /// + /// + /// + public SettingsDictionary(string name, SettingsDictionary dataSource) + : this(name, dataSource._data) + { } + + private SettingsDictionary(string name, Dictionary dataSource) + { + Name = name; + _data = dataSource + .Select(kvp => new {k = kvp.Key.ToUpperInvariant(), v = kvp.Value}) + .ToDictionary(x => x.k, x => x.v); + } + + public string GetString(string key) + { + if (_data.TryGetValue(key.ToUpperInvariant(), out var val)) + return val; + throw new ConfigError($"No value for key: {key}"); + } + + public String GetString(string key, bool capitalize) + { + string s = GetString(key); + return capitalize ? s.ToUpperInvariant() : s; + } + + public int GetInt(string key) + { + try + { + return Convert.ToInt32(GetString(key)); + } + catch (FormatException) + { + throw new ConfigError("Incorrect data type"); + } + catch (QuickFIXException) + { + throw new ConfigError($"No value for key: {key}"); + } + } + + public long GetLong(string key) + { + try + { + return Convert.ToInt64(GetString(key)); + } + catch(FormatException) + { + throw new ConfigError("Incorrect data type"); + } + catch(QuickFIXException) + { + throw new ConfigError($"No value for key: {key}"); + } + } + + public ulong GetULong(string key) + { + try + { + return Convert.ToUInt64(GetString(key)); + } + catch(FormatException) + { + throw new ConfigError("Incorrect data type"); + } + catch(QuickFIXException) + { + throw new ConfigError($"No value for key: {key}"); + } + } + + public double GetDouble(string key) + { + try + { + return Convert.ToDouble(GetString(key), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); + } + catch (FormatException) + { + throw new ConfigError("Incorrect data type"); + } + catch (QuickFIXException) + { + throw new ConfigError($"No value for key: {key}"); + } + } + + public bool GetBool(string key) + { + try + { + return BoolConverter.Convert(GetString(key)); + } + catch (FormatException) + { + throw new ConfigError("Incorrect data type"); + } + catch (QuickFIXException) + { + throw new ConfigError("No value for key: " + key); + } + } + + public DayOfWeek GetDay(string key) { + string abbr = GetString(key).Substring(0, 2).ToUpperInvariant(); + return abbr switch + { + "SU" => DayOfWeek.Sunday, + "MO" => DayOfWeek.Monday, + "TU" => DayOfWeek.Tuesday, + "WE" => DayOfWeek.Wednesday, + "TH" => DayOfWeek.Thursday, + "FR" => DayOfWeek.Friday, + "SA" => DayOfWeek.Saturday, + _ => throw new ConfigError($"Illegal value {GetString(key)} for {key}") + }; + } + + public TimeStampPrecision GetTimeStampPrecision( string key ) + { + string precision = GetString( key ).ToUpperInvariant(); + switch( precision ) + { + case "SECOND": + return TimeStampPrecision.Second; + case "MILLISECOND": + case "MILLI": + return TimeStampPrecision.Millisecond; + case "MICROSECOND": + case "MICRO": + return TimeStampPrecision.Microsecond; + case "NANOSECOND": + case "NANO": + return TimeStampPrecision.Nanosecond; + default: throw new ConfigError($"Illegal value {GetString(key)} for {key}"); + } + } + + public void SetString(string key, string val) + { + _data[key.ToUpperInvariant()] = val; + } + + public void SetLong(string key, long val) + { + SetString(key, Convert.ToString(val)); + } + + public void SetDouble(string key, double val) + { + SetString(key, Convert.ToString(val, System.Globalization.CultureInfo.InvariantCulture.NumberFormat)); + } + + public void SetBool(string key, bool val) + { + SetString(key, BoolConverter.Convert(val)); + } + + public void SetDay(string key, DayOfWeek val) + { + switch(val) + { + case DayOfWeek.Sunday: SetString(key, "SU"); break; + case DayOfWeek.Monday: SetString(key, "MO"); break; + case DayOfWeek.Tuesday: SetString(key, "TU"); break; + case DayOfWeek.Wednesday: SetString(key, "WE"); break; + case DayOfWeek.Thursday: SetString(key, "TH"); break; + case DayOfWeek.Friday: SetString(key, "FR"); break; + case DayOfWeek.Saturday: SetString(key, "SA"); break; + default: throw new ConfigError($"Illegal value {val} for {key}"); + } + } + + public bool Has(string key) + { + return _data.ContainsKey(key.ToUpperInvariant()); + } + + public void Merge(SettingsDictionary toMerge) + { + foreach (KeyValuePair entry in toMerge._data) + { + _data.TryAdd(entry.Key, entry.Value); + } + } + + #region Object Overrides + /// + /// Test Dictionary objects for equality. + /// Dictionaries are deemed to be equal if their names and dictionary contents are the same + /// + /// Dictionary to compare against + /// true if the two Dictionary objects are the same in terms of contents, else false + public override bool Equals(object? other) + { + //Check whether the compared objects reference the same data. + if (ReferenceEquals(this, other)) + return true; + + //Check whether the compared object is null. + if (ReferenceEquals(other, null)) + return false; + + //Check whether the names and dictionary contents are the same + var otherDict = (SettingsDictionary)other; + if (Name != otherDict.Name || Count != otherDict.Count) + return false; + + // Could use LINQ query here, but this is probably faster! + foreach (var kvp in _data) + if (!otherDict._data.TryGetValue(kvp.Key, out var otherDictValue) || otherDictValue != kvp.Value) + return false; + return true; + } + + /// + /// Generate hash code for the Dictionary. + /// If Equals() returns true for a compared object, + /// then GetHashCode() must return the same value for this object and the compared object. + /// + /// hash code + public override int GetHashCode() + { + int nameHash = ReferenceEquals(Name, null) ? 1 : Name.GetHashCode(); + return nameHash + 100 * Count; + } + #endregion + + #region IEnumerable Members + + public System.Collections.IEnumerator GetEnumerator() + { + return _data.GetEnumerator(); + } + + #endregion +} diff --git a/QuickFIXn/SocketSettings.cs b/QuickFIXn/SocketSettings.cs index 3915346f5..872c9aa64 100644 --- a/QuickFIXn/SocketSettings.cs +++ b/QuickFIXn/SocketSettings.cs @@ -166,63 +166,63 @@ public SocketSettings() /// used "Configure" as name since it is used in a lot of other places, /// alternative names are ReadSettings or FromDictionary /// - /// the dictionary to read the settings from - public void Configure(QuickFix.Dictionary dictionary) + /// the dictionary to read the settings from + public void Configure(QuickFix.SettingsDictionary settingsDictionary) { - if (dictionary.Has(SessionSettings.SOCKET_IGNORE_PROXY)) - SocketIgnoreProxy = dictionary.GetBool(SessionSettings.SOCKET_IGNORE_PROXY); + if (settingsDictionary.Has(SessionSettings.SOCKET_IGNORE_PROXY)) + SocketIgnoreProxy = settingsDictionary.GetBool(SessionSettings.SOCKET_IGNORE_PROXY); - if (dictionary.Has(SessionSettings.SOCKET_NODELAY)) - SocketNodelay = dictionary.GetBool(SessionSettings.SOCKET_NODELAY); + if (settingsDictionary.Has(SessionSettings.SOCKET_NODELAY)) + SocketNodelay = settingsDictionary.GetBool(SessionSettings.SOCKET_NODELAY); - if (dictionary.Has(SessionSettings.SOCKET_RECEIVE_BUFFER_SIZE)) - SocketReceiveBufferSize = dictionary.GetInt(SessionSettings.SOCKET_RECEIVE_BUFFER_SIZE); + if (settingsDictionary.Has(SessionSettings.SOCKET_RECEIVE_BUFFER_SIZE)) + SocketReceiveBufferSize = settingsDictionary.GetInt(SessionSettings.SOCKET_RECEIVE_BUFFER_SIZE); - if (dictionary.Has(SessionSettings.SOCKET_SEND_BUFFER_SIZE)) - SocketSendBufferSize = dictionary.GetInt(SessionSettings.SOCKET_SEND_BUFFER_SIZE); + if (settingsDictionary.Has(SessionSettings.SOCKET_SEND_BUFFER_SIZE)) + SocketSendBufferSize = settingsDictionary.GetInt(SessionSettings.SOCKET_SEND_BUFFER_SIZE); - if (dictionary.Has(SessionSettings.SOCKET_RECEIVE_TIMEOUT)) - SocketReceiveTimeout = dictionary.GetInt(SessionSettings.SOCKET_RECEIVE_TIMEOUT); + if (settingsDictionary.Has(SessionSettings.SOCKET_RECEIVE_TIMEOUT)) + SocketReceiveTimeout = settingsDictionary.GetInt(SessionSettings.SOCKET_RECEIVE_TIMEOUT); - if (dictionary.Has(SessionSettings.SOCKET_SEND_TIMEOUT)) - SocketSendTimeout = dictionary.GetInt(SessionSettings.SOCKET_SEND_TIMEOUT); + if (settingsDictionary.Has(SessionSettings.SOCKET_SEND_TIMEOUT)) + SocketSendTimeout = settingsDictionary.GetInt(SessionSettings.SOCKET_SEND_TIMEOUT); - if (dictionary.Has(SessionSettings.SSL_SERVERNAME)) - ServerCommonName = dictionary.GetString(SessionSettings.SSL_SERVERNAME); + if (settingsDictionary.Has(SessionSettings.SSL_SERVERNAME)) + ServerCommonName = settingsDictionary.GetString(SessionSettings.SSL_SERVERNAME); - if (dictionary.Has(SessionSettings.SSL_CA_CERTIFICATE)) - CACertificatePath = dictionary.GetString(SessionSettings.SSL_CA_CERTIFICATE); + if (settingsDictionary.Has(SessionSettings.SSL_CA_CERTIFICATE)) + CACertificatePath = settingsDictionary.GetString(SessionSettings.SSL_CA_CERTIFICATE); - if (dictionary.Has(SessionSettings.SSL_CERTIFICATE)) - CertificatePath = dictionary.GetString(SessionSettings.SSL_CERTIFICATE); + if (settingsDictionary.Has(SessionSettings.SSL_CERTIFICATE)) + CertificatePath = settingsDictionary.GetString(SessionSettings.SSL_CERTIFICATE); - if (dictionary.Has(SessionSettings.SSL_CERTIFICATE_PASSWORD)) - CertificatePassword = dictionary.GetString(SessionSettings.SSL_CERTIFICATE_PASSWORD); + if (settingsDictionary.Has(SessionSettings.SSL_CERTIFICATE_PASSWORD)) + CertificatePassword = settingsDictionary.GetString(SessionSettings.SSL_CERTIFICATE_PASSWORD); - if (dictionary.Has(SessionSettings.SSL_VALIDATE_CERTIFICATES)) - ValidateCertificates = dictionary.GetBool(SessionSettings.SSL_VALIDATE_CERTIFICATES); + if (settingsDictionary.Has(SessionSettings.SSL_VALIDATE_CERTIFICATES)) + ValidateCertificates = settingsDictionary.GetBool(SessionSettings.SSL_VALIDATE_CERTIFICATES); - if (dictionary.Has(SessionSettings.SSL_CHECK_CERTIFICATE_REVOCATION)) + if (settingsDictionary.Has(SessionSettings.SSL_CHECK_CERTIFICATE_REVOCATION)) { // can only be true if ValdateCertificates is true (this is noted in the config docs) - CheckCertificateRevocation = ValidateCertificates && dictionary.GetBool(SessionSettings.SSL_CHECK_CERTIFICATE_REVOCATION); + CheckCertificateRevocation = ValidateCertificates && settingsDictionary.GetBool(SessionSettings.SSL_CHECK_CERTIFICATE_REVOCATION); } // Use setting for client certificate check if one exist // otherwise enable client certificate check if a ca certificate is specified - if (dictionary.Has(SessionSettings.SSL_REQUIRE_CLIENT_CERTIFICATE)) - RequireClientCertificate = dictionary.GetBool(SessionSettings.SSL_REQUIRE_CLIENT_CERTIFICATE); + if (settingsDictionary.Has(SessionSettings.SSL_REQUIRE_CLIENT_CERTIFICATE)) + RequireClientCertificate = settingsDictionary.GetBool(SessionSettings.SSL_REQUIRE_CLIENT_CERTIFICATE); // Use setting for SSL if one exist // otherwise enable ssl if certificate path is specified - if (dictionary.Has(SessionSettings.SSL_ENABLE)) - UseSSL = dictionary.GetBool(SessionSettings.SSL_ENABLE); + if (settingsDictionary.Has(SessionSettings.SSL_ENABLE)) + UseSSL = settingsDictionary.GetBool(SessionSettings.SSL_ENABLE); else UseSSL = !string.IsNullOrEmpty(CertificatePath); - if (dictionary.Has(SessionSettings.SSL_PROTOCOLS)) + if (settingsDictionary.Has(SessionSettings.SSL_PROTOCOLS)) { - var protocolString = dictionary.GetString(SessionSettings.SSL_PROTOCOLS); + var protocolString = settingsDictionary.GetString(SessionSettings.SSL_PROTOCOLS); try { diff --git a/QuickFIXn/ThreadedSocketAcceptor.cs b/QuickFIXn/ThreadedSocketAcceptor.cs index 735dcb432..88e460bd0 100755 --- a/QuickFIXn/ThreadedSocketAcceptor.cs +++ b/QuickFIXn/ThreadedSocketAcceptor.cs @@ -48,7 +48,7 @@ public ThreadedSocketAcceptor( { foreach (SessionID sessionId in settings.GetSessions()) { - QuickFix.Dictionary dict = settings.Get(sessionId); + QuickFix.SettingsDictionary dict = settings.Get(sessionId); CreateSession(sessionId, dict); } } @@ -62,7 +62,7 @@ public ThreadedSocketAcceptor( #region Private Methods - private AcceptorSocketDescriptor GetAcceptorSocketDescriptor(Dictionary dict) + private AcceptorSocketDescriptor GetAcceptorSocketDescriptor(SettingsDictionary dict) { int port = System.Convert.ToInt32(dict.GetLong(SessionSettings.SOCKET_ACCEPT_PORT)); SocketSettings socketSettings = new SocketSettings(); @@ -118,7 +118,7 @@ private static bool IsAnyIpAddress(string host) /// ID of new session /// config settings for new session /// true if session added successfully, false if session already exists or is not an acceptor - private bool CreateSession(SessionID sessionId, Dictionary dict) + private bool CreateSession(SessionID sessionId, SettingsDictionary dict) { if (!_sessions.ContainsKey(sessionId)) { @@ -318,7 +318,7 @@ public Dictionary GetAcceptorAddresses() /// ID of new session /// config settings for new session /// true if session added successfully, false if session already exists or is not an acceptor - public bool AddSession(SessionID sessionId, Dictionary dict) + public bool AddSession(SessionID sessionId, SettingsDictionary dict) { lock (_settings) if (!_settings.Has(sessionId)) // session won't be in settings if ad-hoc creation after startup diff --git a/QuickFIXn/ThreadedSocketReactor.cs b/QuickFIXn/ThreadedSocketReactor.cs index 17b54215c..7a676e499 100755 --- a/QuickFIXn/ThreadedSocketReactor.cs +++ b/QuickFIXn/ThreadedSocketReactor.cs @@ -35,7 +35,7 @@ public State ReactorState private readonly Dictionary _clientThreads = new (); private readonly TcpListener _tcpListener; private readonly SocketSettings _socketSettings; - private readonly QuickFix.Dictionary _sessionDict; + private readonly QuickFix.SettingsDictionary _sessionDict; private readonly IPEndPoint _serverSocketEndPoint; private readonly AcceptorSocketDescriptor? _acceptorSocketDescriptor; @@ -44,14 +44,14 @@ public State ReactorState public ThreadedSocketReactor( IPEndPoint serverSocketEndPoint, SocketSettings socketSettings, - QuickFix.Dictionary sessionDict + QuickFix.SettingsDictionary sessionDict ) : this(serverSocketEndPoint, socketSettings, sessionDict, null) { } internal ThreadedSocketReactor( IPEndPoint serverSocketEndPoint, SocketSettings socketSettings, - QuickFix.Dictionary sessionDict, + QuickFix.SettingsDictionary sessionDict, AcceptorSocketDescriptor? acceptorSocketDescriptor) { _socketSettings = socketSettings; diff --git a/QuickFIXn/Transport/SocketInitiator.cs b/QuickFIXn/Transport/SocketInitiator.cs index f35638492..086949126 100644 --- a/QuickFIXn/Transport/SocketInitiator.cs +++ b/QuickFIXn/Transport/SocketInitiator.cs @@ -142,7 +142,7 @@ private void RemoveThread(SessionID sessionId) } } - private IPEndPoint GetNextSocketEndPoint(SessionID sessionId, QuickFix.Dictionary settings) + private IPEndPoint GetNextSocketEndPoint(SessionID sessionId, QuickFix.SettingsDictionary settings) { if (!_sessionToHostNum.TryGetValue(sessionId, out var num)) num = 0; @@ -237,7 +237,7 @@ protected override void OnStop() _shutdownRequested = true; } - protected override void DoConnect(Session session, Dictionary settings) + protected override void DoConnect(Session session, SettingsDictionary settings) { try { diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5e4b5afa6..70788fe49 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -51,6 +51,11 @@ What's New * ScreenLog ctor: removed unused sessionId param * ScreenLogFactory: remove public vars and a ctor that no one should be using * #708 - In FIX50, rename field SecurityStat to SecurityStatus, to match SP1 and SP2 (gbirchmeier) +* #639 - address Dictionary ctor bug, then cleanup/nullable-ize (gbirchmeier) + * rename to SettingsDictionary to reduce name confusion with System.Collections.Generic.Dictionary + * privatize a ctor that takes a generic Dict; apps shouldn't use it + * remove the copy ctor that takes only a SessionDict; replace it with one + that explicitly requires a name also **Non-breaking changes** * #400 - added DDTool, a C#-based codegen, and deleted Ruby-based generator (gbirchmeier) diff --git a/UnitTests/DictionaryTest.cs b/UnitTests/DictionaryTest.cs deleted file mode 100755 index 77bd4f0af..000000000 --- a/UnitTests/DictionaryTest.cs +++ /dev/null @@ -1,166 +0,0 @@ -using NUnit.Framework; -using QuickFix; - -namespace UnitTests -{ - [TestFixture] - public class DictionaryTest - { - [TearDown] - public void Teardown() - { - System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; - } - - [Test] - public void SetGetString() - { - QuickFix.Dictionary d = new QuickFix.Dictionary(); - d.SetString("STRINGKEY1", "STRINGVALUE1"); - d.SetString("STRINGKEY2", "stringvalue2"); - Assert.That(d.GetString("STRINGKEY1"), Is.EqualTo("STRINGVALUE1")); - Assert.That(d.GetString("STRINGKEY2"), Is.EqualTo("stringvalue2")); - Assert.That(d.GetString("STRINGKEY2", true), Is.EqualTo("STRINGVALUE2")); - Assert.Throws(delegate { d.GetString("STRINGKEY3"); }); - } - - [Test] - public void SetGetLong() - { - QuickFix.Dictionary d = new QuickFix.Dictionary(); - d.SetLong("LONGKEY1", 12); - d.SetLong("LONGKEY2", 987362); - d.SetString("BADLONGKEY", "AB12"); - Assert.That(d.GetLong("LONGKEY1"), Is.EqualTo(12)); - Assert.That(d.GetLong("LONGKEY2"), Is.EqualTo(987362)); - Assert.Throws(delegate { d.GetLong("LONGKEY3"); }); - Assert.Throws(delegate { d.GetLong("BADLONGKEY"); }); - } - - [Test] - public void SetDouble() - { - // make sure that QF/n uses the invariant culture, no matter what the current culture is - System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-FR"); - - QuickFix.Dictionary d = new QuickFix.Dictionary(); - d.SetDouble("DOUBLEKEY1", 12.3); - d.SetDouble("DOUBLEKEY2", 987362.987362); - - Assert.AreEqual("12.3", d.GetString("DOUBLEKEY1")); - Assert.AreEqual("987362.987362", d.GetString("DOUBLEKEY2")); - } - - [Test] - public void GetDouble() - { - // make sure that QF/n uses the invariant culture, no matter what the current culture is - System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-FR"); - - QuickFix.Dictionary d = new QuickFix.Dictionary(); - d.SetString("DOUBLEKEY1", "12.3"); - d.SetString("DOUBLEKEY2", "987362.987362"); - d.SetString("BADDOUBLEKEY", "AB12.3"); - d.SetString("FOREIGNFORMAT", "44,44"); - - Assert.That(d.GetDouble("DOUBLEKEY1"), Is.EqualTo(12.3)); - Assert.That(d.GetDouble("DOUBLEKEY2"), Is.EqualTo(987362.987362)); - Assert.Throws(delegate { d.GetDouble("DOUBLEKEY3"); }); - Assert.Throws(delegate { d.GetDouble("BADDOUBLEKEY"); }); - Assert.Throws(delegate { d.GetDouble("BADDOUBLEKEY"); }); - } - - [Test] - public void SetGetBool() - { - QuickFix.Dictionary d = new QuickFix.Dictionary(); - d.SetBool("BOOLKEY1", true); - d.SetBool("BOOLKEY2", false); - d.SetString("BADBOOLKEY2", "YO"); - Assert.That(d.GetBool("BOOLKEY1"), Is.True); - Assert.That(d.GetBool("BOOLKEY2"), Is.False); - Assert.Throws(delegate { d.GetBool("BOOLKEY3"); }); - Assert.Throws(delegate { d.GetBool("BADBOOLKEY2"); }); - } - - [Test] - public void SetGetDay() - { - QuickFix.Dictionary d = new QuickFix.Dictionary(); - - d.SetString("DAY1", "SU"); - d.SetString("DAY2", "MO"); - d.SetString("DAY3", "TU"); - d.SetString("DAY4", "WE"); - d.SetString("DAY5", "TH"); - d.SetString("DAY6", "FR"); - d.SetString("DAY7", "SA"); - Assert.That(d.GetDay("DAY1"), Is.EqualTo(System.DayOfWeek.Sunday)); - Assert.That(d.GetDay("DAY2"), Is.EqualTo(System.DayOfWeek.Monday)); - Assert.That(d.GetDay("DAY3"), Is.EqualTo(System.DayOfWeek.Tuesday)); - Assert.That(d.GetDay("DAY4"), Is.EqualTo(System.DayOfWeek.Wednesday)); - Assert.That(d.GetDay("DAY5"), Is.EqualTo(System.DayOfWeek.Thursday)); - Assert.That(d.GetDay("DAY6"), Is.EqualTo(System.DayOfWeek.Friday)); - Assert.That(d.GetDay("DAY7"), Is.EqualTo(System.DayOfWeek.Saturday)); - - d.SetDay("NEXTDAY1", System.DayOfWeek.Sunday); - d.SetDay("NEXTDAY2", System.DayOfWeek.Monday); - d.SetDay("NEXTDAY3", System.DayOfWeek.Tuesday); - d.SetDay("NEXTDAY4", System.DayOfWeek.Wednesday); - d.SetDay("NEXTDAY5", System.DayOfWeek.Thursday); - d.SetDay("NEXTDAY6", System.DayOfWeek.Friday); - d.SetDay("NEXTDAY7", System.DayOfWeek.Saturday); - Assert.That(d.GetDay("NEXTDAY1"), Is.EqualTo(System.DayOfWeek.Sunday)); - Assert.That(d.GetDay("NEXTDAY2"), Is.EqualTo(System.DayOfWeek.Monday)); - Assert.That(d.GetDay("NEXTDAY3"), Is.EqualTo(System.DayOfWeek.Tuesday)); - Assert.That(d.GetDay("NEXTDAY4"), Is.EqualTo(System.DayOfWeek.Wednesday)); - Assert.That(d.GetDay("NEXTDAY5"), Is.EqualTo(System.DayOfWeek.Thursday)); - Assert.That(d.GetDay("NEXTDAY6"), Is.EqualTo(System.DayOfWeek.Friday)); - Assert.That(d.GetDay("NEXTDAY7"), Is.EqualTo(System.DayOfWeek.Saturday)); - } - - [Test] - public void Merge() - { - QuickFix.Dictionary first = new QuickFix.Dictionary(); - first.SetString("FIRSTKEY", "FIRSTVALUE"); - first.SetString("THIRDKEY", "FIRST"); - - QuickFix.Dictionary second = new QuickFix.Dictionary(); - second.SetString("SECONDKEY", "SECONDVALUE"); - second.SetString("THIRDKEY", "SECOND"); - - first.Merge(second); - Assert.That(first.GetString("FIRSTKEY"), Is.EqualTo("FIRSTVALUE")); - Assert.That(first.GetString("SECONDKEY"), Is.EqualTo("SECONDVALUE")); - Assert.That(first.GetString("THIRDKEY"), Is.EqualTo("FIRST")); - } - - [Test] - public void ValueEquality() - { - QuickFix.Dictionary first = new QuickFix.Dictionary("Name"); - QuickFix.Dictionary second = new QuickFix.Dictionary("Name"); - Assert.True(first.Equals(second)); - - first.SetString("THIRDKEY", "FIRST"); - second.SetString("THIRDKEY", "SECOND"); - Assert.False(first.Equals(second)); - - first.SetString("THIRDKEY", "SECOND"); - Assert.True(first.Equals(second)); - - first.SetString("FIRSTKEY", "FIRSTVALUE"); - second.SetString("SECONDKEY", "SECONDVALUE"); - Assert.False(first.Equals(second)); - - first.SetString("SECONDKEY", "SECONDVALUE"); - second.SetString("FIRSTKEY", "FIRSTVALUE"); - Assert.True(first.Equals(second)); - - QuickFix.Dictionary third = new QuickFix.Dictionary("Name1"); - QuickFix.Dictionary fourth = new QuickFix.Dictionary("Name2"); - Assert.False(third.Equals(fourth)); - } - } -} diff --git a/UnitTests/FileStoreTests.cs b/UnitTests/FileStoreTests.cs index 165945e2d..bed03da65 100755 --- a/UnitTests/FileStoreTests.cs +++ b/UnitTests/FileStoreTests.cs @@ -28,7 +28,7 @@ public void Setup() _sessionID = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); - QuickFix.Dictionary config = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary config = new QuickFix.SettingsDictionary(); config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); config.SetString(QuickFix.SessionSettings.FILE_STORE_PATH, _storeDirectory); diff --git a/UnitTests/Logger/FileLogTests.cs b/UnitTests/Logger/FileLogTests.cs index 20c5a2e98..2a155132b 100644 --- a/UnitTests/Logger/FileLogTests.cs +++ b/UnitTests/Logger/FileLogTests.cs @@ -53,7 +53,7 @@ public void TestGeneratedFileName() QuickFix.SessionID sessionId = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); - QuickFix.Dictionary config = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary config = new QuickFix.SettingsDictionary(); config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); config.SetString(QuickFix.SessionSettings.FILE_LOG_PATH, logDirectory); @@ -74,7 +74,7 @@ public void TestGeneratedFileName() public void TestThrowsIfNoConfig() { QuickFix.SessionID sessionId = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); - QuickFix.Dictionary config = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary config = new QuickFix.SettingsDictionary(); config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); QuickFix.SessionSettings settings = new QuickFix.SessionSettings(); settings.Set(sessionId, config); diff --git a/UnitTests/SessionDynamicTest.cs b/UnitTests/SessionDynamicTest.cs index a29dc3e51..5953560ad 100644 --- a/UnitTests/SessionDynamicTest.cs +++ b/UnitTests/SessionDynamicTest.cs @@ -77,9 +77,9 @@ public SocketState(Socket s) HashSet _loggedOnCompIDs; Socket _listenSocket; - Dictionary CreateSessionConfig(string targetCompID, bool isInitiator) + SettingsDictionary CreateSessionConfig(string targetCompID, bool isInitiator) { - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.CONNECTION_TYPE, isInitiator ? "initiator" : "acceptor"); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.START_TIME, "12:00:00"); @@ -120,7 +120,7 @@ void StartEngine(bool initiator, bool twoSessions) TestApplication application = new TestApplication(LogonCallback, LogoffCallback); IMessageStoreFactory storeFactory = new MemoryStoreFactory(); SessionSettings settings = new SessionSettings(); - Dictionary defaults = new Dictionary(); + SettingsDictionary defaults = new SettingsDictionary(); defaults.SetString(QuickFix.SessionSettings.FILE_LOG_PATH, _logPath); // Put IP endpoint settings into default section to verify that that defaults get merged into diff --git a/UnitTests/SessionFactoryTest.cs b/UnitTests/SessionFactoryTest.cs index cab6bcd62..c0229b220 100755 --- a/UnitTests/SessionFactoryTest.cs +++ b/UnitTests/SessionFactoryTest.cs @@ -16,7 +16,7 @@ public void TestPersistMessages() SessionFactory factory = new SessionFactory(app, storeFactory); SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET"); - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); settings.SetString(SessionSettings.HEARTBTINT, "30"); @@ -40,7 +40,7 @@ public void ValidConfiguration() SessionFactory factory = new SessionFactory(app, storeFactory); SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET"); - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.START_TIME, "12:00:00"); @@ -58,7 +58,7 @@ public void StartDayAndEndDayAreDifferent() SessionFactory factory = new SessionFactory(app, storeFactory); SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET"); - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.START_TIME, "12:00:00"); @@ -78,7 +78,7 @@ public void TestExtendedSettings() SessionFactory factory = new SessionFactory(app, storeFactory); SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET"); - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.SEND_REDUNDANT_RESENDREQUESTS, "Y"); settings.SetString(SessionSettings.RESEND_SESSION_LEVEL_REJECTS, "Y"); @@ -120,7 +120,7 @@ public void TestTimeStampPrecisionSettings() SessionFactory factory = new SessionFactory(app, storeFactory); SessionID sessionID = new SessionID("FIX.4.2", "SENDER", "TARGET"); - Dictionary settings = new Dictionary(); + SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); settings.SetString(SessionSettings.USE_DATA_DICTIONARY, "N"); settings.SetString(SessionSettings.HEARTBTINT, "30"); diff --git a/UnitTests/SessionScheduleTests.cs b/UnitTests/SessionScheduleTests.cs index b5854f4d0..eaa9d9cff 100755 --- a/UnitTests/SessionScheduleTests.cs +++ b/UnitTests/SessionScheduleTests.cs @@ -46,7 +46,7 @@ public string PACIFIC_STANDARD_TIME_ZONE_ID [Test] public void testRequiredArgs() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); Assert.Throws(typeof(QuickFix.ConfigError), delegate { new QuickFix.SessionSchedule(settings); }); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); @@ -62,7 +62,7 @@ public void testRequiredArgs() [Test] public void testOptArgs() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -76,7 +76,7 @@ public void testOptArgs() [Test] public void testDailyIsSessionTimeAllDay() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -91,7 +91,7 @@ public void testDailyIsSessionTimeAllDay() [Test] public void testWeeklySessionSameDayAllWeek() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -117,7 +117,7 @@ public void testWeeklySessionSameDayAllWeek() [Test] public void testWeeklySessionSameDayMostWeek() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "05:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -143,7 +143,7 @@ public void testWeeklySessionSameDayMostWeek() [Test] public void testWeeklySessionSameDayOneDay() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "05:00:00"); @@ -169,7 +169,7 @@ public void testWeeklySessionSameDayOneDay() [Test] public void testWeeklySessionMultiDay() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -195,7 +195,7 @@ public void testWeeklySessionMultiDay() [Test] public void testWeeklySessionMultiDayOverlap() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); @@ -222,7 +222,7 @@ public void testWeeklySessionMultiDayOverlap() [Test] public void testWeeklySessionMultiDayHours() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "07:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "15:00:00"); @@ -256,7 +256,7 @@ public void testWeeklySessionMultiDayHours() [Test] public void testWeeklySessionMultiDayHoursOverlap() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "15:00:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "07:00:00"); @@ -281,7 +281,7 @@ public void testWeeklySessionMultiDayHoursOverlap() [Test] public void testDailyIsSessionTime() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "00:12:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "06:00:23"); @@ -298,7 +298,7 @@ public void testDailyIsSessionTime() [Test] public void testDailyIsSessionTimeWrapAround() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "06:00:23"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:12:00"); @@ -316,7 +316,7 @@ public void testDailyIsSessionTimeWrapAround() [Test] public void testInvalidTimeZone() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "06:00:23"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:12:00"); settings.SetString(QuickFix.SessionSettings.TIME_ZONE, "Doh"); @@ -327,7 +327,7 @@ public void testInvalidTimeZone() [Test] public void testLocalTimeTimeZoneConflict() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "06:00:23"); settings.SetString(QuickFix.SessionSettings.END_TIME, "00:12:00"); settings.SetString(QuickFix.SessionSettings.TIME_ZONE, "Doh"); @@ -340,7 +340,7 @@ public void testLocalTimeTimeZoneConflict() [Test] public void testTimeZone() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); @@ -356,7 +356,7 @@ public void testTimeZone() [Test] public void testNextEndTime_takesUtcOnly() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); QuickFix.SessionSchedule sched = new QuickFix.SessionSchedule(settings); @@ -371,7 +371,7 @@ public void testNextEndTime_takesUtcOnly() [Test] public void testNextEndTime_Daily() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); QuickFix.SessionSchedule sched = new QuickFix.SessionSchedule(settings); @@ -385,7 +385,7 @@ public void testNextEndTime_Daily() // ========== // Settings file is specified in a zone (est, -5) - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-5 @@ -400,7 +400,7 @@ public void testNextEndTime_Daily() // ========== // Time zone during Daylight Savings - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "05:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "12:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-4 for DST @@ -417,7 +417,7 @@ public void testNextEndTime_Daily() [Test] public void testNextEndTime_Weekly() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); settings.SetDay(QuickFix.SessionSettings.START_DAY, System.DayOfWeek.Monday); @@ -434,7 +434,7 @@ public void testNextEndTime_Weekly() // ========== // Settings file is specified in a zone (est, -5) - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-5 @@ -452,7 +452,7 @@ public void testNextEndTime_Weekly() // ========== // Time zone during Daylight Savings - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "05:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "12:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-4 for DST @@ -473,7 +473,7 @@ public void testNextEndTime_Weekly() [Test] public void testIsNewSession_takesUtcOnly() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); QuickFix.SessionSchedule sched = new QuickFix.SessionSchedule(settings); @@ -491,7 +491,7 @@ public void testIsNewSession_takesUtcOnly() [Test] public void testIsNewSession_Daily() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); QuickFix.SessionSchedule sched = new QuickFix.SessionSchedule(settings); @@ -511,7 +511,7 @@ public void testIsNewSession_Daily() // ========== // Settings file is specified in a zone (est, -5) - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-5 @@ -532,7 +532,7 @@ public void testIsNewSession_Daily() // ========== // Time zone during Daylight savings - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "05:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "12:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-4 during dst @@ -555,7 +555,7 @@ public void testIsNewSession_Daily() [Test] public void testAdjustDateTime() { - QuickFix.Dictionary settings = new QuickFix.Dictionary(); + QuickFix.SettingsDictionary settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "09:30:00"); settings.SetString(QuickFix.SessionSettings.END_TIME, "16:00:00"); QuickFix.SessionSchedule sched = new QuickFix.SessionSchedule(settings); @@ -571,7 +571,7 @@ public void testAdjustDateTime() Assert.AreEqual(d2, sched.AdjustUtcDateTime(d2)); // 3) if settings has a TimeZone, convert to TimeZone - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-5 @@ -583,7 +583,7 @@ public void testAdjustDateTime() Util.UtcDateTimeSerializerTests.AssertHackyDateTimeEquality(d3expected, d3actual); // now with Pacific Standard Time - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, PACIFIC_STANDARD_TIME_ZONE_ID); //-5 @@ -595,7 +595,7 @@ public void testAdjustDateTime() Util.UtcDateTimeSerializerTests.AssertHackyDateTimeEquality(d3expected, d3actual); // 4) TimeZone with daylight savings - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.TIME_ZONE, EASTERN_STANDARD_TIME_ZONE_ID); //-4 in June @@ -607,7 +607,7 @@ public void testAdjustDateTime() Util.UtcDateTimeSerializerTests.AssertHackyDateTimeEquality(d4expected, d4actual); // 5) if settings has UseLocalTime, convert to local time - settings = new QuickFix.Dictionary(); + settings = new QuickFix.SettingsDictionary(); settings.SetString(QuickFix.SessionSettings.START_TIME, "04:30:00"); // 09:30:00 utc settings.SetString(QuickFix.SessionSettings.END_TIME, "11:00:00"); // 16:00:00 utc settings.SetString(QuickFix.SessionSettings.USE_LOCAL_TIME, "Y"); diff --git a/UnitTests/SessionSettingsTest.cs b/UnitTests/SessionSettingsTest.cs index 585eea473..fd2fd8f0c 100755 --- a/UnitTests/SessionSettingsTest.cs +++ b/UnitTests/SessionSettingsTest.cs @@ -196,20 +196,20 @@ public void Validate() SessionID sessionID = new SessionID("FIX.4.2", "SenderCompID", "TargetCompID"); // ConnectionType not set - QuickFix.Dictionary dictionary = new QuickFix.Dictionary(); - Assert.Throws(delegate { settings.Set(sessionID, dictionary); }); + QuickFix.SettingsDictionary settingsDictionary = new QuickFix.SettingsDictionary(); + Assert.Throws(delegate { settings.Set(sessionID, settingsDictionary); }); // ConnectionType set to invalid value - dictionary.SetString(SessionSettings.CONNECTION_TYPE, "badvalue"); - Assert.Throws(delegate { settings.Set(sessionID, dictionary); }); + settingsDictionary.SetString(SessionSettings.CONNECTION_TYPE, "badvalue"); + Assert.Throws(delegate { settings.Set(sessionID, settingsDictionary); }); // ConnectionType set to valid value - dictionary.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); - Assert.DoesNotThrow(delegate { settings.Set(sessionID, dictionary); }); + settingsDictionary.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); + Assert.DoesNotThrow(delegate { settings.Set(sessionID, settingsDictionary); }); // Invalid BeginString sessionID = new SessionID("FIX4.2", "SenderCompID", "TargetCompID"); - Assert.Throws(delegate { settings.Set(sessionID, dictionary); }); + Assert.Throws(delegate { settings.Set(sessionID, settingsDictionary); }); } [Test] diff --git a/UnitTests/SessionStateTest.cs b/UnitTests/SessionStateTest.cs index 614458a51..2e0db7cc4 100755 --- a/UnitTests/SessionStateTest.cs +++ b/UnitTests/SessionStateTest.cs @@ -141,7 +141,7 @@ public void ThreadSafeSetAndGet() { SessionID sessionId = new SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); - Dictionary config = new Dictionary(); + SettingsDictionary config = new SettingsDictionary(); config.SetString(SessionSettings.CONNECTION_TYPE, "initiator"); config.SetString(SessionSettings.FILE_STORE_PATH, storeDirectory); diff --git a/UnitTests/SessionTest.cs b/UnitTests/SessionTest.cs index 808796eb7..cda66f587 100755 --- a/UnitTests/SessionTest.cs +++ b/UnitTests/SessionTest.cs @@ -176,7 +176,7 @@ public class SessionTest MockApplication application = null; QuickFix.Session session = null; QuickFix.Session session2 = null; - QuickFix.Dictionary config = null; + QuickFix.SettingsDictionary config = null; SeqNumType seqNum = 1; Regex msRegex = new Regex(@"\.[\d]{1,3}$"); Regex microsecondRegex = new Regex(@"\.[\d]{1,6}$"); @@ -189,7 +189,7 @@ public void Setup() application = new MockApplication(); settings = new QuickFix.SessionSettings(); - config = new QuickFix.Dictionary(); + config = new QuickFix.SettingsDictionary(); config.SetBool(QuickFix.SessionSettings.PERSIST_MESSAGES, false); config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); config.SetString(QuickFix.SessionSettings.START_TIME, "00:00:00"); diff --git a/UnitTests/SettingsDictionaryTests.cs b/UnitTests/SettingsDictionaryTests.cs new file mode 100755 index 000000000..4a1dd4ec0 --- /dev/null +++ b/UnitTests/SettingsDictionaryTests.cs @@ -0,0 +1,179 @@ +#nullable enable +using NUnit.Framework; +using QuickFix; + +namespace UnitTests; + +[TestFixture] +public class SettingsDictionaryTests +{ + [TearDown] + public void Teardown() + { + System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; + } + + [Test] + public void SetGetString() + { + SettingsDictionary d = new(); + d.SetString("STRINGKEY1", "STRINGVALUE1"); + d.SetString("STRINGKEY2", "stringvalue2"); + Assert.That(d.GetString("STRINGKEY1"), Is.EqualTo("STRINGVALUE1")); + Assert.That(d.GetString("STRINGKEY2"), Is.EqualTo("stringvalue2")); + Assert.That(d.GetString("STRINGKEY2", true), Is.EqualTo("STRINGVALUE2")); + Assert.Throws(delegate { d.GetString("STRINGKEY3"); }); + } + + [Test] + public void SetGetLong() + { + SettingsDictionary d = new(); + d.SetLong("LONGKEY1", 12); + d.SetLong("LONGKEY2", 987362); + d.SetString("BADLONGKEY", "AB12"); + Assert.That(d.GetLong("LONGKEY1"), Is.EqualTo(12)); + Assert.That(d.GetLong("LONGKEY2"), Is.EqualTo(987362)); + Assert.Throws(delegate { d.GetLong("LONGKEY3"); }); + Assert.Throws(delegate { d.GetLong("BADLONGKEY"); }); + } + + [Test] + public void SetDouble() + { + // make sure that QF/n uses the invariant culture, no matter what the current culture is + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-FR"); + + SettingsDictionary d = new(); + d.SetDouble("DOUBLEKEY1", 12.3); + d.SetDouble("DOUBLEKEY2", 987362.987362); + + Assert.AreEqual("12.3", d.GetString("DOUBLEKEY1")); + Assert.AreEqual("987362.987362", d.GetString("DOUBLEKEY2")); + } + + [Test] + public void GetDouble() + { + // make sure that QF/n uses the invariant culture, no matter what the current culture is + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("fr-FR"); + + SettingsDictionary d = new(); + d.SetString("DOUBLEKEY1", "12.3"); + d.SetString("DOUBLEKEY2", "987362.987362"); + d.SetString("BADDOUBLEKEY", "AB12.3"); + d.SetString("FOREIGNFORMAT", "44,44"); + + Assert.That(d.GetDouble("DOUBLEKEY1"), Is.EqualTo(12.3)); + Assert.That(d.GetDouble("DOUBLEKEY2"), Is.EqualTo(987362.987362)); + Assert.Throws(delegate { d.GetDouble("DOUBLEKEY3"); }); + Assert.Throws(delegate { d.GetDouble("BADDOUBLEKEY"); }); + Assert.Throws(delegate { d.GetDouble("BADDOUBLEKEY"); }); + } + + [Test] + public void SetGetBool() + { + SettingsDictionary d = new(); + d.SetBool("BOOLKEY1", true); + d.SetBool("BOOLKEY2", false); + d.SetString("BADBOOLKEY2", "YO"); + Assert.That(d.GetBool("BOOLKEY1"), Is.True); + Assert.That(d.GetBool("BOOLKEY2"), Is.False); + Assert.Throws(delegate { d.GetBool("BOOLKEY3"); }); + Assert.Throws(delegate { d.GetBool("BADBOOLKEY2"); }); + } + + [Test] + public void SetGetDay() + { + SettingsDictionary d = new(); + + d.SetString("DAY1", "SU"); + d.SetString("DAY2", "MO"); + d.SetString("DAY3", "TU"); + d.SetString("DAY4", "WE"); + d.SetString("DAY5", "TH"); + d.SetString("DAY6", "FR"); + d.SetString("DAY7", "SA"); + Assert.That(d.GetDay("DAY1"), Is.EqualTo(System.DayOfWeek.Sunday)); + Assert.That(d.GetDay("DAY2"), Is.EqualTo(System.DayOfWeek.Monday)); + Assert.That(d.GetDay("DAY3"), Is.EqualTo(System.DayOfWeek.Tuesday)); + Assert.That(d.GetDay("DAY4"), Is.EqualTo(System.DayOfWeek.Wednesday)); + Assert.That(d.GetDay("DAY5"), Is.EqualTo(System.DayOfWeek.Thursday)); + Assert.That(d.GetDay("DAY6"), Is.EqualTo(System.DayOfWeek.Friday)); + Assert.That(d.GetDay("DAY7"), Is.EqualTo(System.DayOfWeek.Saturday)); + + d.SetDay("NEXTDAY1", System.DayOfWeek.Sunday); + d.SetDay("NEXTDAY2", System.DayOfWeek.Monday); + d.SetDay("NEXTDAY3", System.DayOfWeek.Tuesday); + d.SetDay("NEXTDAY4", System.DayOfWeek.Wednesday); + d.SetDay("NEXTDAY5", System.DayOfWeek.Thursday); + d.SetDay("NEXTDAY6", System.DayOfWeek.Friday); + d.SetDay("NEXTDAY7", System.DayOfWeek.Saturday); + Assert.That(d.GetDay("NEXTDAY1"), Is.EqualTo(System.DayOfWeek.Sunday)); + Assert.That(d.GetDay("NEXTDAY2"), Is.EqualTo(System.DayOfWeek.Monday)); + Assert.That(d.GetDay("NEXTDAY3"), Is.EqualTo(System.DayOfWeek.Tuesday)); + Assert.That(d.GetDay("NEXTDAY4"), Is.EqualTo(System.DayOfWeek.Wednesday)); + Assert.That(d.GetDay("NEXTDAY5"), Is.EqualTo(System.DayOfWeek.Thursday)); + Assert.That(d.GetDay("NEXTDAY6"), Is.EqualTo(System.DayOfWeek.Friday)); + Assert.That(d.GetDay("NEXTDAY7"), Is.EqualTo(System.DayOfWeek.Saturday)); + } + + [Test] + public void Merge() + { + SettingsDictionary first = new(); + first.SetString("FIRSTKEY", "FIRSTVALUE"); + first.SetString("THIRDKEY", "FIRST"); + + SettingsDictionary second = new(); + second.SetString("SECONDKEY", "SECONDVALUE"); + second.SetString("THIRDKEY", "SECOND"); + + first.Merge(second); + Assert.That(first.GetString("FIRSTKEY"), Is.EqualTo("FIRSTVALUE")); + Assert.That(first.GetString("SECONDKEY"), Is.EqualTo("SECONDVALUE")); + Assert.That(first.GetString("THIRDKEY"), Is.EqualTo("FIRST")); + } + + [Test] + public void ValueEquality() + { + SettingsDictionary first = new("MyName"); + SettingsDictionary second = new("MyName"); + Assert.True(first.Equals(second)); + + first.SetString("THIRDKEY", "FIRST"); + second.SetString("THIRDKEY", "SECOND"); + Assert.False(first.Equals(second)); + + first.SetString("THIRDKEY", "SECOND"); + Assert.True(first.Equals(second)); + + first.SetString("FIRSTKEY", "FIRSTVALUE"); + second.SetString("SECONDKEY", "SECONDVALUE"); + Assert.False(first.Equals(second)); + + first.SetString("SECONDKEY", "SECONDVALUE"); + second.SetString("FIRSTKEY", "FIRSTVALUE"); + Assert.True(first.Equals(second)); + + SettingsDictionary third = new("Name1"); + SettingsDictionary fourth = new("Name2"); + Assert.False(third.Equals(fourth)); + } + + [Test] + public void CopyCtor() { + SettingsDictionary orig = new("orig"); + orig.SetString("uno", "One"); + orig.SetLong("dos", 2); + + SettingsDictionary dupe = new("dupe", orig); + + Assert.AreEqual(2, dupe.Count); + Assert.AreEqual("One", dupe.GetString("uNo")); + Assert.AreEqual("2", dupe.GetString("DOs")); + } +} diff --git a/UnitTests/SettingsTest.cs b/UnitTests/SettingsTest.cs index e3b037759..94cc53b3b 100644 --- a/UnitTests/SettingsTest.cs +++ b/UnitTests/SettingsTest.cs @@ -32,14 +32,14 @@ public void Load() "; Settings settings = new Settings(new System.IO.StringReader(configuration)); - LinkedList foo = settings.Get("FOO"); + LinkedList foo = settings.Get("FOO"); Assert.That(foo.Count, Is.EqualTo(1)); Assert.That(foo.First.Value.GetLong("bar"), Is.EqualTo(24)); Assert.That(foo.First.Value.GetString("baz"), Is.EqualTo("moo")); Assert.That(foo.First.Value.GetString("baz"), Is.EqualTo("moo")); Assert.That(foo.First.Value.Count, Is.EqualTo(2)); - LinkedList oren = settings.Get("OREN"); + LinkedList oren = settings.Get("OREN"); Assert.That(oren.Count, Is.EqualTo(2)); Assert.That(oren.First.Value.Count, Is.EqualTo(1)); Assert.That(oren.First.Value.GetString("Nero"), Is.EqualTo("TW")); @@ -48,7 +48,7 @@ public void Load() Assert.That(oren.First.Value.GetString("ISLD"), Is.EqualTo("Nero")); Assert.That(oren.First.Value.GetString("STUFF"), Is.EqualTo("./\\:")); - LinkedList nero = settings.Get("NERO"); + LinkedList nero = settings.Get("NERO"); Assert.That(nero.Count, Is.EqualTo(1)); Assert.That(nero.First.Value.Count, Is.EqualTo(5)); Assert.That(nero.First.Value.GetString("WINDIR"), Is.EqualTo("D:\\This Is\\A-Directory\\Connamara\\")); @@ -68,14 +68,14 @@ public void CaseInsensitiveSectionName() what=huh"; Settings settings = new Settings(new System.IO.StringReader(configuration)); - LinkedList byLower = settings.Get("foo"); + LinkedList byLower = settings.Get("foo"); Assert.AreEqual(1, byLower.Count); Assert.AreEqual(2, byLower.First.Value.Count); Assert.AreEqual("uno", byLower.First.Value.GetString("one")); Assert.AreEqual("dos", byLower.First.Value.GetString("two")); // too lazy to write a QuickFix.Dictionary#Equals method (which would only be used by this test) - LinkedList byUpper = settings.Get("FOO"); + LinkedList byUpper = settings.Get("FOO"); Assert.AreEqual(byLower.Count, byUpper.Count); Assert.AreEqual(byLower.First.Value.Count, byUpper.First.Value.Count); Assert.AreEqual(byUpper.First.Value.GetString("one"), byUpper.First.Value.GetString("one")); diff --git a/UnitTests/SocketSettingsTest.cs b/UnitTests/SocketSettingsTest.cs index 766729a3d..50cb36a92 100644 --- a/UnitTests/SocketSettingsTest.cs +++ b/UnitTests/SocketSettingsTest.cs @@ -29,9 +29,9 @@ public void DefaultValues() Assert.IsTrue(socketSettings.RequireClientCertificate); } - private Dictionary BaseTestDict() + private SettingsDictionary BaseTestDict() { - Dictionary dict = new Dictionary(); + SettingsDictionary dict = new SettingsDictionary(); dict.SetBool(SessionSettings.SOCKET_IGNORE_PROXY, false); dict.SetBool(SessionSettings.SOCKET_NODELAY, false); dict.SetLong(SessionSettings.SOCKET_RECEIVE_BUFFER_SIZE, 1); @@ -105,4 +105,4 @@ public void Configure_SslOverride() Assert.IsFalse(socketSettings.CheckCertificateRevocation); } } -} \ No newline at end of file +}