TcpClientToTcpServerSocketHandlerMockup.cs
using GenXdev.AsyncSockets.Arguments;
using GenXdev.AsyncSockets.Handlers; using GenXdev.AsyncSockets.Logging; using Ninject; using System.Collections.Concurrent; namespace GenXdev.AsyncSockets.Mocking { public delegate void OnInitializeCallback<ServerHandlerType, ClientHandlerType>(ServerHandlerType ServerHandler, ClientHandlerType ClientHandler); public class TcpClientToTcpServerSocketHandlerMockup<ServerHandlerType, ClientHandlerType> : IDisposable where ServerHandlerType : SocketHandlerBase where ClientHandlerType : SocketHandlerBase { IKernel Kernel; IServiceLogger Logger; volatile bool ClientHandlerIsTimedOut; volatile bool ServerHandlerIsTimedOut; public ServerHandlerType ServerHandler { get; private set; } public ClientHandlerType ClientHandler { get; private set; } [Inject] public TcpClientToTcpServerSocketHandlerMockup(IKernel Kernel) { this.Kernel = Kernel; this.Logger = Kernel.Get<IServiceLogger>(); } void ClientHandler_OnHandleException(object sender, OnHandleExceptionEventArgs e) { System.Threading.Thread.Sleep(2000); if ((ClientHandlerIsTimedOut || ServerHandlerIsTimedOut) && ( e.Exception.Message.ToLowerInvariant().Contains("dispose"))) return; if ((ClientHandlerIsTimedOut || ServerHandlerIsTimedOut) && ( e.Exception.Message.ToLowerInvariant().Contains("handler wants to switch state"))) return; Exceptions.Enqueue(e.Exception); } void ServerHandler_OnHandleException(object sender, OnHandleExceptionEventArgs e) { System.Threading.Thread.Sleep(2000); if ((ClientHandlerIsTimedOut || ServerHandlerIsTimedOut) && ( e.Exception.Message.ToLowerInvariant().Contains("dispose"))) return; if ((ClientHandlerIsTimedOut || ServerHandlerIsTimedOut) && ( e.Exception.Message.ToLowerInvariant().Contains("handler wants to switch state"))) return; Logger.LogException(e.Exception, "Exception: " + e.Exception.Message); Exceptions.Enqueue(e.Exception); } object closeLock = new object(); void ClientHandler_OnHandlerClosed(object sender, Containers.HandlerClosedEventArgs e) { lock (closeLock) { Logger.LogProgramFlowInfoMessage(() => { return "ClientHandler closed"; }); ClientHandlerClosed = true; CheckForContinue(); } } void ServerHandler_OnHandlerClosed(object sender, Containers.HandlerClosedEventArgs e) { lock (closeLock) { Logger.LogProgramFlowInfoMessage(() => { return "ServerHandler closed"; }); ServerHandlerClosed = true; CheckForContinue(); } } void CheckForContinue() { if (ServerHandlerClosed && ClientHandlerClosed) { ServerHandlerClosed = false; ClientHandlerClosed = false; ConnectionsCompleted++; if (ConnectionsCompleted < ConnectionsToComplete) { Logger.LogProgramFlowInfoMessage(() => { return "CheckForContinue: ConnectionsCompleted < ConnectionsToComplete, " + ConnectionsCompleted.ToString() + " < " + ConnectionsToComplete.ToString(); }); ThreadPool.QueueUserWorkItem(ServerHandler.StartHandlingSocket); } } } #region Fields volatile bool ClientHandlerClosed; volatile bool ServerHandlerClosed; volatile int ConnectionsCompleted; volatile int ConnectionsToComplete; ConcurrentQueue<Exception> Exceptions = new ConcurrentQueue<Exception>(); #endregion public TcpClientToTcpServerSocketHandlerMockup<ServerHandlerType, ClientHandlerType> Execute(int ConnectionsToComplete = 1, OnInitializeCallback<ServerHandlerType, ClientHandlerType> InitializeCallback = null) { ClientHandlerIsTimedOut = false; ServerHandlerIsTimedOut = false; lock (this) { if (ConnectionsToComplete < 1) return this; this.ConnectionsToComplete = ConnectionsToComplete; try { // create socket IO handlers var ServerSocketIOHandler = new SocketIOMockHandler(); var ClientSocketIOHandler = new SocketIOMockHandler() { Remote = ServerSocketIOHandler }; // create handlers this.ServerHandler = Kernel.Get<ServerHandlerType>(); this.ClientHandler = Kernel.Get<ClientHandlerType>(); // initialize io handlers ServerSocketIOHandler.Initialize(Kernel); ClientSocketIOHandler.Initialize(Kernel, ServerSocketIOHandler, null, false, (object sender, EventArgs e) => { ServerHandler.StartHandlingSocket(null); } ); // assign our own handlers this.ServerHandler.OnHandlerClosed += ServerHandler_OnHandlerClosed; this.ServerHandler.OnHandleException += ServerHandler_OnHandleException; this.ClientHandler.OnHandlerClosed += ClientHandler_OnHandlerClosed; this.ClientHandler.OnHandleException += ClientHandler_OnHandleException; // initialize handlers this.ServerHandler.CreateSaea(); ServerSocketIOHandler.SetSaea(ServerHandler.saeaHandler); this.ClientHandler.CreateSaea(); ClientSocketIOHandler.SetSaea(ClientHandler.saeaHandler); this.ServerHandler.OnDequeueHandler(); this.ClientHandler.OnDequeueHandler(); // assign new mock io handlers this.ServerHandler.SocketIO = ServerSocketIOHandler; this.ServerHandler.RegisterHandler(this.ServerHandler.saeaHandler); this.ClientHandler.SocketIO = ClientSocketIOHandler; this.ClientHandler.RegisterHandler(this.ClientHandler.saeaHandler); // allow unit-test to do it's initialization if (InitializeCallback != null) { InitializeCallback(this.ServerHandler, this.ClientHandler); } // reset ConnectionsCompleted = 0; ServerHandlerClosed = false; ClientHandlerClosed = false; // start System.Threading.ThreadPool.QueueUserWorkItem((state) => { ClientHandler.StartHandlingSocket(null); }); // while (ConnectionsCompleted < this.ConnectionsToComplete) { if ((ServerHandler.IsTimedOut) || (ClientHandler.IsTimedOut)) { Kernel.Get<IServiceLogger>().Stop(); Kernel.Get<IServiceLogger>().Start(); Logger.LogProgramFlowInfoMessage(() => { return ClientHandler.GetType().Name + ", timeout expired!"; }); ClientHandlerIsTimedOut = true; ClientHandler.Close(); ServerHandlerIsTimedOut = true; ServerHandler.Close(); } System.Threading.Thread.Sleep(100); } if (ConnectionsCompleted > this.ConnectionsToComplete) { throw new InvalidOperationException("ConnectionsCompleted > ConnectionsToComplete"); } if (Exceptions.TryDequeue(out Exception exc)) throw exc; } finally { Logger.LogProgramFlowInfoMessage(() => { return "stopping!"; }); Kernel.Get<IServiceLogger>().Stop(); DisposeHandlers(); } return this; } } #region Disposing public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { DisposeHandlers(); } } private void DisposeHandlers() { while (Exceptions.TryDequeue(out Exception e)) { }; if (ServerHandler != null) { ServerHandler.OnHandlerClosed -= ServerHandler_OnHandlerClosed; ServerHandler.OnHandleException -= ServerHandler_OnHandleException; ServerHandler.Dispose(); ServerHandler = null; } if (ClientHandler != null) { ClientHandler.OnHandlerClosed -= ClientHandler_OnHandlerClosed; ClientHandler.OnHandleException -= ClientHandler_OnHandleException; ClientHandler.Dispose(); ClientHandler = null; } } ~TcpClientToTcpServerSocketHandlerMockup() { Dispose(false); } #endregion } } |