From e846384b53a46f12f0093fe21bfef3ca11f7d616 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Wed, 25 Sep 2024 16:12:13 -0500 Subject: [PATCH 1/5] split up SessionTest and nullable-ize it --- QuickFIXn/IApplicationExt.cs | 15 +- UnitTests/SessionTest.cs | 1511 ++++++++--------- .../SessionTestSupport/MockApplication.cs | 40 + .../SessionTestSupport/MockApplicationExt.cs | 28 + UnitTests/SessionTestSupport/MockResponder.cs | 66 + 5 files changed, 836 insertions(+), 824 deletions(-) create mode 100644 UnitTests/SessionTestSupport/MockApplication.cs create mode 100644 UnitTests/SessionTestSupport/MockApplicationExt.cs create mode 100644 UnitTests/SessionTestSupport/MockResponder.cs diff --git a/QuickFIXn/IApplicationExt.cs b/QuickFIXn/IApplicationExt.cs index 2555472cc..30ee02f76 100644 --- a/QuickFIXn/IApplicationExt.cs +++ b/QuickFIXn/IApplicationExt.cs @@ -7,20 +7,23 @@ namespace QuickFix /// and facilitates early interception of such messages. 'Early', in this context, /// means after structure, length and checksum have been validated, but before any /// further validation has been performed. + /// /// This interface will not normally be required, and it should be used only with caution: - /// it allows modfications to be made to irregular inbound messages that would otherwise + /// it allows modifications to be made to irregular inbound messages that would otherwise /// fail validation against the Fix dictionary, an provides an alternative to dictionary /// customisation as a means of dealing with such messages. /// public interface IApplicationExt : IApplication { /// - /// This callback provides early notification of when an administrative or application message is sent from a counterparty to your FIX engine. - /// This can be useful for doing pre-processing of an inbound message after its structure, checksum and length have been validated, but before - /// any further validation has been performed on it. + /// This callback provides early notification of when an administrative or application + /// message is sent from a counterparty to your FIX engine. + /// This can be useful for doing pre-processing of an inbound message after its structure, + /// checksum and length have been validated, but before + /// any further validation has been performed on it. /// /// received message - /// session on which message received - void FromEarlyIntercept(Message message, SessionID sessionID); + /// session on which message received + void FromEarlyIntercept(Message message, SessionID sessionId); } } diff --git a/UnitTests/SessionTest.cs b/UnitTests/SessionTest.cs index 4715986e9..87368e25d 100755 --- a/UnitTests/SessionTest.cs +++ b/UnitTests/SessionTest.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; @@ -7,938 +9,811 @@ using QuickFix.Logger; using QuickFix.Store; -namespace UnitTests +namespace UnitTests; + +[TestFixture] +public class SessionTest { - internal class MockResponder : QuickFix.IResponder + private SessionTestSupport.MockResponder _responder = new(); + + private QuickFix.SessionID _sessionId = new("unset", "unset", "unset"); + private QuickFix.SessionSettings _settings = new(); + private SessionTestSupport.MockApplication _application = new(); + private QuickFix.Session? _session = null; + private QuickFix.Session? _session2 = null; + private QuickFix.SettingsDictionary _config = new(); + private SeqNumType _seqNum = 1; + private readonly Regex _msRegex = new(@"\.[\d]{1,3}$"); + private readonly Regex _microsecondRegex = new(@"\.[\d]{1,6}$"); + + [SetUp] + public void Setup() { - private readonly QuickFix.DefaultMessageFactory _messageFactory = new(); - private readonly QuickFix.IMessageFactory _defaultMsgFactory = new QuickFix.DefaultMessageFactory(); - - public Dictionary> MsgLookup = new(); - public Queue Dups = new(); - - public bool Disconnected = false; - - #region Responder Members - public bool Send(string msgStr) - { - QuickFix.Fields.MsgType msgType = QuickFix.Message.IdentifyType(msgStr); - string beginString = QuickFix.Message.ExtractBeginString(msgStr); - - QuickFix.Message message = _messageFactory.Create(beginString, msgType.Value); - QuickFix.DataDictionary.DataDictionary dd = new QuickFix.DataDictionary.DataDictionary(); - message.FromString(msgStr, false, dd, dd, _defaultMsgFactory); - - if (!MsgLookup.ContainsKey(msgType.Value)) - MsgLookup.Add(msgType.Value, new Queue()); - - MsgLookup[msgType.Value].Enqueue(message); - - QuickFix.Fields.PossDupFlag possDup = new QuickFix.Fields.PossDupFlag(false); - if (message.Header.IsSetField(possDup)) - message.Header.GetField(possDup); - - if (possDup.Value && msgType.Value != QuickFix.Fields.MsgType.SEQUENCE_RESET) - { - Dups.Enqueue(message); - } - - return true; - } - - public void Disconnect() - { - Disconnected = true; - } - #endregion - - /// - /// For debug use if needed - /// - public void DumpMsgLookup() - { - Console.WriteLine("Responder dump:"); - foreach (string key in MsgLookup.Keys) - { - Console.WriteLine($" {key}: count {MsgLookup[key].Count}"); - foreach (QuickFix.Message m in MsgLookup[key]) - { - Console.WriteLine(" - " + m.ConstructString()); - } - } - } - - public int GetCount(string msgType) - { - return MsgLookup.TryGetValue(msgType, out var value) ? value.Count : 0; - } - + _responder = new SessionTestSupport.MockResponder(); + _sessionId = new QuickFix.SessionID("FIX.4.2", "SENDER", "TARGET"); + _application = new SessionTestSupport.MockApplication(); + _settings = new QuickFix.SessionSettings(); + + _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"); + _config.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); + _settings.Set(_sessionId, _config); + + var logFactory = new NullLogFactory(); // use QuickFix.ScreenLogFactory(settings) if you need to see output + + // acceptor + _session = new QuickFix.Session(false, _application, new MemoryStoreFactory(), _sessionId, + new QuickFix.DataDictionaryProvider(),new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); + _session.SetResponder(_responder); + _session.CheckLatency = false; + + // initiator + _session2 = new QuickFix.Session(true, _application, new MemoryStoreFactory(), new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"), + new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); + _session2.SetResponder(_responder); + _session2.CheckLatency = false; + + _seqNum = 1; } - class MockApplication : QuickFix.IApplication + public void Logon() { - public Exception FromAppException = null; - public Exception FromAdminException = null; - public QuickFix.DoNotSend DoNotSendException = null; - - public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } - - public void FromAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) - { - if (FromAdminException is not null) - throw FromAdminException; - } - - public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId) - { - if (DoNotSendException is not null) - throw DoNotSendException; - } + SendLogon(new QuickFix.FIX42.Logon()); + } - public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionId) - { - if (FromAppException is not null) - throw FromAppException; - } + public void Logon40() + { + SendLogon(new QuickFix.FIX40.Logon()); + } - public void OnCreate(QuickFix.SessionID sessionId) { } + private void SendLogon(QuickFix.Message msg) + { + msg.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + msg.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + msg.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); + msg.Header.SetField(new QuickFix.Fields.SendingTime(DateTime.UtcNow)); + msg.SetField(new QuickFix.Fields.HeartBtInt(1)); + _session!.Next(msg.ConstructString()); + } - public void OnLogout(QuickFix.SessionID sessionId) - { - throw new NotImplementedException(); - } + public bool SENT_SEQUENCE_RESET() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.SEQUENCE_RESET) && + _responder.MsgLookup[QuickFix.Fields.MsgType.SEQUENCE_RESET].Count > 0; + } - public void OnLogon(QuickFix.SessionID sessionId) { } + public bool SENT_RESEND_REQUEST() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.RESEND_REQUEST) && + _responder.MsgLookup[QuickFix.Fields.MsgType.RESEND_REQUEST].Count > 0; } - class MockApplicationExt : QuickFix.IApplicationExt + public bool RESENT() { - public HashSet InterceptedMessageTypes = new(); + if (_responder.Dups.Count == 0) + return false; - public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } + _responder.Dups.Dequeue(); + return true; + } - public void FromAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } + public bool SENT_REJECT() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT) && + _responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Count>0; + } - public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId) { } + public bool SENT_HEART_BEAT() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.HEARTBEAT) && + _responder.MsgLookup[QuickFix.Fields.MsgType.HEARTBEAT].Count > 0; + } - public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionId) { } + public bool SENT_BUSINESS_REJECT() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT) && + _responder.MsgLookup[QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT].Count > 0; + } - public void OnCreate(QuickFix.SessionID sessionId) { } + public bool SENT_BUSINESS_REJECT(int reason) + { + if (!SENT_BUSINESS_REJECT()) + return false; - public void OnLogout(QuickFix.SessionID sessionId) { } + QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT].First(); - public void OnLogon(QuickFix.SessionID sessionId) { } + if (!msg.IsSetField(QuickFix.Fields.Tags.BusinessRejectReason)) + return false; - public void FromEarlyIntercept(QuickFix.Message message, QuickFix.SessionID sessionId) - { - InterceptedMessageTypes.Add(message.Header.GetString(QuickFix.Fields.Tags.MsgType)); - } + QuickFix.Fields.BusinessRejectReason reasonField = new QuickFix.Fields.BusinessRejectReason(); + msg.GetField(reasonField); + return reasonField.Value == reason; } - [TestFixture] - public class SessionTest + public bool SENT_LOGOUT() { - private MockResponder _responder = null; - - private QuickFix.SessionID _sessionId = null; - private QuickFix.SessionSettings _settings = null; - private MockApplication _application = null; - private QuickFix.Session _session = null; - private QuickFix.Session _session2 = null; - private QuickFix.SettingsDictionary _config = null; - private SeqNumType _seqNum = 1; - private readonly Regex _msRegex = new(@"\.[\d]{1,3}$"); - private readonly Regex _microsecondRegex = new(@"\.[\d]{1,6}$"); - - [SetUp] - public void Setup() - { - _responder = new MockResponder(); - _sessionId = new QuickFix.SessionID("FIX.4.2", "SENDER", "TARGET"); - _application = new MockApplication(); - _settings = new QuickFix.SessionSettings(); - - _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"); - _config.SetString(QuickFix.SessionSettings.END_TIME, "00:00:00"); - _settings.Set(_sessionId, _config); - - var logFactory = new NullLogFactory(); // use QuickFix.ScreenLogFactory(settings) if you need to see output - - // acceptor - _session = new QuickFix.Session(false, _application, new MemoryStoreFactory(), _sessionId, - new QuickFix.DataDictionaryProvider(),new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); - _session.SetResponder(_responder); - _session.CheckLatency = false; - - // initiator - _session2 = new QuickFix.Session(true, _application, new MemoryStoreFactory(), new QuickFix.SessionID("FIX.4.2", "OTHER_SENDER", "OTHER_TARGET"), - new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config), 0, logFactory, new QuickFix.DefaultMessageFactory(), "blah"); - _session2.SetResponder(_responder); - _session2.CheckLatency = false; - - _seqNum = 1; - } - - public void Logon() - { - SendLogon(new QuickFix.FIX42.Logon()); - } + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.LOGOUT) && + _responder.MsgLookup[QuickFix.Fields.MsgType.LOGOUT].Count > 0; + } - public void Logon40() - { - SendLogon(new QuickFix.FIX40.Logon()); - } + public bool SENT_NOS() + { + return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.NEWORDERSINGLE) && + _responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count > 0; + } - private void SendLogon(QuickFix.Message msg) - { - msg.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - msg.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - msg.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); - msg.Header.SetField(new QuickFix.Fields.SendingTime(System.DateTime.UtcNow)); - msg.SetField(new QuickFix.Fields.HeartBtInt(1)); - _session.Next(msg.ConstructString()); - } + public bool DISCONNECTED() + { + return _responder.Disconnected; + } - public bool SENT_SEQUENCE_RESET() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.SEQUENCE_RESET) && - _responder.MsgLookup[QuickFix.Fields.MsgType.SEQUENCE_RESET].Count > 0; - } + public bool SENT_REJECT(int reason, int refTag) + { + if (!SENT_REJECT()) + return false; - public bool SENT_RESEND_REQUEST() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.RESEND_REQUEST) && - _responder.MsgLookup[QuickFix.Fields.MsgType.RESEND_REQUEST].Count > 0; - } + QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].First(); - public bool RESENT() - { - if (_responder.Dups.Count == 0) - return false; + if (!msg.IsSetField(QuickFix.Fields.Tags.SessionRejectReason)) + return false; - _responder.Dups.Dequeue(); - return true; - } + QuickFix.Fields.SessionRejectReason reasonField = new QuickFix.Fields.SessionRejectReason(); + msg.GetField(reasonField); + if(reasonField.Value != reason) + return false; - public bool SENT_REJECT() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT) && - _responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Count>0; - } + if (!msg.IsSetField(QuickFix.Fields.Tags.RefTagID)) + return false; - public bool SENT_HEART_BEAT() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.HEARTBEAT) && - _responder.MsgLookup[QuickFix.Fields.MsgType.HEARTBEAT].Count > 0; - } + QuickFix.Fields.RefTagID refTagField = new QuickFix.Fields.RefTagID(); + msg.GetField(refTagField); + return refTagField.Value == refTag; + } - public bool SENT_BUSINESS_REJECT() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT) && - _responder.MsgLookup[QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT].Count > 0; - } + public void SendNOSMessage() + { + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); + + _session!.Next(order.ConstructString()); + } - public bool SENT_BUSINESS_REJECT(int reason) - { - if (!SENT_BUSINESS_REJECT()) - return false; + public void SendResendRequest(SeqNumType begin, SeqNumType end) + { + SendTheMessage(new QuickFix.FIX42.ResendRequest( + new QuickFix.Fields.BeginSeqNo(begin), + new QuickFix.Fields.EndSeqNo(end))); + } - QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.BUSINESS_MESSAGE_REJECT].First(); + public void SendResendRequest40(SeqNumType begin, SeqNumType end) + { + SendTheMessage(new QuickFix.FIX40.ResendRequest( + new QuickFix.Fields.BeginSeqNo(begin), + new QuickFix.Fields.EndSeqNo(end))); + } - if (!msg.IsSetField(QuickFix.Fields.Tags.BusinessRejectReason)) - return false; + private void SendTheMessage(QuickFix.Message msg) + { + msg.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + msg.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + msg.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); - QuickFix.Fields.BusinessRejectReason reasonField = new QuickFix.Fields.BusinessRejectReason(); - msg.GetField(reasonField); - return reasonField.Value == reason; - } + _session!.Next(msg.ConstructString()); + } - public bool SENT_LOGOUT() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.LOGOUT) && - _responder.MsgLookup[QuickFix.Fields.MsgType.LOGOUT].Count > 0; - } + [Test] + public void ConditionalTagMissingReject() + { + _application.FromAppException = new QuickFix.FieldNotFoundException(61); - public bool SENT_NOS() - { - return _responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.NEWORDERSINGLE) && - _responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count > 0; - } + Logon(); + SendNOSMessage(); - public bool DISCONNECTED() - { - return _responder.Disconnected; - } + Assert.That(SENT_BUSINESS_REJECT(QuickFix.Fields.BusinessRejectReason.CONDITIONALLY_REQUIRED_FIELD_MISSING)); + } - public bool SENT_REJECT(int reason, int refTag) - { - if (!SENT_REJECT()) - return false; + [Test] + public void IncorrectTagValueReject() + { + _application.FromAppException = new QuickFix.IncorrectTagValue(54); - QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].First(); + Logon(); + SendNOSMessage(); + Assert.That(SENT_REJECT(QuickFix.Fields.SessionRejectReason.VALUE_IS_INCORRECT,54)); - if (!msg.IsSetField(QuickFix.Fields.Tags.SessionRejectReason)) - return false; + } - QuickFix.Fields.SessionRejectReason reasonField = new QuickFix.Fields.SessionRejectReason(); - msg.GetField(reasonField); - if(reasonField.Value != reason) - return false; + [Test] + public void UnsupportedMessageReject() + { + _application.FromAppException = new QuickFix.UnsupportedMessageType(); - if (!msg.IsSetField(QuickFix.Fields.Tags.RefTagID)) - return false; + Logon(); + SendNOSMessage(); + Assert.That(SENT_BUSINESS_REJECT()); + } - QuickFix.Fields.RefTagID refTagField = new QuickFix.Fields.RefTagID(); - msg.GetField(refTagField); - return refTagField.Value == refTag; - } + [Test] + public void LogonReject() + { + _application.FromAdminException = new QuickFix.RejectLogon("Failed Logon"); + Logon(); - public void SendNOSMessage() - { - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); - - _session.Next(order.ConstructString()); - } + Assert.That(SENT_LOGOUT()); + Assert.That(DISCONNECTED()); + } - public void SendResendRequest(SeqNumType begin, SeqNumType end) - { - SendTheMessage(new QuickFix.FIX42.ResendRequest( - new QuickFix.Fields.BeginSeqNo(begin), - new QuickFix.Fields.EndSeqNo(end))); - } + [Test] + public void HeartBeatCheckAfterMessageProcess() + { + Logon(); + Thread.Sleep(2000); - public void SendResendRequest40(SeqNumType begin, SeqNumType end) - { - SendTheMessage(new QuickFix.FIX40.ResendRequest( - new QuickFix.Fields.BeginSeqNo(begin), - new QuickFix.Fields.EndSeqNo(end))); - } + SendNOSMessage(); + Assert.That(SENT_HEART_BEAT()); + } - private void SendTheMessage(QuickFix.Message msg) - { - msg.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - msg.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - msg.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); + [Test] + public void NextResendRequestNoMessagePersist() + { + _session!.PersistMessages = false; - _session.Next(msg.ConstructString()); - } + Logon(); //seq 1 - [Test] - public void ConditionalTagMissingReject() + for (int i = 0; i < 3; ++i) { - _application.FromAppException = new QuickFix.FieldNotFoundException(61); - - Logon(); SendNOSMessage(); + } //seq 4, next is 5 - Assert.That(SENT_BUSINESS_REJECT(QuickFix.Fields.BusinessRejectReason.CONDITIONALLY_REQUIRED_FIELD_MISSING)); - } - - + SendResendRequest(1, 4); + Assert.That(SENT_SEQUENCE_RESET()); + Assert.IsFalse(RESENT()); + } - [Test] - public void IncorrectTagValueReject() - { - _application.FromAppException = new QuickFix.IncorrectTagValue(54); + [Test] + public void TestGapFillOnResend() + { + // Engineer a gap fill at the beginning of a re-send range, in the middle, and at the end + Logon(); //seq 1 + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - Logon(); - SendNOSMessage(); - Assert.That(SENT_REJECT(QuickFix.Fields.SessionRejectReason.VALUE_IS_INCORRECT,54)); + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.SenderCompID)); - } + SeqNumType[] gapStarts = new[] { 1UL, 5UL, 11UL }; // 1st gap from seq num 1 to 2 is just the Logon message + SeqNumType[] gapEnds = new[] { 2UL, 8UL, 15UL }; + int orderCount = 0; - [Test] - public void UnsupportedMessageReject() + for (SeqNumType msgSeqNum = gapEnds[0]; msgSeqNum < gapStarts[1]; ++msgSeqNum) { - _application.FromAppException = new QuickFix.UnsupportedMessageType(); - - Logon(); - SendNOSMessage(); - Assert.That(SENT_BUSINESS_REJECT()); - } + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(msgSeqNum)); + _session!.Send(order); + ++orderCount; + } //seq 4, next is 5 - [Test] - public void LogonReject() + for (SeqNumType msgSeqNum = gapStarts[1]; msgSeqNum < gapEnds[1]; ++msgSeqNum) { - _application.FromAdminException = new QuickFix.RejectLogon("Failed Logon"); - Logon(); + _session!.GenerateHeartbeat(); + } //seq 7, next is 8 - Assert.That(SENT_LOGOUT()); - Assert.That(DISCONNECTED()); - } - - [Test] - public void HeartBeatCheckAfterMessageProcess() + for (SeqNumType msgSeqNum = gapEnds[1]; msgSeqNum < gapStarts[2]; ++msgSeqNum) { - Logon(); - Thread.Sleep(2000); - - SendNOSMessage(); - Assert.That(SENT_HEART_BEAT()); - } + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(msgSeqNum)); + _session!.Send(order); + ++orderCount; + } //seq 10, next is 11 - [Test] - public void NextResendRequestNoMessagePersist() + for (SeqNumType msgSeqNum = gapStarts[2]; msgSeqNum < gapEnds[2]; ++msgSeqNum) { - _session.PersistMessages = false; - - Logon(); //seq 1 + _session!.GenerateHeartbeat(); + } // seq 11 - 14 - for (int i = 0; i < 3; ++i) - { - SendNOSMessage(); - } //seq 4, next is 5 + _responder.MsgLookup.Clear(); + SendResendRequest(1, 100); - SendResendRequest(1, 4); - Assert.That(SENT_SEQUENCE_RESET()); - Assert.IsFalse(RESENT()); - } + Assert.AreEqual(_responder.GetCount(QuickFix.Fields.MsgType.NEWORDERSINGLE), orderCount); + Assert.AreEqual(_responder.GetCount(QuickFix.Fields.MsgType.SEQUENCE_RESET), gapStarts.Length); - [Test] - public void TestGapFillOnResend() + int count = -1; + foreach (QuickFix.Message sequenceResestMsg in _responder.MsgLookup[QuickFix.Fields.MsgType.SEQUENCE_RESET]) { - // Engineer a gap fill at the beginning of a re-send range, in the middle, and at the end - Logon(); //seq 1 - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.SenderCompID)); - - SeqNumType[] gapStarts = new[] { 1UL, 5UL, 11UL }; // 1st gap from seq num 1 to 2 is just the Logon message - SeqNumType[] gapEnds = new[] { 2UL, 8UL, 15UL }; - int orderCount = 0; - - for (SeqNumType msgSeqNum = gapEnds[0]; msgSeqNum < gapStarts[1]; ++msgSeqNum) - { - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(msgSeqNum)); - _session.Send(order); - ++orderCount; - } //seq 4, next is 5 - - for (SeqNumType msgSeqNum = gapStarts[1]; msgSeqNum < gapEnds[1]; ++msgSeqNum) - { - _session.GenerateHeartbeat(); - } //seq 7, next is 8 - - for (SeqNumType msgSeqNum = gapEnds[1]; msgSeqNum < gapStarts[2]; ++msgSeqNum) - { - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(msgSeqNum)); - _session.Send(order); - ++orderCount; - } //seq 10, next is 11 - - for (SeqNumType msgSeqNum = gapStarts[2]; msgSeqNum < gapEnds[2]; ++msgSeqNum) - { - _session.GenerateHeartbeat(); - } // seq 11 - 14 - - _responder.MsgLookup.Clear(); - SendResendRequest(1, 100); - - Assert.AreEqual(_responder.GetCount(QuickFix.Fields.MsgType.NEWORDERSINGLE), orderCount); - Assert.AreEqual(_responder.GetCount(QuickFix.Fields.MsgType.SEQUENCE_RESET), gapStarts.Length); - - int count = -1; - foreach (QuickFix.Message sequenceResestMsg in _responder.MsgLookup[QuickFix.Fields.MsgType.SEQUENCE_RESET]) - { - Assert.AreEqual(sequenceResestMsg.GetString(QuickFix.Fields.Tags.GapFillFlag), "Y"); - Assert.AreEqual(sequenceResestMsg.Header.GetULong(QuickFix.Fields.Tags.MsgSeqNum), gapStarts[++count]); - Assert.AreEqual(sequenceResestMsg.GetInt(QuickFix.Fields.Tags.NewSeqNo), gapEnds[count]); - } + Assert.AreEqual(sequenceResestMsg.GetString(QuickFix.Fields.Tags.GapFillFlag), "Y"); + Assert.AreEqual(sequenceResestMsg.Header.GetULong(QuickFix.Fields.Tags.MsgSeqNum), gapStarts[++count]); + Assert.AreEqual(sequenceResestMsg.GetInt(QuickFix.Fields.Tags.NewSeqNo), gapEnds[count]); } + } - [Test] - public void TestResendSessionLevelReject() - { - Assert.False(_session.ResendSessionLevelRejects); // check for correct default - Logon(); + [Test] + public void TestResendSessionLevelReject() + { + Assert.False(_session!.ResendSessionLevelRejects); // check for correct default + Logon(); - QuickFix.FIX42.Reject reject = new QuickFix.FIX42.Reject( - new QuickFix.Fields.RefSeqNum(10)); + QuickFix.FIX42.Reject reject = new QuickFix.FIX42.Reject( + new QuickFix.Fields.RefSeqNum(10)); - reject.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.TargetCompID)); - reject.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.SenderCompID)); - _session.Send(reject); + reject.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.TargetCompID)); + reject.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.SenderCompID)); + _session.Send(reject); - _responder.MsgLookup.Clear(); - _session.ResendSessionLevelRejects = true; - SendResendRequest(1, 100); - Assert.That(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); + _responder.MsgLookup.Clear(); + _session.ResendSessionLevelRejects = true; + SendResendRequest(1, 100); + Assert.That(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); - _responder.MsgLookup.Clear(); - _session.ResendSessionLevelRejects = false; - SendResendRequest(1, 100); - Assert.False(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); - } + _responder.MsgLookup.Clear(); + _session.ResendSessionLevelRejects = false; + SendResendRequest(1, 100); + Assert.False(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); + } - public void AssertMsInTag(string msgType, int tag, bool shouldHaveMs) - { - QuickFix.Message msg = _responder.MsgLookup[msgType].Last(); - string sendingTime = msg.Header.GetString(tag); - Match m = _msRegex.Match(sendingTime); - Assert.That(m.Success == shouldHaveMs); - } + public void AssertMsInTag(string msgType, int tag, bool shouldHaveMs) + { + QuickFix.Message msg = _responder.MsgLookup[msgType].Last(); + string sendingTime = msg.Header.GetString(tag); + Match m = _msRegex.Match(sendingTime); + Assert.That(m.Success == shouldHaveMs); + } - public void AssertMicrosecondsInTag(string msgType, int tag, bool shouldHaveMicrosecond) - { - QuickFix.Message msg = _responder.MsgLookup[msgType].Last(); - string sendingTime = msg.Header.GetString(tag); - Match m = _microsecondRegex.Match(sendingTime); - Assert.That(m.Success == shouldHaveMicrosecond); - } + public void AssertMicrosecondsInTag(string msgType, int tag, bool shouldHaveMicrosecond) + { + QuickFix.Message msg = _responder.MsgLookup[msgType].Last(); + string sendingTime = msg.Header.GetString(tag); + Match m = _microsecondRegex.Match(sendingTime); + Assert.That(m.Success == shouldHaveMicrosecond); + } - [Test] - public void TestMillisecondsInSendingTimeStamp() - { - // MS in timestamp should default to Y - Assert.That(_session.TimeStampPrecision == QuickFix.Fields.Converters.TimeStampPrecision.Millisecond ); - - // Ms should show up - Logon(); - AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); - - // No ms - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; - Logon(); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 2); - AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); - - // Less than FIX42 - no ms in timestamp, even if you tell it to - _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); - _session.SessionID = _sessionId; - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; - Logon40(); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 3); - AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); - } + [Test] + public void TestMillisecondsInSendingTimeStamp() + { + // MS in timestamp should default to Y + Assert.That(_session!.TimeStampPrecision == QuickFix.Fields.Converters.TimeStampPrecision.Millisecond ); + + // Ms should show up + Logon(); + AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); + + // No ms + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; + Logon(); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 2); + AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); + + // Less than FIX42 - no ms in timestamp, even if you tell it to + _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); + _session.SessionID = _sessionId; + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; + Logon40(); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 3); + AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); + } - [Test] - public void TestMicrosecondsInSendingTimeStamp() - { - // Microseconds in timestamp - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; - - // Microseconds should show up - Logon(); - AssertMicrosecondsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); - - // Milliseconds in timestamp - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; - Logon(); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 2); - AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); - - // Less than FIX42 - no microseconds in timestamp, even if you tell it to - _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); - _session.SessionID = _sessionId; - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; - Logon40(); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 3); - AssertMicrosecondsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); - } + [Test] + public void TestMicrosecondsInSendingTimeStamp() + { + // Microseconds in timestamp + _session!.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; + + // Microseconds should show up + Logon(); + AssertMicrosecondsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); + + // Milliseconds in timestamp + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; + Logon(); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 2); + AssertMsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, true); + + // Less than FIX42 - no microseconds in timestamp, even if you tell it to + _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); + _session.SessionID = _sessionId; + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; + Logon40(); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Count == 3); + AssertMicrosecondsInTag(QuickFix.Fields.MsgType.LOGON, QuickFix.Fields.Tags.SendingTime, false); + } - [Test] - public void TestMillisecondsInOrigSendingTimeStamp() - { - // MS in timestamp should default - Assert.That( _session.TimeStampPrecision == QuickFix.Fields.Converters.TimeStampPrecision.Millisecond ); - - // Logon first - Logon(); - - // Do a resend request - SendResendRequest(0, 2); - AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, true); - - // NO MS - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; - SendResendRequest(0, 2); - AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); - - // Less than FIX42 - no ms in timestamp, even if you tell it to - _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); - _session.SessionID = _sessionId; - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; - SendResendRequest40(0, 2); - AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); - } + [Test] + public void TestMillisecondsInOrigSendingTimeStamp() + { + // MS in timestamp should default + Assert.That(_session!.TimeStampPrecision == QuickFix.Fields.Converters.TimeStampPrecision.Millisecond); + + // Logon first + Logon(); + + // Do a resend request + SendResendRequest(0, 2); + AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, true); + + // NO MS + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; + SendResendRequest(0, 2); + AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); + + // Less than FIX42 - no ms in timestamp, even if you tell it to + _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); + _session.SessionID = _sessionId; + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Millisecond; + SendResendRequest40(0, 2); + AssertMsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); + } - [Test] - public void TestMicrosecondsInOrigSendingTimeStamp() - { - // Microsecond in timestamp - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; - - // Logon first - Logon(); - - // Do a resend request - SendResendRequest(0, 2); - AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, true); - - // NO MS - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; - SendResendRequest(0, 2); - AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); - - // Less than FIX42 - no ms in timestamp, even if you tell it to - _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); - _session.SessionID = _sessionId; - _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; - SendResendRequest40(0, 2); - AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); - } + [Test] + public void TestMicrosecondsInOrigSendingTimeStamp() + { + // Microsecond in timestamp + _session!.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; + + // Logon first + Logon(); + + // Do a resend request + SendResendRequest(0, 2); + AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, true); + + // NO MS + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Second; + SendResendRequest(0, 2); + AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); + + // Less than FIX42 - no ms in timestamp, even if you tell it to + _sessionId = new QuickFix.SessionID(QuickFix.FixValues.BeginString.FIX40, "SENDER", "TARGET"); + _session.SessionID = _sessionId; + _session.TimeStampPrecision = QuickFix.Fields.Converters.TimeStampPrecision.Microsecond; + SendResendRequest40(0, 2); + AssertMicrosecondsInTag(QuickFix.Fields.MsgType.SEQUENCERESET, QuickFix.Fields.Tags.OrigSendingTime, false); + } - [Test] - public void TestLastMsgSeqNumProcessed() - { - // Disabled by default - Assert.That(!_session.EnableLastMsgSeqNumProcessed); - - _session.EnableLastMsgSeqNumProcessed = true; - - // Logon - Logon(); - QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Last(); - SeqNumType lastSeqNumProcessed = msg.Header.GetULong(QuickFix.Fields.Tags.LastMsgSeqNumProcessed); - Assert.That(lastSeqNumProcessed == 1); - - // NOS - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); - _session.Send(order); - - msg = _responder.MsgLookup[QuickFix.Fields.MsgType.NEW_ORDER_D].Last(); - lastSeqNumProcessed = msg.Header.GetULong(QuickFix.Fields.Tags.LastMsgSeqNumProcessed); - Assert.That(lastSeqNumProcessed == 1); - } + [Test] + public void TestLastMsgSeqNumProcessed() + { + // Disabled by default + Assert.That(_session!.EnableLastMsgSeqNumProcessed, Is.False); + + _session.EnableLastMsgSeqNumProcessed = true; + + // Logon + Logon(); + QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.LOGON].Last(); + SeqNumType lastSeqNumProcessed = msg.Header.GetULong(QuickFix.Fields.Tags.LastMsgSeqNumProcessed); + Assert.That(lastSeqNumProcessed == 1); + + // NOS + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); + _session.Send(order); + + msg = _responder.MsgLookup[QuickFix.Fields.MsgType.NEW_ORDER_D].Last(); + lastSeqNumProcessed = msg.Header.GetULong(QuickFix.Fields.Tags.LastMsgSeqNumProcessed); + Assert.That(lastSeqNumProcessed == 1); + } - [Test] - public void TestMaxMessagesInResendRequest() - { - // Default - Assert.That(_session.MaxMessagesInResendRequest, Is.EqualTo(0)); - - _session.MaxMessagesInResendRequest = 2500; - // Logon - Logon(); - - // NOS - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(5005)); - // This will generate resend requests - _session.Verify(order, true, false); - - // 3 resend requests - // 2->2501 - // 2502->5001 - // 5002->5005 - - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); - QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(2)); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(2501)); - - // Jump forward to the end of the resend chunk with a fillgap reset message - QuickFix.FIX42.SequenceReset reset = new QuickFix.FIX42.SequenceReset(); - reset.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - reset.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - reset.SetField(new QuickFix.Fields.GapFillFlag(true)); - - reset.Header.SetField(new QuickFix.Fields.MsgSeqNum(2)); - reset.SetField(new QuickFix.Fields.NewSeqNo(2501)); - _session.Next(reset.ConstructString()); - - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(2501)); - _session.Next(order.ConstructString()); - - // Should have triggered next resend (2502->5001), check this - //Console.WriteLine(responder.msgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); - msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(2502)); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(5001)); - - // Jump forward to the end of the resend chunk with a fillgap reset message - reset.Header.SetField(new QuickFix.Fields.MsgSeqNum(2502)); - reset.SetField(new QuickFix.Fields.NewSeqNo(5001)); - _session.Next(reset.ConstructString()); - - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(5001)); - _session.Next(order.ConstructString()); // Triggers next resend (5002->5005) - - //Console.WriteLine(responder.msgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); - msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(5002)); - Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(5004)); - } + [Test] + public void TestMaxMessagesInResendRequest() + { + // Default + Assert.That(_session!.MaxMessagesInResendRequest, Is.EqualTo(0)); + + _session.MaxMessagesInResendRequest = 2500; + // Logon + Logon(); + + // NOS + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(5005)); + // This will generate resend requests + _session.Verify(order, true, false); + + // 3 resend requests + // 2->2501 + // 2502->5001 + // 5002->5005 + + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); + QuickFix.Message msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(2)); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(2501)); + + // Jump forward to the end of the resend chunk with a fillgap reset message + QuickFix.FIX42.SequenceReset reset = new QuickFix.FIX42.SequenceReset(); + reset.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + reset.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + reset.SetField(new QuickFix.Fields.GapFillFlag(true)); + + reset.Header.SetField(new QuickFix.Fields.MsgSeqNum(2)); + reset.SetField(new QuickFix.Fields.NewSeqNo(2501)); + _session.Next(reset.ConstructString()); + + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(2501)); + _session.Next(order.ConstructString()); + + // Should have triggered next resend (2502->5001), check this + //Console.WriteLine(responder.msgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); + msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(2502)); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(5001)); + + // Jump forward to the end of the resend chunk with a fillgap reset message + reset.Header.SetField(new QuickFix.Fields.MsgSeqNum(2502)); + reset.SetField(new QuickFix.Fields.NewSeqNo(5001)); + _session.Next(reset.ConstructString()); + + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(5001)); + _session.Next(order.ConstructString()); // Triggers next resend (5002->5005) + + //Console.WriteLine(responder.msgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count); + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Count == 1); + msg = _responder.MsgLookup[QuickFix.Fields.MsgType.RESENDREQUEST].Dequeue(); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.BeginSeqNo), Is.EqualTo(5002)); + Assert.That(msg.GetInt(QuickFix.Fields.Tags.EndSeqNo), Is.EqualTo(5004)); + } - [Test] - public void TestIgnorePossDupInResendRequest() - { - // Default is false - Assert.That(_session.IgnorePossDupResendRequests, Is.EqualTo(false)); - - _session.IgnorePossDupResendRequests = true; - // Logon - Logon(); - - // NOS - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); - // This will generate resend requests - _session.Send(order); - - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count == 1); - - QuickFix.Message msg = new QuickFix.FIX42.ResendRequest( - new QuickFix.Fields.BeginSeqNo(1), - new QuickFix.Fields.EndSeqNo(0)); - msg.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); - SendTheMessage(msg); - - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count == 1); - } + [Test] + public void TestIgnorePossDupInResendRequest() + { + // Default is false + Assert.That(_session!.IgnorePossDupResendRequests, Is.EqualTo(false)); + + _session.IgnorePossDupResendRequests = true; + // Logon + Logon(); + + // NOS + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum++)); + // This will generate resend requests + _session.Send(order); + + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count == 1); + + QuickFix.Message msg = new QuickFix.FIX42.ResendRequest( + new QuickFix.Fields.BeginSeqNo(1), + new QuickFix.Fields.EndSeqNo(0)); + msg.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); + SendTheMessage(msg); + + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.NEWORDERSINGLE].Count == 1); + } - [Test] - public void TestDoesSessionExist() - { - QuickFix.SessionID invalidSessionID = new QuickFix.SessionID("FIX.4.2", "NOT_SENDER", "NOT_TARGET"); - QuickFix.SessionID validSessionID = new QuickFix.SessionID("FIX.4.2", "SENDER", "TARGET"); + [Test] + public void TestDoesSessionExist() + { + QuickFix.SessionID invalidSessionId = new QuickFix.SessionID("FIX.4.2", "NOT_SENDER", "NOT_TARGET"); + QuickFix.SessionID validSessionId = new QuickFix.SessionID("FIX.4.2", "SENDER", "TARGET"); - Assert.That(QuickFix.Session.DoesSessionExist(invalidSessionID), Is.EqualTo(false)); - Assert.That(QuickFix.Session.DoesSessionExist(validSessionID), Is.EqualTo(true)); - } + Assert.That(QuickFix.Session.DoesSessionExist(invalidSessionId), Is.EqualTo(false)); + Assert.That(QuickFix.Session.DoesSessionExist(validSessionId), Is.EqualTo(true)); + } - [Test] - public void TestSettingNextTargetMsgSeqNum() - { - _session.NextTargetMsgSeqNum = 100; - Assert.That(_session.NextTargetMsgSeqNum, Is.EqualTo(100)); - } + [Test] + public void TestSettingNextTargetMsgSeqNum() + { + _session!.NextTargetMsgSeqNum = 100; + Assert.That(_session.NextTargetMsgSeqNum, Is.EqualTo(100)); + } - [Test] - public void TestSettingNextSenderMsgSeqNum() - { - _session.NextSenderMsgSeqNum = 200; - Assert.That(_session.NextSenderMsgSeqNum, Is.EqualTo(200)); - } + [Test] + public void TestSettingNextSenderMsgSeqNum() + { + _session!.NextSenderMsgSeqNum = 200; + Assert.That(_session.NextSenderMsgSeqNum, Is.EqualTo(200)); + } - [Test] - public void TestGettingIsInitiator() - { - Assert.That(_session2.IsInitiator, Is.EqualTo(true)); - } + [Test] + public void TestGettingIsInitiator() + { + Assert.That(_session2!.IsInitiator, Is.EqualTo(true)); + } - [Test] - public void TestGettingIsAcceptor() - { - Assert.That(_session2.IsAcceptor, Is.EqualTo(false)); - } + [Test] + public void TestGettingIsAcceptor() + { + Assert.That(_session2!.IsAcceptor, Is.EqualTo(false)); + } - [Test] - public void TestMessageStoreAccessor() - { - List messages = new List(); + [Test] + public void TestMessageStoreAccessor() + { + List messages = new List(); - messages.Clear(); - _session.MessageStore.Get(0, 100, messages); - Assert.That(messages.Count, Is.EqualTo(0)); + messages.Clear(); + _session!.MessageStore.Get(0, 100, messages); + Assert.That(messages.Count, Is.EqualTo(0)); - Logon(); + Logon(); - messages.Clear(); - _session.MessageStore.Get(0, 100, messages); - Assert.That(messages.Count, Is.EqualTo(1)); // logon response - } + messages.Clear(); + _session.MessageStore.Get(0, 100, messages); + Assert.That(messages.Count, Is.EqualTo(1)); // logon response + } - [Test] - public void TestRequiresOrigSendingTime_Y() - { - // Under default configuration, session should reject a ResendRequest that lacks OrigSendingTime unset + [Test] + public void TestRequiresOrigSendingTime_Y() + { + // Under default configuration, session should reject a ResendRequest that lacks OrigSendingTime unset - // Check default is as expected - Assert.That(_session.RequiresOrigSendingTime, Is.EqualTo(true)); + // Check default is as expected + Assert.That(_session!.RequiresOrigSendingTime, Is.EqualTo(true)); - Logon(); + Logon(); - QuickFix.FIX42.SequenceReset sr = new QuickFix.FIX42.SequenceReset(new QuickFix.Fields.NewSeqNo(5)); - sr.GapFillFlag = new QuickFix.Fields.GapFillFlag(true); - sr.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); + QuickFix.FIX42.SequenceReset sr = new(new QuickFix.Fields.NewSeqNo(5)); + sr.GapFillFlag = new QuickFix.Fields.GapFillFlag(true); + sr.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); - sr.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum--)); // so it triggers DoTargetTooLow code + sr.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum--)); // so it triggers DoTargetTooLow code - SendTheMessage(sr); + SendTheMessage(sr); - Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Count == 1); - QuickFix.FIX42.Reject rej = _responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Peek() as QuickFix.FIX42.Reject; - Assert.That(rej.SessionRejectReason.Value, Is.EqualTo(QuickFix.Fields.SessionRejectReason.REQUIRED_TAG_MISSING)); - } + Assert.That(_responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Count == 1); + QuickFix.FIX42.Reject rej = + (_responder.MsgLookup[QuickFix.Fields.MsgType.REJECT].Peek() as QuickFix.FIX42.Reject)!; + Assert.That(rej.SessionRejectReason.Value, Is.EqualTo(QuickFix.Fields.SessionRejectReason.REQUIRED_TAG_MISSING)); + } - [Test] - public void TestRequiresOrigSendingTime_N() - { - // Under OrigSendingTime=N, session will allow ResendRequest that lacks OrigSendingTime - _session.RequiresOrigSendingTime = false; + [Test] + public void TestRequiresOrigSendingTime_N() + { + // Under OrigSendingTime=N, session will allow ResendRequest that lacks OrigSendingTime + _session!.RequiresOrigSendingTime = false; - Logon(); + Logon(); - QuickFix.FIX42.SequenceReset sr = new QuickFix.FIX42.SequenceReset(new QuickFix.Fields.NewSeqNo(5)); - sr.GapFillFlag = new QuickFix.Fields.GapFillFlag(true); - sr.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); + QuickFix.FIX42.SequenceReset sr = new(new QuickFix.Fields.NewSeqNo(5)); + sr.GapFillFlag = new QuickFix.Fields.GapFillFlag(true); + sr.Header.SetField(new QuickFix.Fields.PossDupFlag(true)); - sr.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum--)); // so it triggers DoTargetTooLow code + sr.Header.SetField(new QuickFix.Fields.MsgSeqNum(_seqNum--)); // so it triggers DoTargetTooLow code - SendTheMessage(sr); + SendTheMessage(sr); - Assert.False(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); - } - [Test] - public void TestToAppDoNotSend() - { - Logon(); - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - _application.DoNotSendException = new QuickFix.DoNotSend(); - _session.Send(order); - Assert.False(SENT_NOS()); - } + Assert.False(_responder.MsgLookup.ContainsKey(QuickFix.Fields.MsgType.REJECT)); + } + [Test] + public void TestToAppDoNotSend() + { + Logon(); + QuickFix.FIX42.NewOrderSingle order = new( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + _application.DoNotSendException = new QuickFix.DoNotSend(); + _session!.Send(order); + Assert.False(SENT_NOS()); + } - [Test] - public void TestToAppResendDoNotSend() - { - Logon(); - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - _session.Send(order); - Assert.True(SENT_NOS()); - - _responder.MsgLookup.Remove(QuickFix.Fields.MsgType.NEWORDERSINGLE); - _application.DoNotSendException = new QuickFix.DoNotSend(); - - SendResendRequest(1, 0); - Assert.False(SENT_NOS()); - } + [Test] + public void TestToAppResendDoNotSend() + { + Logon(); + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + _session!.Send(order); + Assert.True(SENT_NOS()); + + _responder.MsgLookup.Remove(QuickFix.Fields.MsgType.NEWORDERSINGLE); + _application.DoNotSendException = new QuickFix.DoNotSend(); + + SendResendRequest(1, 0); + Assert.False(SENT_NOS()); + } - [Test] - public void TestApplicationExtension() - { - var mockApp = new MockApplicationExt(); - _session = new QuickFix.Session(true, mockApp, new MemoryStoreFactory(), _sessionId, - new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config), 0, new NullLogFactory(), new QuickFix.DefaultMessageFactory(), "blah"); - _session.SetResponder(_responder); - _session.CheckLatency = false; - - Logon(); - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - - order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); - order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); - order.Header.SetField(new QuickFix.Fields.MsgSeqNum(2)); - - _session.Next(order.ConstructString()); - - Assert.That(mockApp.InterceptedMessageTypes.Count, Is.EqualTo(2)); - Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.LOGON)); - Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.NEWORDERSINGLE)); - } + [Test] + public void TestApplicationExtension() + { + var mockApp = new SessionTestSupport.MockApplicationExt(); + _session = new QuickFix.Session(true, mockApp, new MemoryStoreFactory(), _sessionId, + new QuickFix.DataDictionaryProvider(), new QuickFix.SessionSchedule(_config), 0, new NullLogFactory(), new QuickFix.DefaultMessageFactory(), "blah"); + _session.SetResponder(_responder); + _session.CheckLatency = false; + + Logon(); + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + + order.Header.SetField(new QuickFix.Fields.TargetCompID(_sessionId.SenderCompID)); + order.Header.SetField(new QuickFix.Fields.SenderCompID(_sessionId.TargetCompID)); + order.Header.SetField(new QuickFix.Fields.MsgSeqNum(2)); + + _session.Next(order.ConstructString()); + + Assert.That(mockApp.InterceptedMessageTypes.Count, Is.EqualTo(2)); + Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.LOGON)); + Assert.True(mockApp.InterceptedMessageTypes.Contains(QuickFix.Fields.MsgType.NEWORDERSINGLE)); + } - [Test] - public void TestRequireLogon() - { - QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( - new QuickFix.Fields.ClOrdID("1"), - new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), - new QuickFix.Fields.Symbol("IBM"), - new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), - new QuickFix.Fields.TransactTime(), - new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); - // This should cause disconnect, because first message is something other than a logon. - SendTheMessage(order); - Assert.That(DISCONNECTED()); - } + [Test] + public void TestRequireLogon() + { + QuickFix.FIX42.NewOrderSingle order = new QuickFix.FIX42.NewOrderSingle( + new QuickFix.Fields.ClOrdID("1"), + new QuickFix.Fields.HandlInst(QuickFix.Fields.HandlInst.MANUAL_ORDER), + new QuickFix.Fields.Symbol("IBM"), + new QuickFix.Fields.Side(QuickFix.Fields.Side.BUY), + new QuickFix.Fields.TransactTime(), + new QuickFix.Fields.OrdType(QuickFix.Fields.OrdType.LIMIT)); + // This should cause disconnect, because first message is something other than a logon. + SendTheMessage(order); + Assert.That(DISCONNECTED()); + } - [Test] - public void TestResendRequestMsgSeqNumNotIgnoredWhenNoPersistance() - { - _session.PersistMessages = false; + [Test] + public void TestResendRequestMsgSeqNumNotIgnoredWhenNoPersistance() + { + _session!.PersistMessages = false; - Logon(); + Logon(); - SendNOSMessage(); - SendNOSMessage(); + SendNOSMessage(); + SendNOSMessage(); - //The below will trigger a sequence reset - SendResendRequest(2, 0); + //The below will trigger a sequence reset + SendResendRequest(2, 0); - SendNOSMessage(); - Assert.That(!SENT_RESEND_REQUEST()); - } + SendNOSMessage(); + Assert.That(!SENT_RESEND_REQUEST()); } } + diff --git a/UnitTests/SessionTestSupport/MockApplication.cs b/UnitTests/SessionTestSupport/MockApplication.cs new file mode 100644 index 000000000..04deb1028 --- /dev/null +++ b/UnitTests/SessionTestSupport/MockApplication.cs @@ -0,0 +1,40 @@ +#nullable enable +using System; + +namespace UnitTests.SessionTestSupport; + +internal class MockApplication : QuickFix.IApplication +{ + public Exception? FromAppException { get; set; } + public Exception? FromAdminException { get; set; } + public QuickFix.DoNotSend? DoNotSendException { get; set; } + + public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } + + public void FromAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) + { + if (FromAdminException is not null) + throw FromAdminException; + } + + public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId) + { + if (DoNotSendException is not null) + throw DoNotSendException; + } + + public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionId) + { + if (FromAppException is not null) + throw FromAppException; + } + + public void OnCreate(QuickFix.SessionID sessionId) { } + + public void OnLogout(QuickFix.SessionID sessionId) + { + throw new NotImplementedException(); + } + + public void OnLogon(QuickFix.SessionID sessionId) { } +} diff --git a/UnitTests/SessionTestSupport/MockApplicationExt.cs b/UnitTests/SessionTestSupport/MockApplicationExt.cs new file mode 100644 index 000000000..cda8a9eaa --- /dev/null +++ b/UnitTests/SessionTestSupport/MockApplicationExt.cs @@ -0,0 +1,28 @@ +#nullable enable +using System.Collections.Generic; + +namespace UnitTests.SessionTestSupport; + +class MockApplicationExt : QuickFix.IApplicationExt +{ + public HashSet InterceptedMessageTypes = new(); + + public void ToAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } + + public void FromAdmin(QuickFix.Message message, QuickFix.SessionID sessionId) { } + + public void ToApp(QuickFix.Message message, QuickFix.SessionID sessionId) { } + + public void FromApp(QuickFix.Message message, QuickFix.SessionID sessionId) { } + + public void OnCreate(QuickFix.SessionID sessionId) { } + + public void OnLogout(QuickFix.SessionID sessionId) { } + + public void OnLogon(QuickFix.SessionID sessionId) { } + + public void FromEarlyIntercept(QuickFix.Message message, QuickFix.SessionID sessionId) + { + InterceptedMessageTypes.Add(message.Header.GetString(QuickFix.Fields.Tags.MsgType)); + } +} diff --git a/UnitTests/SessionTestSupport/MockResponder.cs b/UnitTests/SessionTestSupport/MockResponder.cs new file mode 100644 index 000000000..3bff8fcd2 --- /dev/null +++ b/UnitTests/SessionTestSupport/MockResponder.cs @@ -0,0 +1,66 @@ +#nullable enable +using System; +using System.Collections.Generic; + +namespace UnitTests.SessionTestSupport; + +internal class MockResponder : QuickFix.IResponder +{ + private readonly QuickFix.DefaultMessageFactory _messageFactory = new(); + private readonly QuickFix.IMessageFactory _defaultMsgFactory = new QuickFix.DefaultMessageFactory(); + + public Dictionary> MsgLookup = new(); + public Queue Dups = new(); + + public bool Disconnected = false; + + public bool Send(string msgStr) + { + QuickFix.Fields.MsgType msgType = QuickFix.Message.IdentifyType(msgStr); + string beginString = QuickFix.Message.ExtractBeginString(msgStr); + + QuickFix.Message message = _messageFactory.Create(beginString, msgType.Value); + QuickFix.DataDictionary.DataDictionary dd = new QuickFix.DataDictionary.DataDictionary(); + message.FromString(msgStr, false, dd, dd, _defaultMsgFactory); + + if (!MsgLookup.ContainsKey(msgType.Value)) + MsgLookup.Add(msgType.Value, new Queue()); + + MsgLookup[msgType.Value].Enqueue(message); + + QuickFix.Fields.PossDupFlag possDup = new QuickFix.Fields.PossDupFlag(false); + if (message.Header.IsSetField(possDup)) + message.Header.GetField(possDup); + + if (possDup.Value && msgType.Value != QuickFix.Fields.MsgType.SEQUENCE_RESET) + { + Dups.Enqueue(message); + } + + return true; + } + + public void Disconnect() + { + Disconnected = true; + } + + /// + /// For debug use if needed + /// + public void DumpMsgLookup() + { + Console.WriteLine("Responder dump:"); + foreach (string key in MsgLookup.Keys) { + Console.WriteLine($" {key}: count {MsgLookup[key].Count}"); + foreach (QuickFix.Message m in MsgLookup[key]) { + Console.WriteLine(" - " + m.ConstructString()); + } + } + } + + public int GetCount(string msgType) + { + return MsgLookup.TryGetValue(msgType, out var value) ? value.Count : 0; + } +} From 6bc3f0b6e6d9f1537455d599dee0a229511de006 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Wed, 25 Sep 2024 18:29:33 -0500 Subject: [PATCH 2/5] we don't need to AllowUnsafeCodeBlocks! for real, what was that even from --- UnitTests/UnitTests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index 4a8333010..5811fa7af 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -2,7 +2,6 @@ net8.0 - true AnyCPU;x64 false From 2311a458fcd4de877e2252c1788a08835b966bc6 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Thu, 26 Sep 2024 11:13:12 -0500 Subject: [PATCH 3/5] nullable-ize UnitTests project also deprecate a AcceptorSocketDescriptor ctor due to unused param --- QuickFIXn/AcceptorSocketDescriptor.cs | 12 +++++- QuickFIXn/Fields/Converters/AsciiConverter.cs | 8 ++-- QuickFIXn/ThreadedSocketAcceptor.cs | 2 +- QuickFIXn/ThreadedSocketReactor.cs | 1 - RELEASE_NOTES.md | 2 + UnitTests/DataDictionaryTests.cs | 14 +++--- .../Converters/DecimalConverterTests.cs | 22 +++++----- .../Fields/Converters/IntConverterTests.cs | 2 +- UnitTests/FileStoreTests.cs | 43 +++++++++---------- UnitTests/GroupTests.cs | 43 ++++++++----------- UnitTests/MessageCrackerTests.cs | 20 ++++----- UnitTests/MessageTests.cs | 4 +- UnitTests/MessageToXmlTests.cs | 2 +- UnitTests/SessionDynamicTest.cs | 6 +-- UnitTests/SessionScheduleTests.cs | 16 +++---- UnitTests/SessionSettingsTest.cs | 33 +++++++------- UnitTests/SessionStateTest.cs | 8 ++-- UnitTests/SettingsTest.cs | 10 ++--- UnitTests/ThreadedSocketReactorTests.cs | 14 +++--- UnitTests/UnitTests.csproj | 1 + 20 files changed, 127 insertions(+), 136 deletions(-) diff --git a/QuickFIXn/AcceptorSocketDescriptor.cs b/QuickFIXn/AcceptorSocketDescriptor.cs index 2349b44d9..527ea062b 100644 --- a/QuickFIXn/AcceptorSocketDescriptor.cs +++ b/QuickFIXn/AcceptorSocketDescriptor.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Net; using QuickFix.Logger; @@ -14,13 +15,20 @@ internal class AcceptorSocketDescriptor public AcceptorSocketDescriptor( IPEndPoint socketEndPoint, SocketSettings socketSettings, - SettingsDictionary sessionDict, NonSessionLog nonSessionLog) { Address = socketEndPoint; - SocketReactor = new ThreadedSocketReactor(Address, socketSettings, sessionDict, this, nonSessionLog); + SocketReactor = new ThreadedSocketReactor(Address, socketSettings, this, nonSessionLog); } + [Obsolete("Param 'sessionDict' is unused. Use the alt constructor without it.")] + public AcceptorSocketDescriptor( + IPEndPoint socketEndPoint, + SocketSettings socketSettings, + SettingsDictionary sessionDict, + NonSessionLog nonSessionLog) : this(socketEndPoint, socketSettings, nonSessionLog) + { } + internal void AcceptSession(Session session) { lock (_acceptedSessions) diff --git a/QuickFIXn/Fields/Converters/AsciiConverter.cs b/QuickFIXn/Fields/Converters/AsciiConverter.cs index a798ef93f..e77df7674 100644 --- a/QuickFIXn/Fields/Converters/AsciiConverter.cs +++ b/QuickFIXn/Fields/Converters/AsciiConverter.cs @@ -10,18 +10,18 @@ public static class AsciiValidator public const int ASCII_NINE = 57; public const int ASCII_MINUS = 45; - /// /// TODO can we use NumberFormatInfo or NumberStyles to avoid this bit of ASCII hackery? - /// Validates that a string looks like number (for use before conversion to an int, ulong, etc.). + /// + /// Validates that a string looks like a number (for use before conversion to an int, ulong, etc.). /// /// /// public static void Validate(string i) { - if ((null == i) || (i.Length < 1)) + if (i is null || i.Length < 1) throw new FieldConvertError("The argument string cannot be null or empty"); int asciiValOfFirstChar = System.Convert.ToInt32(i[0]); - if ((asciiValOfFirstChar < ASCII_ZERO) || (asciiValOfFirstChar > ASCII_NINE)) + if (asciiValOfFirstChar < ASCII_ZERO || asciiValOfFirstChar > ASCII_NINE) if (asciiValOfFirstChar != ASCII_MINUS) throw new FieldConvertError("Could not convert string to int (" + i + "): The first character must be a digit or a minus sign"); } diff --git a/QuickFIXn/ThreadedSocketAcceptor.cs b/QuickFIXn/ThreadedSocketAcceptor.cs index c57ce7950..840300aab 100755 --- a/QuickFIXn/ThreadedSocketAcceptor.cs +++ b/QuickFIXn/ThreadedSocketAcceptor.cs @@ -94,7 +94,7 @@ private AcceptorSocketDescriptor GetAcceptorSocketDescriptor(SettingsDictionary if (!_socketDescriptorForAddress.TryGetValue(socketEndPoint, out var descriptor)) { - descriptor = new AcceptorSocketDescriptor(socketEndPoint, socketSettings, dict, _nonSessionLog); + descriptor = new AcceptorSocketDescriptor(socketEndPoint, socketSettings, _nonSessionLog); _socketDescriptorForAddress[socketEndPoint] = descriptor; } diff --git a/QuickFIXn/ThreadedSocketReactor.cs b/QuickFIXn/ThreadedSocketReactor.cs index ac7e5b103..daaceec06 100755 --- a/QuickFIXn/ThreadedSocketReactor.cs +++ b/QuickFIXn/ThreadedSocketReactor.cs @@ -36,7 +36,6 @@ public State ReactorState internal ThreadedSocketReactor( IPEndPoint serverSocketEndPoint, SocketSettings socketSettings, - SettingsDictionary sessionDict, AcceptorSocketDescriptor? acceptorSocketDescriptor, NonSessionLog nonSessionLog) { diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 438749c53..10d55ea1d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -40,6 +40,8 @@ What's New * deprecate Field.Obj (renamed to Value) * deprecate Field.getValue/setValue (just use Value getter/setter) * #889 - nullable-ize Examples and fix deprecations (gbirchmeier) +* #892 - nullable-ize UnitTests project (gbirchmeier) + * also deprecate a AcceptorSocketDescriptor ctor due to unused param ### v1.12.0 diff --git a/UnitTests/DataDictionaryTests.cs b/UnitTests/DataDictionaryTests.cs index aac8303d1..87db364dd 100644 --- a/UnitTests/DataDictionaryTests.cs +++ b/UnitTests/DataDictionaryTests.cs @@ -379,7 +379,7 @@ private static XmlNode MakeNode(string xmlString) if (xmlString.StartsWith('<')) { doc.LoadXml(xmlString); - return doc.DocumentElement; + return doc.DocumentElement!; } return doc.CreateTextNode(xmlString); } @@ -392,18 +392,18 @@ public void VerifyChildNodeAndReturnNameAtt() { MakeNode(""), parentNode)); DictionaryParseException dpx = Assert.Throws( - delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("foo"), parentNode); }); - Assert.AreEqual("Malformed data dictionary: Found text-only node containing 'foo'", dpx!.Message); + delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("foo"), parentNode); })!; + Assert.AreEqual("Malformed data dictionary: Found text-only node containing 'foo'", dpx.Message); dpx = Assert.Throws( - delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("qty"), parentNode); }); - Assert.AreEqual("Malformed data dictionary: Found 'field' node without 'name' within parent 'parentnode/Daddy'", dpx!.Message); + delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("qty"), parentNode); })!; + Assert.AreEqual("Malformed data dictionary: Found 'field' node without 'name' within parent 'parentnode/Daddy'", dpx.Message); // alt error message, where parent has no name parentNode = MakeNode(""); dpx = Assert.Throws( - delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("qty"), parentNode); }); - Assert.AreEqual("Malformed data dictionary: Found 'field' node without 'name' within parent 'parentnode/parentnode'", dpx!.Message); + delegate { DataDictionary.VerifyChildNodeAndReturnNameAtt(MakeNode("qty"), parentNode); })!; + Assert.AreEqual("Malformed data dictionary: Found 'field' node without 'name' within parent 'parentnode/parentnode'", dpx.Message); } } } diff --git a/UnitTests/Fields/Converters/DecimalConverterTests.cs b/UnitTests/Fields/Converters/DecimalConverterTests.cs index 734454b2f..6363fd7a1 100644 --- a/UnitTests/Fields/Converters/DecimalConverterTests.cs +++ b/UnitTests/Fields/Converters/DecimalConverterTests.cs @@ -11,29 +11,29 @@ public class DecimalConverterTests { [Test] public void Convert() { - Assert.That(DecimalConverter.Convert(new Decimal(4.23322)), Is.EqualTo("4.23322")); - Assert.That(DecimalConverter.Convert(new Decimal(-4.23322)), Is.EqualTo("-4.23322")); + Assert.That(DecimalConverter.Convert(4.23322m), Is.EqualTo("4.23322")); + Assert.That(DecimalConverter.Convert(-4.23322m), Is.EqualTo("-4.23322")); Assert.That(DecimalConverter.Convert("4332.33"), Is.EqualTo(new Decimal(4332.33))); Assert.That(DecimalConverter.Convert("3.000000000021874E-4"), Is.EqualTo(0.0003000000000021874M)); Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert("2.32a34"); }); Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert("+1.2"); }); Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert("(1.2)"); }); Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert(""); }); - Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert(null); }); + Assert.Throws(typeof(FieldConvertError), delegate { DecimalConverter.Convert(null!); }); // check for a different culture than en-XX - System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo( "tr-TR" ); - Assert.That( DecimalConverter.Convert( "4332.33" ), Is.EqualTo( new Decimal( 4332.33 ) ) ); - Assert.That( DecimalConverter.Convert( "-2.33" ), Is.EqualTo( new Decimal( -2.33 ) ) ); - Assert.That( DecimalConverter.Convert( new Decimal( 4.23322 ) ), Is.EqualTo( "4.23322" ) ); - Assert.That( DecimalConverter.Convert( new Decimal( -4.23322 ) ), Is.EqualTo( "-4.23322" ) ); + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("tr-TR"); + Assert.That(DecimalConverter.Convert("4332.33"), Is.EqualTo(4332.33m)); + Assert.That(DecimalConverter.Convert("-2.33"), Is.EqualTo(-2.33m)); + Assert.That(DecimalConverter.Convert(4.23322m), Is.EqualTo("4.23322")); + Assert.That(DecimalConverter.Convert(-4.23322m), Is.EqualTo("-4.23322")); } [Test] public void Convert_WithoutLeadingTrailingZeros() { - Assert.That(DecimalConverter.Convert("23."), Is.EqualTo(new Decimal(23))); - Assert.That(DecimalConverter.Convert(".23"), Is.EqualTo(new Decimal(0.23))); - Assert.That(DecimalConverter.Convert("-.23"), Is.EqualTo(new Decimal(-0.23))); + Assert.That(DecimalConverter.Convert("23."), Is.EqualTo(23m)); + Assert.That(DecimalConverter.Convert(".23"), Is.EqualTo(0.23m)); + Assert.That(DecimalConverter.Convert("-.23"), Is.EqualTo(-0.23m)); } } diff --git a/UnitTests/Fields/Converters/IntConverterTests.cs b/UnitTests/Fields/Converters/IntConverterTests.cs index 827aebd46..e2b8152f8 100644 --- a/UnitTests/Fields/Converters/IntConverterTests.cs +++ b/UnitTests/Fields/Converters/IntConverterTests.cs @@ -19,6 +19,6 @@ public void Convert() Assert.Throws(typeof(FieldConvertError), delegate { IntConverter.Convert("AB"); }); Assert.Throws(typeof(FieldConvertError), delegate { IntConverter.Convert("2.3234"); }); Assert.Throws(typeof(FieldConvertError), delegate { IntConverter.Convert(""); }); - Assert.Throws(typeof(FieldConvertError), delegate { IntConverter.Convert(null); }); + Assert.Throws(typeof(FieldConvertError), delegate { IntConverter.Convert(null!); }); } } diff --git a/UnitTests/FileStoreTests.cs b/UnitTests/FileStoreTests.cs index bed03da65..ed6c6470c 100755 --- a/UnitTests/FileStoreTests.cs +++ b/UnitTests/FileStoreTests.cs @@ -3,6 +3,7 @@ using System.IO; using NUnit.Framework; using System.Threading; +using QuickFix; using QuickFix.Store; namespace UnitTests @@ -10,13 +11,13 @@ namespace UnitTests [TestFixture] public class FileStoreTests { - private FileStore _store; - private FileStoreFactory _factory; + private FileStore? _store; + private FileStoreFactory? _factory; - private QuickFix.SessionSettings _settings; - private QuickFix.SessionID _sessionID; + private QuickFix.SessionSettings _settings = new(); + private QuickFix.SessionID _sessionId = new("unset", "unset", "unset"); - private string _storeDirectory; + private string _storeDirectory = "unset"; [SetUp] public void Setup() @@ -26,34 +27,30 @@ public void Setup() if (System.IO.Directory.Exists(_storeDirectory)) System.IO.Directory.Delete(_storeDirectory, true); - _sessionID = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); + _sessionId = new QuickFix.SessionID("FIX.4.2", "SENDERCOMP", "TARGETCOMP"); QuickFix.SettingsDictionary config = new QuickFix.SettingsDictionary(); config.SetString(QuickFix.SessionSettings.CONNECTION_TYPE, "initiator"); config.SetString(QuickFix.SessionSettings.FILE_STORE_PATH, _storeDirectory); _settings = new QuickFix.SessionSettings(); - _settings.Set(_sessionID, config); + _settings.Set(_sessionId, config); _factory = new FileStoreFactory(_settings); - _store = (FileStore)_factory.Create(_sessionID); + _store = (FileStore)_factory.Create(_sessionId); } void RebuildStore() { - if(_store != null) - { - _store.Dispose(); - } - - _store = (FileStore)_factory.Create(_sessionID); + _store?.Dispose(); + _store = (FileStore)_factory!.Create(_sessionId); } [TearDown] public void Teardown() { - _store.Dispose(); + _store!.Dispose(); Directory.Delete(_storeDirectory, true); } @@ -79,7 +76,7 @@ public void GenerateFileNamesTest() [Test] public void NextSenderMsgSeqNumTest() { - Assert.AreEqual(1, _store.NextSenderMsgSeqNum); + Assert.AreEqual(1, _store!.NextSenderMsgSeqNum); _store.NextSenderMsgSeqNum = 5; Assert.AreEqual(5, _store.NextSenderMsgSeqNum); RebuildStore(); @@ -89,7 +86,7 @@ public void NextSenderMsgSeqNumTest() [Test] public void IncNextSenderMsgSeqNumTest() { - _store.IncrNextSenderMsgSeqNum(); + _store!.IncrNextSenderMsgSeqNum(); Assert.AreEqual(2, _store.NextSenderMsgSeqNum); RebuildStore(); Assert.AreEqual(2, _store.NextSenderMsgSeqNum); @@ -98,7 +95,7 @@ public void IncNextSenderMsgSeqNumTest() [Test] public void NextTargetMsgSeqNumTest() { - Assert.AreEqual(1, _store.NextTargetMsgSeqNum); + Assert.AreEqual(1, _store!.NextTargetMsgSeqNum); _store.NextTargetMsgSeqNum = 6; Assert.AreEqual(6, _store.NextTargetMsgSeqNum); RebuildStore(); @@ -108,7 +105,7 @@ public void NextTargetMsgSeqNumTest() [Test] public void IncNextTargetMsgSeqNumTest() { - _store.IncrNextTargetMsgSeqNum(); + _store!.IncrNextTargetMsgSeqNum(); Assert.AreEqual(2, _store.NextTargetMsgSeqNum); RebuildStore(); Assert.AreEqual(2, _store.NextTargetMsgSeqNum); @@ -119,7 +116,7 @@ public void IncNextTargetMsgSeqNumTest() public void TestSeqNumLimitsForContinuousMarkets() { // Given the next seqnums are UInt64.MaxValue - 1 - _store.NextSenderMsgSeqNum = System.UInt64.MaxValue - 1; + _store!.NextSenderMsgSeqNum = System.UInt64.MaxValue - 1; _store.NextTargetMsgSeqNum = _store.NextSenderMsgSeqNum; // When the next seqnums are incremented @@ -157,7 +154,7 @@ public void TestSeqNumLimitsForContinuousMarkets() public void ResetTest() { // seq nums reset - _store.NextTargetMsgSeqNum = 5; + _store!.NextTargetMsgSeqNum = 5; _store.NextSenderMsgSeqNum = 4; _store.Reset(); Assert.AreEqual(1, _store.NextTargetMsgSeqNum); @@ -179,7 +176,7 @@ public void ResetTest() [Test] public void CreationTimeTest() { - DateTime d1 = _store.CreationTime.Value; + DateTime d1 = _store!.CreationTime!.Value; RebuildStore(); DateTime d2 = _store.CreationTime.Value; Util.UtcDateTimeSerializerTests.AssertHackyDateTimeEquality(d1, d2); @@ -194,7 +191,7 @@ public void CreationTimeTest() [Test] public void GetTest() { - _store.Set(1, "dude"); + _store!.Set(1, "dude"); _store.Set(2, "pude"); _store.Set(3, "ok"); _store.Set(4, "ohai"); diff --git a/UnitTests/GroupTests.cs b/UnitTests/GroupTests.cs index 5daad06b9..25dad3555 100644 --- a/UnitTests/GroupTests.cs +++ b/UnitTests/GroupTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; +using NUnit.Framework; using QuickFix; using QuickFix.Fields; @@ -15,40 +12,38 @@ public void SubGroup() { // issue #11 bug, as reported by karabiberoglu's further-down post - QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup noParty = new QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup(); - noParty.PartyID = new QuickFix.Fields.PartyID("ABC"); - noParty.PartyIDSource = new QuickFix.Fields.PartyIDSource(QuickFix.Fields.PartyIDSource.PROPRIETARY_CUSTOM_CODE); - noParty.PartyRole = new QuickFix.Fields.PartyRole(QuickFix.Fields.PartyRole.CLEARING_FIRM); + QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup noParty = new(); + noParty.PartyID = new PartyID("ABC"); + noParty.PartyIDSource = new PartyIDSource(PartyIDSource.PROPRIETARY_CUSTOM_CODE); + noParty.PartyRole = new PartyRole(PartyRole.CLEARING_FIRM); // group in group - QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup.NoPartySubIDsGroup noPartySub = new QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup.NoPartySubIDsGroup(); - noPartySub.PartySubID = new QuickFix.Fields.PartySubID("subABC"); - noPartySub.PartySubIDType = new QuickFix.Fields.PartySubIDType(QuickFix.Fields.PartySubIDType.FIRM); + QuickFix.FIX44.CollateralInquiry.NoPartyIDsGroup.NoPartySubIDsGroup noPartySub = new(); + noPartySub.PartySubID = new PartySubID("subABC"); + noPartySub.PartySubIDType = new PartySubIDType(PartySubIDType.FIRM); noParty.AddGroup(noPartySub); - noPartySub.PartySubID = new QuickFix.Fields.PartySubID("subDEF"); - noPartySub.PartySubIDType = new QuickFix.Fields.PartySubIDType(QuickFix.Fields.PartySubIDType.LOCATION); + noPartySub.PartySubID = new PartySubID("subDEF"); + noPartySub.PartySubIDType = new PartySubIDType(PartySubIDType.LOCATION); noParty.AddGroup(noPartySub); string msgString = noParty.ToString(); - string expected = String.Join(Message.SOH, new string[] { - "448=ABC","447=D","452=4", - "802=2", //NoPartySubIDs - "523=subABC","803=1", - "523=subDEF","803=31" - }); + string expected = "448=ABC|447=D|452=4|" + + "802=2|" //NoPartySubIDs + + "523=subABC|803=1|" + + "523=subDEF|803=31|"; //Console.WriteLine(msgString); - StringAssert.Contains(expected, msgString); + StringAssert.Contains(expected, msgString.Replace(Message.SOH, '|')); } [Test] public void GroupClone() { - QuickFix.FIX42.News.LinesOfTextGroup linesGroup = new QuickFix.FIX42.News.LinesOfTextGroup(); - linesGroup.Text = new QuickFix.Fields.Text("foo"); - linesGroup.EncodedText = new QuickFix.Fields.EncodedText("bar"); + QuickFix.FIX42.News.LinesOfTextGroup linesGroup = new(); + linesGroup.Text = new Text("foo"); + linesGroup.EncodedText = new EncodedText("bar"); - QuickFix.FIX42.News.LinesOfTextGroup clone = linesGroup.Clone() as QuickFix.FIX42.News.LinesOfTextGroup; + QuickFix.FIX42.News.LinesOfTextGroup clone = (linesGroup.Clone() as QuickFix.FIX42.News.LinesOfTextGroup)!; Assert.AreEqual(linesGroup.Text.Value, clone.Text.Value); Assert.AreEqual(linesGroup.EncodedText.Value, clone.EncodedText.Value); diff --git a/UnitTests/MessageCrackerTests.cs b/UnitTests/MessageCrackerTests.cs index 4d9dd53c6..ddfaa3e27 100644 --- a/UnitTests/MessageCrackerTests.cs +++ b/UnitTests/MessageCrackerTests.cs @@ -1,18 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Text; +using System.Collections.Generic; using NUnit.Framework; using QuickFix; -using QuickFix.Fields; using System.Reflection; - namespace UnitTests { [TestFixture] public class MessageCrackerTests { - private readonly SessionID _DummySessionID = new SessionID("a","b","c"); + private readonly SessionID _dummySessionId = new ("a","b","c"); [SetUp] public void Setup() @@ -87,21 +83,21 @@ public class TestCracker : MessageCracker public void GoldenPath() { MessageCracker mc = new TestCracker(); - TestCracker tc = mc as TestCracker; + TestCracker tc = (mc as TestCracker)!; - mc.Crack(new QuickFix.FIX42.News(), _DummySessionID); + mc.Crack(new QuickFix.FIX42.News(), _dummySessionId); Assert.IsTrue(tc.CrackedNews42); Assert.IsFalse(tc.CrackedNews44); // reset and do the opposite tc.CrackedNews42 = false; - mc.Crack(new QuickFix.FIX44.News(), _DummySessionID); + mc.Crack(new QuickFix.FIX44.News(), _dummySessionId); Assert.IsFalse(tc.CrackedNews42); Assert.IsTrue(tc.CrackedNews44); Assert.IsFalse(tc.CrackedLogonFIXT11); - mc.Crack(new QuickFix.FIXT11.Logon(), _DummySessionID); + mc.Crack(new QuickFix.FIXT11.Logon(), _dummySessionId); Assert.IsTrue(tc.CrackedLogonFIXT11); } @@ -109,8 +105,8 @@ public void GoldenPath() public void UnsupportedMessage() { MessageCracker mc = new TestCracker(); - Assert.Throws(delegate { mc.Crack(new QuickFix.FIX42.Email(), _DummySessionID); }); - Assert.Throws(delegate { mc.Crack(new QuickFix.FIX43.News(), _DummySessionID); }); + Assert.Throws(delegate { mc.Crack(new QuickFix.FIX42.Email(), _dummySessionId); }); + Assert.Throws(delegate { mc.Crack(new QuickFix.FIX43.News(), _dummySessionId); }); } } } diff --git a/UnitTests/MessageTests.cs b/UnitTests/MessageTests.cs index 132c666d4..c4993f37b 100644 --- a/UnitTests/MessageTests.cs +++ b/UnitTests/MessageTests.cs @@ -367,8 +367,8 @@ public void XmlDataWithoutLengthTest() { + "10=028|").Replace('|', Message.SOH); FieldNotFoundException ex = - Assert.Throws(delegate { n.FromString(s, true, dd, dd, _defaultMsgFactory); }); - Assert.AreEqual("field not found for tag: 212", ex!.Message); + Assert.Throws(delegate { n.FromString(s, true, dd, dd, _defaultMsgFactory); })!; + Assert.AreEqual("field not found for tag: 212", ex.Message); } [Test] diff --git a/UnitTests/MessageToXmlTests.cs b/UnitTests/MessageToXmlTests.cs index 8d22a3b89..a1388bc48 100644 --- a/UnitTests/MessageToXmlTests.cs +++ b/UnitTests/MessageToXmlTests.cs @@ -99,7 +99,7 @@ public void ToJSONWithGroupsTest() StringAssert.Contains("\"35\":\"8\"", msg.ToJSON(dataDictionary: null)); // EXCEPTION CASE: params (null, true) => Exception - var ex = Assert.Throws(delegate { msg.ToJSON(null, true); }); + var ex = Assert.Throws(delegate { msg.ToJSON(null, true); })!; StringAssert.Contains( "Must be non-null if 'convertEnumsToDescriptions' is true. (Parameter 'dataDictionary')", ex.Message); diff --git a/UnitTests/SessionDynamicTest.cs b/UnitTests/SessionDynamicTest.cs index 1c405a194..f442c2e8b 100644 --- a/UnitTests/SessionDynamicTest.cs +++ b/UnitTests/SessionDynamicTest.cs @@ -20,8 +20,8 @@ class SessionDynamicTest { public class TestApplication : IApplication { - Action _logonNotify; - Action _logoffNotify; + private readonly Action _logonNotify; + private readonly Action _logoffNotify; public TestApplication(Action logonNotify, Action logoffNotify) { _logonNotify = logonNotify; @@ -55,7 +55,7 @@ public SocketState(Socket s) public Socket _socket; public byte[] _rxBuffer = new byte[1024]; public string _messageFragment = string.Empty; - public string _exMessage; + public string _exMessage = "unset"; } const string Host = "127.0.0.1"; diff --git a/UnitTests/SessionScheduleTests.cs b/UnitTests/SessionScheduleTests.cs index 953b1b320..ecfa36ba3 100755 --- a/UnitTests/SessionScheduleTests.cs +++ b/UnitTests/SessionScheduleTests.cs @@ -44,15 +44,15 @@ private static string PacificStandardTimeZoneId public void TestCtor_BasicDailySchedule() { SettingsDictionary settings = new SettingsDictionary(); - var ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + Exception ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("No value for key: StartTime", ex.Message); settings.SetString(SessionSettings.START_TIME, "00:00:00"); - ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("No value for key: EndTime", ex.Message); settings.SetString(SessionSettings.END_TIME, "00:0blkajsdf"); - ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("String '00:0blkajsdf' was not recognized as a valid TimeSpan", ex.Message); settings.SetString(SessionSettings.END_TIME, "00:00:00"); @@ -67,7 +67,7 @@ public void TestCtor_WeeklongSession() settings.SetString(SessionSettings.END_TIME, "00:00:00"); settings.SetDay(SessionSettings.START_DAY, DayOfWeek.Thursday); - var ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + Exception ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("StartDay used without EndDay", ex.Message); settings.SetDay(SessionSettings.END_DAY, DayOfWeek.Friday); @@ -80,7 +80,7 @@ public void TestCtor_WeekdaysSession() SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.WEEKDAYS, "Sun,Tue,Fri"); - var ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + Exception ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("No value for key: StartTime", ex.Message); settings.SetString(SessionSettings.START_TIME, "00:00:00"); @@ -88,7 +88,7 @@ public void TestCtor_WeekdaysSession() Assert.DoesNotThrow(delegate { new SessionSchedule(settings); }); settings.SetString(SessionSettings.START_DAY, "Tue"); - ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("StartDay/EndDay are not compatible with 'Weekdays' setting", ex.Message); } @@ -100,13 +100,13 @@ public void TestCtor_NonStopSession() Assert.DoesNotThrow(delegate { new SessionSchedule(settings); }); settings.SetString(SessionSettings.START_DAY, "Monday"); - var ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + Exception ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("NonStopSession is not compatible with StartDay/EndDay and StartTime/EndTime", ex.Message); settings = new SettingsDictionary(); settings.SetBool(SessionSettings.NON_STOP_SESSION, true); settings.SetString(SessionSettings.START_TIME, "05:00:00"); - ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); }); + ex = Assert.Throws(typeof(ConfigError), delegate { new SessionSchedule(settings); })!; StringAssert.Contains("NonStopSession is not compatible with StartDay/EndDay and StartTime/EndTime", ex.Message); } diff --git a/UnitTests/SessionSettingsTest.cs b/UnitTests/SessionSettingsTest.cs index 9b6c8d1de..ca108193c 100755 --- a/UnitTests/SessionSettingsTest.cs +++ b/UnitTests/SessionSettingsTest.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using NUnit.Framework; using QuickFix; @@ -7,12 +8,12 @@ namespace UnitTests [TestFixture] public class SessionSettingsTest { - protected System.Text.StringBuilder partialConfiguration; + private System.Text.StringBuilder _partialConfiguration = new(); [SetUp] public void Init() { - partialConfiguration = new System.Text.StringBuilder() + _partialConfiguration = new System.Text.StringBuilder() .AppendLine("[SESSION]") .AppendLine("BeginString=FIX.4.2") .AppendLine("SenderCompID=ISLD") @@ -56,9 +57,9 @@ public void Load() .AppendLine("BeginString=FIX.4.0") .AppendLine("Value=4") .AppendLine("Empty=") - .AppendLine(partialConfiguration.ToString()) + .AppendLine(_partialConfiguration.ToString()) .ToString(); - SessionSettings settings = new SessionSettings(new System.IO.StringReader(configuration)); + SessionSettings settings = new SessionSettings(new StringReader(configuration)); SessionID session1 = new SessionID("FIX.4.2", "ISLD", "TW"); SessionID session2 = new SessionID("FIX.4.1", "ISLD", "WT"); @@ -99,14 +100,14 @@ public void Load() public void LoadSettingsWithDefaultSectionLast() { string configuration = new System.Text.StringBuilder() - .AppendLine(partialConfiguration.ToString()) + .AppendLine(_partialConfiguration.ToString()) .AppendLine("[DEFAULT]") .AppendLine("ConnectionType=initiator") .AppendLine("BeginString=FIX.4.0") .AppendLine("Value=4") .AppendLine("Empty=") .ToString(); - SessionSettings settings = new SessionSettings(new System.IO.StringReader(configuration)); + SessionSettings settings = new SessionSettings(new StringReader(configuration)); SessionID session1 = new SessionID("FIX.4.2", "ISLD", "TW"); SessionID session2 = new SessionID("FIX.4.1", "ISLD", "WT"); @@ -158,7 +159,7 @@ public void DuplicateSession() .AppendLine("SenderCompID=ISLD") .AppendLine("TargetCompID=TW") .ToString(); - Assert.Throws(delegate { new SessionSettings(new System.IO.StringReader(configuration)); }); + Assert.Throws(delegate { new SessionSettings(new StringReader(configuration)); }); } [Test] @@ -175,7 +176,7 @@ public void StripSpaces() .AppendLine(" Double = 1.23 ") .AppendLine(" Bool = N ") .ToString(); - SessionSettings settings = new SessionSettings(new System.IO.StringReader(configuration)); + SessionSettings settings = new SessionSettings(new StringReader(configuration)); Assert.That(settings.Get().GetString("ConnectionType"), Is.EqualTo("initiator")); @@ -232,13 +233,13 @@ public void SettingsToString() .AppendLine("TARGETCOMPID=WT") .AppendLine("VALUE=2") .ToString(); - SessionSettings settings = new SessionSettings(new System.IO.StringReader(configuration)); + SessionSettings settings = new SessionSettings(new StringReader(configuration)); Assert.That(settings.ToString(), Is.EqualTo(configuration)); } [Test] - public void testExtendedSettings() + public void TestExtendedSettings() { string settingsString = new System.Text.StringBuilder() .AppendLine("[DEFAULT]") @@ -259,7 +260,7 @@ public void testExtendedSettings() .AppendLine("EndTime=05:59:00") .ToString(); - SessionSettings settings = new SessionSettings(new System.IO.StringReader(settingsString)); + SessionSettings settings = new SessionSettings(new StringReader(settingsString)); SessionID id = new SessionID("FIX.4.2", "Company", "FixedIncome", "HongKong", "CLIENT1", "HedgeFund", "NYC"); Assert.That(settings.Get(id).GetString("HeartBtInt"), Is.EqualTo("60")); @@ -275,12 +276,8 @@ public void testExtendedSettings() Assert.That(settings.Get(id).GetString("MaxMessagesInResendRequest"), Is.EqualTo("2500")); Assert.That(settings.Get(id).GetString("StartTime"), Is.EqualTo("06:00:00")); Assert.That(settings.Get(id).GetString("EndTime"), Is.EqualTo("05:59:00")); - id = null; - foreach(SessionID sid in settings.GetSessions()) - { - id = sid; - break; - } + + id = settings.GetSessions().First(); Assert.NotNull(id); Assert.That(id.BeginString, Is.EqualTo("FIX.4.2")); Assert.That(id.SenderCompID, Is.EqualTo("Company")); @@ -310,7 +307,7 @@ public void CaseInsensitiveSectionName() BeginString=FIX.4.2 SenderCompID=ISLD TargetCompID=TW"; - SessionSettings settings = new SessionSettings(new System.IO.StringReader(configuration)); + SessionSettings settings = new SessionSettings(new StringReader(configuration)); Assert.That(settings.Get().GetString("ConnectionType"), Is.EqualTo("initiator")); diff --git a/UnitTests/SessionStateTest.cs b/UnitTests/SessionStateTest.cs index 2e0db7cc4..a5e79191f 100755 --- a/UnitTests/SessionStateTest.cs +++ b/UnitTests/SessionStateTest.cs @@ -169,8 +169,8 @@ public void ThreadSafeSetAndGet() { //Simulate background sending of messages that populate into the store AutoResetEvent setEvent = new AutoResetEvent(false); - ThreadPool.QueueUserWorkItem(delegate(object stateObject) { - AutoResetEvent internalSetEvent = (AutoResetEvent)((object[])stateObject)[0]; + ThreadPool.QueueUserWorkItem(delegate(object? stateObject) { + AutoResetEvent internalSetEvent = (AutoResetEvent)((object[])stateObject!)[0]; SessionState internalState = (SessionState)((object[])stateObject)[1]; for (SeqNumType i = 1001; i < 2000; i++) { try { @@ -187,8 +187,8 @@ public void ThreadSafeSetAndGet() { //Simulate background reading of messages from the store - like is done in a resend request answer AutoResetEvent getEvent = new AutoResetEvent(false); - ThreadPool.QueueUserWorkItem(delegate(object stateObject){ - AutoResetEvent internalGetEvent = (AutoResetEvent)((object[])stateObject)[0]; + ThreadPool.QueueUserWorkItem(delegate(object? stateObject){ + AutoResetEvent internalGetEvent = (AutoResetEvent)((object[])stateObject!)[0]; SessionState internalState = (SessionState)((object[])stateObject)[1]; for (SeqNumType i = 1; i < 1000; i++) { try { diff --git a/UnitTests/SettingsTest.cs b/UnitTests/SettingsTest.cs index 94cc53b3b..7a373bc85 100644 --- a/UnitTests/SettingsTest.cs +++ b/UnitTests/SettingsTest.cs @@ -34,14 +34,14 @@ public void Load() 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.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"); Assert.That(oren.Count, Is.EqualTo(2)); - Assert.That(oren.First.Value.Count, Is.EqualTo(1)); + Assert.That(oren.First!.Value.Count, Is.EqualTo(1)); Assert.That(oren.First.Value.GetString("Nero"), Is.EqualTo("TW")); oren.RemoveFirst(); Assert.That(oren.First.Value.Count, Is.EqualTo(2)); @@ -50,7 +50,7 @@ public void Load() 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.Count, Is.EqualTo(5)); Assert.That(nero.First.Value.GetString("WINDIR"), Is.EqualTo("D:\\This Is\\A-Directory\\Connamara\\")); Assert.That(nero.First.Value.GetString("UNIXDIR"), Is.EqualTo("/home/mgatny/This Is/A Directory/ok/")); Assert.That(nero.First.Value.GetString("WINFILE"), Is.EqualTo("D:\\Program Files\\Tomcat 4.1\\webapps\\mgatny\\WEB-INF\\connamara.cfg")); @@ -70,14 +70,14 @@ public void CaseInsensitiveSectionName() LinkedList byLower = settings.Get("foo"); Assert.AreEqual(1, byLower.Count); - Assert.AreEqual(2, byLower.First.Value.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"); Assert.AreEqual(byLower.Count, byUpper.Count); - Assert.AreEqual(byLower.First.Value.Count, byUpper.First.Value.Count); + Assert.AreEqual(byLower.First.Value.Count, byUpper.First!.Value.Count); Assert.AreEqual(byUpper.First.Value.GetString("one"), byUpper.First.Value.GetString("one")); Assert.AreEqual(byUpper.First.Value.GetString("two"), byUpper.First.Value.GetString("two")); } diff --git a/UnitTests/ThreadedSocketReactorTests.cs b/UnitTests/ThreadedSocketReactorTests.cs index 57c300b99..cc9ad0505 100644 --- a/UnitTests/ThreadedSocketReactorTests.cs +++ b/UnitTests/ThreadedSocketReactorTests.cs @@ -11,17 +11,16 @@ namespace UnitTests [TestFixture] public class ThreadedSocketReactorTests { - static readonly Random _random = new Random(); - static TcpListener _tcpListener; + static TcpListener? _tcpListener; private int OccupyAPort() { - int randomPort; + Random random = new(); for (int i = 0; i < 10; i++) { try { - randomPort = _random.Next(5000, 6000); + int randomPort = random.Next(5000, 6000); _tcpListener = new TcpListener(IPAddress.Loopback, randomPort); _tcpListener.Start(); @@ -49,7 +48,6 @@ public void TestStartOnBusyPort() var testingObject = new ThreadedSocketReactor( new IPEndPoint(IPAddress.Loopback, port), settings, - sessionDict: null, acceptorSocketDescriptor: null, new NonSessionLog(new ScreenLogFactory(true, true, true))); @@ -61,10 +59,8 @@ public void TestStartOnBusyPort() } [TearDown] - public void TearDown() - { - if (_tcpListener != null) - _tcpListener.Stop(); + public void TearDown() { + _tcpListener?.Stop(); } } } diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj index 5811fa7af..872b9c08d 100644 --- a/UnitTests/UnitTests.csproj +++ b/UnitTests/UnitTests.csproj @@ -2,6 +2,7 @@ net8.0 + enable AnyCPU;x64 false From 67ed85c665a14a8276c5571a0817c4742c7d93d0 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Thu, 26 Sep 2024 20:33:54 -0500 Subject: [PATCH 4/5] cleanup/nullable-ize SesssionDynamicTest --- UnitTests/SessionDynamicTest.cs | 351 +++++++++++++++----------------- 1 file changed, 169 insertions(+), 182 deletions(-) diff --git a/UnitTests/SessionDynamicTest.cs b/UnitTests/SessionDynamicTest.cs index f442c2e8b..c0743c79c 100644 --- a/UnitTests/SessionDynamicTest.cs +++ b/UnitTests/SessionDynamicTest.cs @@ -16,7 +16,7 @@ namespace UnitTests { [TestFixture] [Category("DynamicSession")] - class SessionDynamicTest + public class SessionDynamicTest { public class TestApplication : IApplication { @@ -27,57 +27,57 @@ public TestApplication(Action logonNotify, Action logoffNotify) _logonNotify = logonNotify; _logoffNotify = logoffNotify; } - public void FromAdmin(Message message, SessionID sessionID) + public void FromAdmin(Message message, SessionID sessionId) { } - public void FromApp(Message message, SessionID sessionID) + public void FromApp(Message message, SessionID sessionId) { } - public void OnCreate(SessionID sessionID) { } - public void OnLogout(SessionID sessionID) + public void OnCreate(SessionID sessionId) { } + public void OnLogout(SessionID sessionId) { - _logoffNotify(sessionID.TargetCompID); + _logoffNotify(sessionId.TargetCompID); } - public void OnLogon(SessionID sessionID) + public void OnLogon(SessionID sessionId) { - _logonNotify(sessionID.TargetCompID); + _logonNotify(sessionId.TargetCompID); } - public void ToAdmin(Message message, SessionID sessionID) { } - public void ToApp(Message message, SessionID sessionID) { } + public void ToAdmin(Message message, SessionID sessionId) { } + public void ToApp(Message message, SessionID sessionId) { } } + class SocketState { public SocketState(Socket s) { - _socket = s; + Socket = s; } - public Socket _socket; - public byte[] _rxBuffer = new byte[1024]; - public string _messageFragment = string.Empty; - public string _exMessage = "unset"; + public readonly Socket Socket; + public readonly byte[] RxBuffer = new byte[1024]; + public string MessageFragment = string.Empty; } - const string Host = "127.0.0.1"; - const int ConnectPort = 55100; - const int AcceptPort = 55101; - const int AcceptPort2 = 55102; - const string ServerCompID = "dummy"; - const string StaticInitiatorCompID = "ini01"; - const string StaticAcceptorCompID = "acc01"; - const string StaticAcceptorCompID2 = "acc02"; - - const string FIXMessageEnd = @"\x0110=\d{3}\x01"; - const string FIXMessageDelimit = @"(8=FIX|\A).*?(" + FIXMessageEnd + @"|\z)"; - - string _logPath; - SocketInitiator _initiator; - ThreadedSocketAcceptor _acceptor; - Dictionary _sessions; - HashSet _loggedOnCompIDs; - Socket _listenSocket; - - SettingsDictionary CreateSessionConfig(string targetCompID, bool isInitiator) + private const string Host = "127.0.0.1"; + private const int ConnectPort = 55100; + private const int AcceptPort = 55101; + private const int AcceptPort2 = 55102; + private const string ServerCompId = "dummy"; + private const string StaticInitiatorCompId = "ini01"; + private const string StaticAcceptorCompId = "acc01"; + private const string StaticAcceptorCompId2 = "acc02"; + + private const string FixMessageEnd = @"\x0110=\d{3}\x01"; + private const string FixMessageDelimit = @"(8=FIX|\A).*?(" + FixMessageEnd + @"|\z)"; + + private string _logPath = "unset"; + private SocketInitiator? _initiator; + private ThreadedSocketAcceptor? _acceptor; + private Dictionary _sessions = new(); + private HashSet _loggedOnCompIDs = new(); + private Socket? _listenSocket; + + private static SettingsDictionary CreateSessionConfig(bool isInitiator) { SettingsDictionary settings = new SettingsDictionary(); settings.SetString(SessionSettings.CONNECTION_TYPE, isInitiator ? "initiator" : "acceptor"); @@ -88,40 +88,36 @@ SettingsDictionary CreateSessionConfig(string targetCompID, bool isInitiator) return settings; } - SessionID CreateSessionID(string targetCompID) + private static SessionID CreateSessionId(string targetCompId) { - return new SessionID(QuickFix.Values.BeginString_FIX42, ServerCompID, targetCompID); + return new SessionID(QuickFix.Values.BeginString_FIX42, ServerCompId, targetCompId); } - void LogonCallback(string compID) + private void LogonCallback(string compId) { lock (_loggedOnCompIDs) { - _loggedOnCompIDs.Add(compID); + _loggedOnCompIDs.Add(compId); Monitor.Pulse(_loggedOnCompIDs); } } - void LogoffCallback(string compID) + + private void LogoffCallback(string compId) { lock (_loggedOnCompIDs) { - _loggedOnCompIDs.Remove(compID); + _loggedOnCompIDs.Remove(compId); Monitor.Pulse(_loggedOnCompIDs); } } - void StartEngine(bool initiator) - { - StartEngine(initiator, false); - } - - void StartEngine(bool initiator, bool twoSessions) + private void StartEngine(bool initiator, bool twoSessions = false) { TestApplication application = new TestApplication(LogonCallback, LogoffCallback); IMessageStoreFactory storeFactory = new MemoryStoreFactory(); SessionSettings settings = new SessionSettings(); SettingsDictionary defaults = new SettingsDictionary(); - defaults.SetString(QuickFix.SessionSettings.FILE_LOG_PATH, _logPath); + defaults.SetString(SessionSettings.FILE_LOG_PATH, _logPath); // Put IP endpoint settings into default section to verify that that defaults get merged into // session-specific settings not only for static sessions, but also for dynamic ones @@ -136,18 +132,18 @@ void StartEngine(bool initiator, bool twoSessions) if (initiator) { defaults.SetString(SessionSettings.RECONNECT_INTERVAL, "1"); - settings.Set(CreateSessionID(StaticInitiatorCompID), CreateSessionConfig(StaticInitiatorCompID, true)); + settings.Set(CreateSessionId(StaticInitiatorCompId), CreateSessionConfig(true)); _initiator = new SocketInitiator(application, storeFactory, settings, logFactory); _initiator.Start(); } else { - settings.Set(CreateSessionID(StaticAcceptorCompID), CreateSessionConfig(StaticAcceptorCompID, false)); + settings.Set(CreateSessionId(StaticAcceptorCompId), CreateSessionConfig(false)); if (twoSessions) { - var id = CreateSessionID(StaticAcceptorCompID2); - var conf = CreateSessionConfig(StaticAcceptorCompID2, false); + var id = CreateSessionId(StaticAcceptorCompId2); + var conf = CreateSessionConfig(false); conf.SetString(SessionSettings.SOCKET_ACCEPT_PORT, AcceptPort2.ToString()); conf.SetString(SessionSettings.FILE_LOG_PATH, _logPath + "2"); @@ -160,68 +156,70 @@ void StartEngine(bool initiator, bool twoSessions) } } - void StartListener() + private void StartListener() { var address = IPAddress.Parse(Host); var listenEndpoint = new IPEndPoint(address, ConnectPort); _listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _listenSocket.Bind(listenEndpoint); _listenSocket.Listen(10); - _listenSocket.BeginAccept(new AsyncCallback(ProcessInboundConnect), null); + _listenSocket.BeginAccept(ProcessInboundConnect, null); } - void ProcessInboundConnect(IAsyncResult ar) + private void ProcessInboundConnect(IAsyncResult ar) { - Socket handler = null; + if (_listenSocket == null) + return; + try { - handler = _listenSocket.EndAccept(ar); + Socket handler = _listenSocket.EndAccept(ar); + ReceiveAsync(new SocketState(handler)); + _listenSocket.BeginAccept(ProcessInboundConnect, null); } catch { _listenSocket = null; // Assume listener has been closed } - - if (handler != null) - { - ReceiveAsync(new SocketState(handler)); - _listenSocket.BeginAccept(new AsyncCallback(ProcessInboundConnect), null); - } } - void ProcessRXData(IAsyncResult ar) + void ProcessRxData(IAsyncResult ar) { - SocketState socketState = (SocketState)ar.AsyncState; + SocketState? socketState = (SocketState?)ar.AsyncState; + if (socketState is null) + throw new AssertionException("socketState is null"); + int bytesReceived = 0; try { - bytesReceived = socketState._socket.EndReceive(ar); + bytesReceived = socketState.Socket.EndReceive(ar); } catch (Exception ex) { - socketState._exMessage = ex.InnerException == null ? ex.Message : ex.InnerException.Message; + // don't know what else to do with this + Console.WriteLine(ex.InnerException == null ? ex.Message : ex.InnerException.Message); } if (bytesReceived == 0) { - socketState._socket.Close(); - lock (socketState._socket) - Monitor.Pulse(socketState._socket); + socketState.Socket.Close(); + lock (socketState.Socket) + Monitor.Pulse(socketState.Socket); return; } - string msgText = CharEncoding.DefaultEncoding.GetString(socketState._rxBuffer, 0, bytesReceived); - foreach (Match m in Regex.Matches(msgText, FIXMessageDelimit)) + string msgText = CharEncoding.DefaultEncoding.GetString(socketState.RxBuffer, 0, bytesReceived); + foreach (Match m in Regex.Matches(msgText, FixMessageDelimit)) { - socketState._messageFragment += m.Value; - if (Regex.IsMatch(socketState._messageFragment, FIXMessageEnd)) + socketState.MessageFragment += m.Value; + if (Regex.IsMatch(socketState.MessageFragment, FixMessageEnd)) { - Message message = new Message(socketState._messageFragment); - socketState._messageFragment = string.Empty; - string targetCompID = message.Header.GetString(QuickFix.Fields.Tags.TargetCompID); + Message message = new Message(socketState.MessageFragment); + socketState.MessageFragment = string.Empty; + string targetCompId = message.Header.GetString(QuickFix.Fields.Tags.TargetCompID); if (message.Header.GetString(QuickFix.Fields.Tags.MsgType) == QuickFix.Fields.MsgType.LOGON) lock (_sessions) { - _sessions[targetCompID] = socketState; + _sessions[targetCompId] = socketState; Monitor.Pulse(_sessions); } } @@ -231,7 +229,7 @@ void ProcessRXData(IAsyncResult ar) { ReceiveAsync(socketState); } - catch (System.ObjectDisposedException) + catch (ObjectDisposedException) { // ignore socket disposed } @@ -239,20 +237,10 @@ void ProcessRXData(IAsyncResult ar) void ReceiveAsync(SocketState socketState) { - socketState._socket.BeginReceive(socketState._rxBuffer, 0, socketState._rxBuffer.Length, SocketFlags.None, new AsyncCallback(ProcessRXData), socketState); - } - - Socket ConnectToEngine() - { - return ConnectToEngine(AcceptPort); + socketState.Socket.BeginReceive(socketState.RxBuffer, 0, socketState.RxBuffer.Length, SocketFlags.None, ProcessRxData, socketState); } - Socket ConnectToEngine(int port) - { - return ConnectToEngine(port, 3); - } - - Socket ConnectToEngine(int port, int numRetries) + private Socket ConnectToEngine(int port = AcceptPort, int numRetries = 3) { var address = IPAddress.Parse(Host); var endpoint = new IPEndPoint(address, port); @@ -261,49 +249,46 @@ Socket ConnectToEngine(int port, int numRetries) { socket.Connect(endpoint); ReceiveAsync(new SocketState(socket)); - return socket; } catch (Exception ex) { - string errorMsg = string.Format("Failed to connect: {0}", ex.Message); + string errorMsg = $"Failed to connect: {ex.Message}"; if (numRetries > 0) { numRetries--; - TestContext.Out.WriteLine(string.Format("{0}: Retries Remaining: {1}: Retrying...", errorMsg, numRetries)); + TestContext.Out.WriteLine($"{errorMsg}: Retries Remaining: {numRetries}: Retrying..."); Thread.Sleep(500); return ConnectToEngine(port, numRetries); } - else - { - Assert.Fail(errorMsg); - return null; - } + + Assert.Fail(errorMsg); } + return socket; } - Socket GetSocket(string compID) + Socket GetSocket(string compId) { lock (_sessions) - return _sessions[compID]._socket; + return _sessions[compId].Socket; } - bool WaitForLogonStatus(string targetCompID) + bool WaitForLogonStatus(string targetCompId) { lock (_loggedOnCompIDs) { - if (!_loggedOnCompIDs.Contains(targetCompID)) + if (!_loggedOnCompIDs.Contains(targetCompId)) Monitor.Wait(_loggedOnCompIDs, 10000); - return _loggedOnCompIDs.Contains(targetCompID); + return _loggedOnCompIDs.Contains(targetCompId); } } - bool WaitForLogonMessage(string targetCompID) + bool WaitForLogonMessage(string targetCompId) { lock (_sessions) { - if (!_sessions.ContainsKey(targetCompID)) + if (!_sessions.ContainsKey(targetCompId)) Monitor.Wait(_sessions, 10000); - return _sessions.ContainsKey(targetCompID); + return _sessions.ContainsKey(targetCompId); } } @@ -317,33 +302,33 @@ bool WaitForDisconnect(Socket s) } } - bool WaitForDisconnect(string compID) + bool WaitForDisconnect(string compId) { - return WaitForDisconnect(GetSocket(compID)); + return WaitForDisconnect(GetSocket(compId)); } - bool HasReceivedMessage(string compID) + bool HasReceivedMessage(string compId) { lock (_sessions) - return _sessions.ContainsKey(compID); + return _sessions.ContainsKey(compId); } - bool IsLoggedOn(string compID) + bool IsLoggedOn(string compId) { lock (_loggedOnCompIDs) - return _loggedOnCompIDs.Contains(compID); + return _loggedOnCompIDs.Contains(compId); } - void SendInitiatorLogon(string senderCompID) + void SendInitiatorLogon(string senderCompId) { - SendLogon(GetSocket(senderCompID), senderCompID); + SendLogon(GetSocket(senderCompId), senderCompId); } - void SendLogon(Socket s, string senderCompID) + void SendLogon(Socket s, string senderCompId) { var msg = new QuickFix.FIX42.Logon(); - msg.Header.SetField(new QuickFix.Fields.TargetCompID(ServerCompID)); - msg.Header.SetField(new QuickFix.Fields.SenderCompID(senderCompID)); + msg.Header.SetField(new QuickFix.Fields.TargetCompID(ServerCompId)); + msg.Header.SetField(new QuickFix.Fields.SenderCompID(senderCompId)); msg.Header.SetField(new QuickFix.Fields.MsgSeqNum(1)); msg.Header.SetField(new QuickFix.Fields.SendingTime(System.DateTime.UtcNow)); msg.SetField(new QuickFix.Fields.HeartBtInt(300)); @@ -373,12 +358,9 @@ public void Setup() [TearDown] public void TearDown() { - if (_listenSocket != null) - _listenSocket.Close(); - if (_initiator != null) - _initiator.Stop(true); - if (_acceptor != null) - _acceptor.Stop(true); + _listenSocket?.Close(); + _initiator?.Stop(true); + _acceptor?.Stop(true); _initiator = null; _acceptor = null; @@ -391,7 +373,7 @@ public void TearDown() public void DifferentPortForAcceptorTest() { //create two sessions with two different SOCKET_ACCEPT_PORT - StartEngine(false, true); + StartEngine(false, twoSessions: true); Thread.Sleep(100); @@ -399,15 +381,15 @@ public void DifferentPortForAcceptorTest() using (var socket11 = ConnectToEngine(AcceptPort)) { Assert.IsTrue(socket11.Connected, "Failed to connect to 1st accept port"); - SendLogon(socket11, StaticAcceptorCompID); - Assert.IsTrue(WaitForLogonStatus(StaticAcceptorCompID), "Failed to logon 1st acceptor session"); + SendLogon(socket11, StaticAcceptorCompId); + Assert.IsTrue(WaitForLogonStatus(StaticAcceptorCompId), "Failed to logon 1st acceptor session"); } // Ensure we can't log on 2nd session to 1st port using (var socket12 = ConnectToEngine(AcceptPort)) { Assert.IsTrue(socket12.Connected, "Failed to connect to 1st accept port"); - SendLogon(socket12, StaticAcceptorCompID2); + SendLogon(socket12, StaticAcceptorCompId2); Assert.IsTrue(WaitForDisconnect(socket12), "Server failed to disconnect 2nd CompID from 1st port"); } } @@ -418,68 +400,71 @@ public void AddSessionDynamicWithDifferentPortTest() StartEngine(false); // Add the dynamic acceptor with another port and ensure that we can now log on - string dynamicCompID = "acc10"; - var sessionID = CreateSessionID(dynamicCompID); - var sessionConfig = CreateSessionConfig(dynamicCompID, false); + const string dynamicCompId = "acc10"; + SessionID sessionId = CreateSessionId(dynamicCompId); + SettingsDictionary sessionConfig = CreateSessionConfig(false); sessionConfig.SetString(SessionSettings.SOCKET_ACCEPT_PORT, AcceptPort2.ToString()); - _acceptor.AddSession(sessionID, sessionConfig); + if (_acceptor is null) + throw new AssertionException("_acceptor is null"); + _acceptor.AddSession(sessionId, sessionConfig); var socket = ConnectToEngine(AcceptPort2); - SendLogon(socket, dynamicCompID); + SendLogon(socket, dynamicCompId); - Assert.IsTrue(WaitForLogonStatus(dynamicCompID), "Failed to logon dynamic added acceptor session with another port"); + Assert.IsTrue(WaitForLogonStatus(dynamicCompId), "Failed to logon dynamic added acceptor session with another port"); } [Test] public void DynamicAcceptor() { StartEngine(false); + if (_acceptor is null) + throw new AssertionException("_acceptor is null"); // Ensure we can log on statically (normally) configured acceptor var socket01 = ConnectToEngine(); - SendLogon(socket01, StaticAcceptorCompID); - Assert.IsTrue(WaitForLogonStatus(StaticAcceptorCompID), "Failed to logon static acceptor session"); + SendLogon(socket01, StaticAcceptorCompId); + Assert.IsTrue(WaitForLogonStatus(StaticAcceptorCompId), "Failed to logon static acceptor session"); // Ensure that attempt to log on as yet un-added dynamic acceptor fails var socket02 = ConnectToEngine(); - string dynamicCompID = "acc10"; - SendLogon(socket02, dynamicCompID); + string dynamicCompId = "acc10"; + SendLogon(socket02, dynamicCompId); Assert.IsTrue(WaitForDisconnect(socket02), "Server failed to disconnect unconfigured CompID"); - Assert.False(HasReceivedMessage(dynamicCompID), "Unexpected message received for unconfigured CompID"); + Assert.False(HasReceivedMessage(dynamicCompId), "Unexpected message received for unconfigured CompID"); // Add the dynamic acceptor and ensure that we can now log on - var sessionID = CreateSessionID(dynamicCompID); - var sessionConfig = CreateSessionConfig(dynamicCompID, false); - Assert.IsTrue(_acceptor.AddSession(sessionID, sessionConfig), "Failed to add dynamic session to acceptor"); + SessionID sessionId = CreateSessionId(dynamicCompId); + SettingsDictionary sessionConfig = CreateSessionConfig(false); + Assert.IsTrue(_acceptor.AddSession(sessionId, sessionConfig), "Failed to add dynamic session to acceptor"); var socket03 = ConnectToEngine(); - SendLogon(socket03, dynamicCompID); - Assert.IsTrue(WaitForLogonStatus(dynamicCompID), "Failed to logon dynamic acceptor session"); + SendLogon(socket03, dynamicCompId); + Assert.IsTrue(WaitForLogonStatus(dynamicCompId), "Failed to logon dynamic acceptor session"); // Ensure that we can't add the same session again - Assert.IsFalse(_acceptor.AddSession(sessionID, sessionConfig), "Added dynamic session twice"); + Assert.IsFalse(_acceptor.AddSession(sessionId, sessionConfig), "Added dynamic session twice"); // Now that dynamic acceptor is logged on, ensure that unforced attempt to remove session fails - Assert.IsFalse(_acceptor.RemoveSession(sessionID, false), "Unexpected success removing active session"); + Assert.IsFalse(_acceptor.RemoveSession(sessionId, false), "Unexpected success removing active session"); Assert.IsTrue(socket03.Connected, "Unexpected loss of connection"); // Ensure that forced attempt to remove session dynamic session succeeds, even though it is in logged on state - Assert.IsTrue(_acceptor.RemoveSession(sessionID, true), "Failed to remove active session"); + Assert.IsTrue(_acceptor.RemoveSession(sessionId, true), "Failed to remove active session"); Assert.IsTrue(WaitForDisconnect(socket03), "Socket still connected after session removed"); - Assert.IsFalse(IsLoggedOn(dynamicCompID), "Session still logged on after being removed"); + Assert.IsFalse(IsLoggedOn(dynamicCompId), "Session still logged on after being removed"); // Ensure that we can perform unforced removal of a dynamic session that is not logged on. - string dynamicCompID2 = "acc20"; - var sessionID2 = CreateSessionID(dynamicCompID2); - Assert.IsTrue(_acceptor.AddSession(sessionID2, CreateSessionConfig(dynamicCompID2, false)), "Failed to add dynamic session to acceptor"); - Assert.IsTrue(_acceptor.RemoveSession(sessionID2, false), "Failed to remove inactive session"); + string dynamicCompId2 = "acc20"; + var sessionId2 = CreateSessionId(dynamicCompId2); + Assert.IsTrue(_acceptor.AddSession(sessionId2, CreateSessionConfig(false)), "Failed to add dynamic session to acceptor"); + Assert.IsTrue(_acceptor.RemoveSession(sessionId2, false), "Failed to remove inactive session"); // Ensure that we can remove statically configured session - Assert.IsTrue(IsLoggedOn(StaticAcceptorCompID), "Unexpected logoff"); - Assert.IsTrue(_acceptor.RemoveSession(CreateSessionID(StaticAcceptorCompID), true), "Failed to remove active session"); + Assert.IsTrue(IsLoggedOn(StaticAcceptorCompId), "Unexpected logoff"); + Assert.IsTrue(_acceptor.RemoveSession(CreateSessionId(StaticAcceptorCompId), true), "Failed to remove active session"); Assert.IsTrue(WaitForDisconnect(socket01), "Socket still connected after session removed"); - Assert.IsFalse(IsLoggedOn(StaticAcceptorCompID), "Session still logged on after being removed"); - + Assert.IsFalse(IsLoggedOn(StaticAcceptorCompId), "Session still logged on after being removed"); } [Test] @@ -487,46 +472,48 @@ public void DynamicInitiator() { StartListener(); StartEngine(true); + if (_initiator is null) + throw new AssertionException("_initiator is null"); // Ensure we can log on statically (normally) configured initiator - Assert.IsTrue(WaitForLogonMessage(StaticInitiatorCompID), "Failed to get logon message for static initiator session"); - SendInitiatorLogon(StaticInitiatorCompID); + Assert.IsTrue(WaitForLogonMessage(StaticInitiatorCompId), "Failed to get logon message for static initiator session"); + SendInitiatorLogon(StaticInitiatorCompId); // Add the dynamic initator and ensure that we can log on - string dynamicCompID = "ini10"; - var sessionID = CreateSessionID(dynamicCompID); - var sessionConfig = CreateSessionConfig(dynamicCompID, true); - Assert.IsTrue(_initiator.AddSession(sessionID, sessionConfig), "Failed to add dynamic session to initiator"); - Assert.IsTrue(WaitForLogonMessage(dynamicCompID), "Failed to get logon message for dynamic initiator session"); - SendInitiatorLogon(dynamicCompID); - Assert.IsTrue(WaitForLogonStatus(dynamicCompID), "Failed to logon dynamic initiator session"); + string dynamicCompId = "ini10"; + var sessionId = CreateSessionId(dynamicCompId); + var sessionConfig = CreateSessionConfig(true); + Assert.IsTrue(_initiator.AddSession(sessionId, sessionConfig), "Failed to add dynamic session to initiator"); + Assert.IsTrue(WaitForLogonMessage(dynamicCompId), "Failed to get logon message for dynamic initiator session"); + SendInitiatorLogon(dynamicCompId); + Assert.IsTrue(WaitForLogonStatus(dynamicCompId), "Failed to logon dynamic initiator session"); // Ensure that we can't add the same session again - Assert.IsFalse(_initiator.AddSession(sessionID, sessionConfig), "Added dynamic session twice"); + Assert.IsFalse(_initiator.AddSession(sessionId, sessionConfig), "Added dynamic session twice"); // Now that dynamic initiator is logged on, ensure that unforced attempt to remove session fails - Assert.IsFalse(_initiator.RemoveSession(sessionID, false), "Unexpected success removing active session"); - Assert.IsTrue(IsLoggedOn(dynamicCompID), "Unexpected logoff"); + Assert.IsFalse(_initiator.RemoveSession(sessionId, false), "Unexpected success removing active session"); + Assert.IsTrue(IsLoggedOn(dynamicCompId), "Unexpected logoff"); // Ensure that forced attempt to remove session dynamic session succeeds, even though it is in logged on state - Assert.IsTrue(_initiator.RemoveSession(sessionID, true), "Failed to remove active session"); - Assert.IsTrue(WaitForDisconnect(dynamicCompID), "Socket still connected after session removed"); - Assert.IsFalse(IsLoggedOn(dynamicCompID), "Session still logged on after being removed"); + Assert.IsTrue(_initiator.RemoveSession(sessionId, true), "Failed to remove active session"); + Assert.IsTrue(WaitForDisconnect(dynamicCompId), "Socket still connected after session removed"); + Assert.IsFalse(IsLoggedOn(dynamicCompId), "Session still logged on after being removed"); // Ensure that we can perform unforced removal of a dynamic session that is not logged on. - string dynamicCompID2 = "ini20"; - var sessionID2 = CreateSessionID(dynamicCompID2); - Assert.IsTrue(_initiator.AddSession(sessionID2, CreateSessionConfig(dynamicCompID2, true)), "Failed to add dynamic session to initiator"); - Assert.IsTrue(WaitForLogonMessage(dynamicCompID2), "Failed to get logon message for dynamic initiator session"); - Assert.IsFalse(IsLoggedOn(dynamicCompID2), "Session logged on"); - Assert.IsTrue(_initiator.RemoveSession(sessionID2, false), "Failed to remove inactive session"); - Assert.IsTrue(WaitForDisconnect(dynamicCompID2), "Socket still connected after session removed"); + string dynamicCompId2 = "ini20"; + var sessionId2 = CreateSessionId(dynamicCompId2); + Assert.IsTrue(_initiator.AddSession(sessionId2, CreateSessionConfig(true)), "Failed to add dynamic session to initiator"); + Assert.IsTrue(WaitForLogonMessage(dynamicCompId2), "Failed to get logon message for dynamic initiator session"); + Assert.IsFalse(IsLoggedOn(dynamicCompId2), "Session logged on"); + Assert.IsTrue(_initiator.RemoveSession(sessionId2, false), "Failed to remove inactive session"); + Assert.IsTrue(WaitForDisconnect(dynamicCompId2), "Socket still connected after session removed"); // Ensure that we can remove statically configured session - Assert.IsTrue(IsLoggedOn(StaticInitiatorCompID), "Unexpected loss of connection"); - Assert.IsTrue(_initiator.RemoveSession(CreateSessionID(StaticInitiatorCompID), true), "Failed to remove active session"); - Assert.IsTrue(WaitForDisconnect(StaticInitiatorCompID), "Socket still connected after session removed"); - Assert.IsFalse(IsLoggedOn(StaticInitiatorCompID), "Session still logged on after being removed"); + Assert.IsTrue(IsLoggedOn(StaticInitiatorCompId), "Unexpected loss of connection"); + Assert.IsTrue(_initiator.RemoveSession(CreateSessionId(StaticInitiatorCompId), true), "Failed to remove active session"); + Assert.IsTrue(WaitForDisconnect(StaticInitiatorCompId), "Socket still connected after session removed"); + Assert.IsFalse(IsLoggedOn(StaticInitiatorCompId), "Session still logged on after being removed"); // Check that log directory default setting has been effective Assert.Greater(System.IO.Directory.GetFiles(_logPath, QuickFix.Values.BeginString_FIX42 + "*.log").Length, 0); From bc570a288fd0a4f9fc4e97b3cee3c1ed561b28b3 Mon Sep 17 00:00:00 2001 From: Grant Birchmeier Date: Thu, 26 Sep 2024 20:42:00 -0500 Subject: [PATCH 5/5] remove now-unneeded "#nullable enable" --- UnitTests/DataDictionary_ValidateTests.cs | 3 --- UnitTests/Logger/FileLogTests.cs | 4 +--- UnitTests/SessionTest.cs | 4 +--- UnitTests/SessionTestSupport/MockApplication.cs | 1 - UnitTests/SessionTestSupport/MockApplicationExt.cs | 1 - UnitTests/SessionTestSupport/MockResponder.cs | 1 - UnitTests/SettingsDictionaryTests.cs | 3 +-- 7 files changed, 3 insertions(+), 14 deletions(-) diff --git a/UnitTests/DataDictionary_ValidateTests.cs b/UnitTests/DataDictionary_ValidateTests.cs index af32fa3c9..ef1c01f87 100644 --- a/UnitTests/DataDictionary_ValidateTests.cs +++ b/UnitTests/DataDictionary_ValidateTests.cs @@ -1,6 +1,3 @@ -#nullable enable - -using System; using NUnit.Framework; using QuickFix; using QuickFix.DataDictionary; diff --git a/UnitTests/Logger/FileLogTests.cs b/UnitTests/Logger/FileLogTests.cs index 2a155132b..8cee0f083 100644 --- a/UnitTests/Logger/FileLogTests.cs +++ b/UnitTests/Logger/FileLogTests.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.IO; +using System.IO; using NUnit.Framework; using QuickFix.Logger; diff --git a/UnitTests/SessionTest.cs b/UnitTests/SessionTest.cs index 87368e25d..57603c562 100755 --- a/UnitTests/SessionTest.cs +++ b/UnitTests/SessionTest.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; diff --git a/UnitTests/SessionTestSupport/MockApplication.cs b/UnitTests/SessionTestSupport/MockApplication.cs index 04deb1028..f777d3636 100644 --- a/UnitTests/SessionTestSupport/MockApplication.cs +++ b/UnitTests/SessionTestSupport/MockApplication.cs @@ -1,4 +1,3 @@ -#nullable enable using System; namespace UnitTests.SessionTestSupport; diff --git a/UnitTests/SessionTestSupport/MockApplicationExt.cs b/UnitTests/SessionTestSupport/MockApplicationExt.cs index cda8a9eaa..c73dda33e 100644 --- a/UnitTests/SessionTestSupport/MockApplicationExt.cs +++ b/UnitTests/SessionTestSupport/MockApplicationExt.cs @@ -1,4 +1,3 @@ -#nullable enable using System.Collections.Generic; namespace UnitTests.SessionTestSupport; diff --git a/UnitTests/SessionTestSupport/MockResponder.cs b/UnitTests/SessionTestSupport/MockResponder.cs index 3bff8fcd2..4ea7a5fcf 100644 --- a/UnitTests/SessionTestSupport/MockResponder.cs +++ b/UnitTests/SessionTestSupport/MockResponder.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; diff --git a/UnitTests/SettingsDictionaryTests.cs b/UnitTests/SettingsDictionaryTests.cs index 00b59c8c9..edbffd98d 100755 --- a/UnitTests/SettingsDictionaryTests.cs +++ b/UnitTests/SettingsDictionaryTests.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using NUnit.Framework; using QuickFix;