public void IPv4TcpLoopbackConsecutiveSendReceiveTest() { CancellationTokenSource cancelServer = new CancellationTokenSource(); var serverChannel = new SIPTCPChannel(IPAddress.Loopback, 7064); serverChannel.DisableLocalTCPSocketsCheck = true; var serverTask = Task.Run(() => { RunServer(serverChannel, cancelServer); }); for (int i = 1; i < 3; i++) { TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); var clientChannel = new SIPTCPChannel(IPAddress.Any, 7065); clientChannel.DisableLocalTCPSocketsCheck = true; SIPURI serverUri = serverChannel.GetContactURI(SIPSchemesEnum.sip, IPAddress.Loopback); logger.LogDebug($"Server URI {serverUri.ToString()}."); var clientTask = Task.Run(async() => { await RunClient(clientChannel, serverUri, testComplete); }); Task.WhenAny(new Task[] { clientTask, Task.Delay(TRANSPORT_TEST_TIMEOUT) }).Wait(); if (testComplete.Task.IsCompleted == false) { // The client did not set the completed signal. This means the delay task must have completed and hence the test failed. testComplete.SetResult(false); } Assert.True(testComplete.Task.Result); logger.LogDebug($"Completed for test run {i}."); } cancelServer.Cancel(); }
public void IPv6TcpLoopbackSendReceiveTest() { CancellationTokenSource cancelServer = new CancellationTokenSource(); TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); var serverChannel = new SIPTCPChannel(IPAddress.IPv6Loopback, 7060); serverChannel.DisableLocalTCPSocketsCheck = true; var clientChannel = new SIPTCPChannel(IPAddress.IPv6Loopback, 7061); clientChannel.DisableLocalTCPSocketsCheck = true; var serverTask = Task.Run(() => { RunServer(serverChannel, cancelServer); }); var clientTask = Task.Run(async() => { await RunClient(clientChannel, new SIPURI(SIPSchemesEnum.sip, serverChannel.SIPChannelEndPoint), testComplete); }); Task.WhenAny(new Task[] { serverTask, clientTask, Task.Delay(2000) }).Wait(); if (testComplete.Task.IsCompleted == false) { // The client did not set the completed signal. This means the delay task must have completed and hence the test failed. testComplete.SetResult(false); } Assert.IsTrue(testComplete.Task.Result); cancelServer.Cancel(); }
/// <summary> /// Initialises the SIP transport layer. /// </summary> public async Task InitialiseSIP() { if (_isInitialised == false) { await Task.Run(() => { _isInitialised = true; // Configure the SIP transport layer. SIPTransport = new SIPTransport(); bool sipChannelAdded = false; if (m_sipSocketsNode != null) { // Set up the SIP channels based on the app.config file. List <SIPChannel> sipChannels = SIPTransportConfig.ParseSIPChannelsNode(m_sipSocketsNode); if (sipChannels?.Count > 0) { SIPTransport.AddSIPChannel(sipChannels); sipChannelAdded = true; } } if (sipChannelAdded == false) { // Use default options to set up a SIP channel. SIPUDPChannel udpChannel = null; try { udpChannel = new SIPUDPChannel(new IPEndPoint(IPAddress.Any, SIP_DEFAULT_PORT)); } catch (SocketException bindExcp) { logger.LogWarning($"Socket exception attempting to bind UDP channel to port {SIP_DEFAULT_PORT}, will use random port. {bindExcp.Message}."); udpChannel = new SIPUDPChannel(new IPEndPoint(IPAddress.Any, 0)); } var tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Any, udpChannel.Port)); SIPTransport.AddSIPChannel(new List <SIPChannel> { udpChannel, tcpChannel }); } }); // Wire up the transport layer so incoming SIP requests have somewhere to go. SIPTransport.SIPTransportRequestReceived += SIPTransportRequestReceived; // Log all SIP packets received to a log file. SIPTransport.SIPRequestInTraceEvent += SIPRequestInTraceEvent; SIPTransport.SIPRequestOutTraceEvent += SIPRequestOutTraceEvent; SIPTransport.SIPResponseInTraceEvent += SIPResponseInTraceEvent; SIPTransport.SIPResponseOutTraceEvent += SIPResponseOutTraceEvent; } }
public void IPv4TcpLoopbackConsecutiveSendReceiveTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); // This test fails on WSL and Linux due to closed TCP sockets going into the TIME_WAIT state. // See comment in SIPTCPChannel.OnSIPStreamDisconnected for additional info. if (Environment.OSVersion.Platform != PlatformID.Unix) { ManualResetEventSlim serverReadyEvent = new ManualResetEventSlim(false); CancellationTokenSource cancelServer = new CancellationTokenSource(); var serverChannel = new SIPTCPChannel(IPAddress.Loopback, 0); serverChannel.DisableLocalTCPSocketsCheck = true; var serverTask = Task.Run(() => { RunServer(serverChannel, cancelServer, serverReadyEvent); }); for (int i = 1; i < 3; i++) { TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); var clientChannel = new SIPTCPChannel(IPAddress.Loopback, 0); clientChannel.DisableLocalTCPSocketsCheck = true; SIPURI serverUri = serverChannel.GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.tcp, new IPEndPoint(IPAddress.Loopback, 0))); logger.LogDebug($"Server URI {serverUri.ToString()}."); var clientTask = Task.Run(async() => { await RunClient(clientChannel, serverUri, testComplete, cancelServer, serverReadyEvent); }); serverReadyEvent.Wait(); if (!Task.WhenAny(new Task[] { clientTask }).Wait(TRANSPORT_TEST_TIMEOUT)) { logger.LogWarning($"Tasks timed out"); } if (testComplete.Task.IsCompleted == false) { // The client did not set the completed signal. This means the delay task must have completed and hence the test failed. testComplete.SetResult(false); } Assert.True(testComplete.Task.Result); logger.LogDebug($"Completed for test run {i}."); Task.Delay(1000).Wait(); } cancelServer.Cancel(); } }
public void IPv6TcpLoopbackSendReceiveTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); if (!Socket.OSSupportsIPv6) { logger.LogDebug("Test skipped as OS does not support IPv6."); } else { ManualResetEventSlim serverReadyEvent = new ManualResetEventSlim(false); CancellationTokenSource cancelServer = new CancellationTokenSource(); TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); var serverChannel = new SIPTCPChannel(IPAddress.IPv6Loopback, 0); serverChannel.DisableLocalTCPSocketsCheck = true; var clientChannel = new SIPTCPChannel(IPAddress.IPv6Loopback, 0); clientChannel.DisableLocalTCPSocketsCheck = true; var serverTask = Task.Run(() => { RunServer(serverChannel, cancelServer, serverReadyEvent); }); var clientTask = Task.Run(async() => { #pragma warning disable RCS1090 // Add call to 'ConfigureAwait' (or vice versa). await RunClient( clientChannel, serverChannel.GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.tcp, new IPEndPoint(IPAddress.IPv6Loopback, 0))), testComplete, cancelServer, serverReadyEvent); #pragma warning restore RCS1090 // Add call to 'ConfigureAwait' (or vice versa). }); serverReadyEvent.Wait(); if (!Task.WhenAny(new Task[] { serverTask, clientTask }).Wait(TRANSPORT_TEST_TIMEOUT)) { logger.LogWarning($"Tasks timed out"); } if (testComplete.Task.IsCompleted == false) { // The client did not set the completed signal. This means the delay task must have completed and hence the test failed. testComplete.SetResult(false); } Assert.True(testComplete.Task.Result); cancelServer.Cancel(); } }
public void IPv4TcpLoopbackSendReceiveTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); ManualResetEventSlim serverReadyEvent = new ManualResetEventSlim(false); CancellationTokenSource cancelServer = new CancellationTokenSource(); TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); var serverChannel = new SIPTCPChannel(IPAddress.Loopback, 0); serverChannel.DisableLocalTCPSocketsCheck = true; var clientChannel = new SIPTCPChannel(IPAddress.Loopback, 0); clientChannel.DisableLocalTCPSocketsCheck = true; Task.Run(() => { RunServer(serverChannel, cancelServer, serverReadyEvent); }); var clientTask = Task.Run(async() => { await RunClient( clientChannel, serverChannel.GetContactURI(SIPSchemesEnum.sip, new SIPEndPoint(SIPProtocolsEnum.tcp, new IPEndPoint(IPAddress.Loopback, 0))), testComplete, cancelServer, serverReadyEvent); }); serverReadyEvent.Wait(); if (!Task.WhenAny(new Task[] { clientTask }).Wait(TRANSPORT_TEST_TIMEOUT)) { logger.LogWarning($"Tasks timed out"); } if (testComplete.Task.IsCompleted == false) { // The client did not set the completed signal. This means the delay task must have completed and hence the test failed. testComplete.SetResult(false); } Assert.True(testComplete.Task.Result); cancelServer.Cancel(); }
/// <summary> /// Runs a single task as part of the overall job. /// </summary> /// <param name="options">The options that dictate the type of task to run.</param> /// <param name="taskNumber">The number assigned to this task.</param> /// <returns>A boolean indicating whether this single task succeeded or not.</returns> private static async Task <bool> RunTask(Options options, int taskNumber) { SIPTransport sipTransport = new SIPTransport(); try { DateTime startTime = DateTime.Now; (var dstEp, var dstUri) = ParseDestination(options.Destination); logger.LogDebug($"Destination IP end point {dstEp} and SIP URI {dstUri}"); IPAddress localAddress = (dstEp.Address.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Any : IPAddress.Any; SIPChannel sipChannel = null; switch (dstEp.Protocol) { case SIPProtocolsEnum.tcp: sipChannel = new SIPTCPChannel(new IPEndPoint(localAddress, DEFAULT_SIP_CLIENT_PORT)); (sipChannel as SIPTCPChannel).DisableLocalTCPSocketsCheck = true; // Allow sends to listeners on this host. break; case SIPProtocolsEnum.tls: var certificate = new X509Certificate2(@"localhost.pfx", ""); sipChannel = new SIPTLSChannel(certificate, new IPEndPoint(localAddress, DEFAULT_SIPS_CLIENT_PORT)); break; case SIPProtocolsEnum.udp: sipChannel = new SIPUDPChannel(new IPEndPoint(localAddress, DEFAULT_SIP_CLIENT_PORT)); break; case SIPProtocolsEnum.ws: sipChannel = new SIPClientWebSocketChannel(); break; case SIPProtocolsEnum.wss: sipChannel = new SIPClientWebSocketChannel(); break; default: throw new ApplicationException($"Don't know how to create SIP channel for transport {dstEp.Protocol}."); } sipTransport.AddSIPChannel(sipChannel); Task <bool> task = null; switch (options.Scenario) { case Scenarios.uac: task = InitiateCallTaskAsync(sipTransport, dstUri); break; case Scenarios.opt: default: task = SendOptionsTaskAsync(sipTransport, dstUri); break; } var result = await Task.WhenAny(task, Task.Delay(options.Timeout * 1000)); TimeSpan duration = DateTime.Now.Subtract(startTime); bool failed = false; if (!task.IsCompleted) { logger.LogWarning($"=> Request to {dstEp} did not get a response on task {taskNumber} after {duration.TotalMilliseconds.ToString("0")}ms."); failed = true; } else if (!task.Result) { logger.LogWarning($"=> Request to {dstEp} did not get the expected response on task {taskNumber} after {duration.TotalMilliseconds.ToString("0")}ms."); failed = true; } else { logger.LogInformation($"=> Got correct response on send {taskNumber} in {duration.TotalMilliseconds.ToString("0")}ms."); } return(!failed); } finally { logger.LogDebug("Shutting down the SIP transport..."); sipTransport.Shutdown(); } }
public void TcpTrickleReceiveTest() { logger.LogDebug("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); logger.BeginScope(System.Reflection.MethodBase.GetCurrentMethod().Name); TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); // TCP server. TcpListener listener = new TcpListener(IPAddress.Loopback, 0); listener.Start(); var actualEP = listener.LocalEndpoint as IPEndPoint; // SIP TCP Channel var transport = new SIPTransport(); var tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Loopback, 0)); tcpChannel.DisableLocalTCPSocketsCheck = true; transport.AddSIPChannel(tcpChannel); int requestCount = 10; int recvdReqCount = 0; Task.Run(() => { try { var tcpClient = listener.AcceptTcpClient(); logger.LogDebug($"Dummy TCP listener accepted client with remote end point {tcpClient.Client.RemoteEndPoint}."); for (int i = 0; i < requestCount; i++) { logger.LogDebug($"Sending request {i}."); var req = SIPRequest.GetRequest(SIPMethodsEnum.OPTIONS, new SIPURI(SIPSchemesEnum.sip, tcpChannel.ListeningSIPEndPoint)); byte[] reqBytes = Encoding.UTF8.GetBytes(req.ToString()); tcpClient.GetStream().Write(reqBytes, 0, reqBytes.Length); tcpClient.GetStream().Flush(); Task.Delay(30).Wait(); } tcpClient.GetStream().Close(); } catch (Exception excp) { logger.LogError($"Exception on dummy TCP listener task. {excp.Message}"); testComplete.SetResult(false); } }); transport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { logger.LogDebug($"Request received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipRequest.StatusLine}"); logger.LogDebug(sipRequest.ToString()); Interlocked.Increment(ref recvdReqCount); if (recvdReqCount == requestCount) { if (!testComplete.TrySetResult(true)) { logger.LogWarning($"TcpTrickleReceiveTest: FAILED to set result on CompletionSource."); } } return(Task.FromResult(0)); }; transport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) => { logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}"); logger.LogDebug(sipResponse.ToString()); return(Task.FromResult(0)); }; if (!tcpChannel.ConnectClientAsync(actualEP, null, null).Wait(TimeSpan.FromMilliseconds(TRANSPORT_TEST_TIMEOUT))) { logger.LogWarning($"ConnectClientAsync timed out"); } logger.LogDebug("Test client connected."); if (!Task.WhenAny(new Task[] { testComplete.Task }).Wait(TRANSPORT_TEST_TIMEOUT)) { logger.LogWarning($"Tasks timed out"); } logger.LogDebug("Test completed, shutting down SIP transport layer."); transport.Shutdown(); logger.LogDebug("SIP transport layer shutdown."); // Give the SIP transport time to shutdown. Keeps exception messages out of the logs. Task.Delay(500).Wait(); Assert.True(testComplete.Task.IsCompleted); Assert.True(testComplete.Task.Result); Assert.True(requestCount == recvdReqCount, $"The count of {recvdReqCount} for the requests received did not match what was expected."); }
public void TcpTrickleReceiveTest() { TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); IPEndPoint listenEP = new IPEndPoint(IPAddress.Loopback, 9066); var transport = new SIPTransport(); var tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Loopback, 9067)); tcpChannel.DisableLocalTCPSocketsCheck = true; transport.AddSIPChannel(tcpChannel); int requestCount = 10; int recvdReqCount = 0; Task.Run(() => { TcpListener listener = new TcpListener(listenEP); listener.Start(); var tcpClient = listener.AcceptTcpClient(); logger.LogDebug($"TCP listener accepted client with remote end point {tcpClient.Client.RemoteEndPoint}."); for (int i = 0; i < requestCount; i++) { logger.LogDebug($"Sending request {i}."); var req = transport.GetRequest(SIPMethodsEnum.OPTIONS, SIPURI.ParseSIPURIRelaxed($"{i}@sipsorcery.com")); byte[] reqBytes = Encoding.UTF8.GetBytes(req.ToString()); tcpClient.GetStream().Write(reqBytes, 0, reqBytes.Length); tcpClient.GetStream().Flush(); Task.Delay(30).Wait(); } tcpClient.GetStream().Close(); }); transport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { logger.LogDebug($"Request received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipRequest.StatusLine}"); logger.LogDebug(sipRequest.ToString()); Interlocked.Increment(ref recvdReqCount); if (recvdReqCount == requestCount) { testComplete.SetResult(true); } }; transport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) => { logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}"); logger.LogDebug(sipResponse.ToString()); }; tcpChannel.ConnectClientAsync(listenEP, null, null).Wait(); Task.WhenAny(new Task[] { testComplete.Task, Task.Delay(5000) }).Wait(); transport.Shutdown(); Assert.IsTrue(testComplete.Task.IsCompleted); Assert.IsTrue(testComplete.Task.Result); Assert.AreEqual(requestCount, recvdReqCount, $"The count of {recvdReqCount} for the requests received did not match what was expected."); }
/// <summary> /// Executes the command set by the program's command line arguments. /// </summary> /// <param name="options">The options that dictate the SIP command to execute.</param> static async Task RunCommand(Options options) { try { logger.LogDebug($"RunCommand {options.Destination}"); (var dstEp, var dstUri) = ParseDestination(options.Destination); logger.LogDebug($"Destination IP end point {dstEp} and SIP URI {dstUri}"); int sendCount = 0; bool success = true; do { IPAddress localAddress = (dstEp.Address.AddressFamily == AddressFamily.InterNetworkV6) ? IPAddress.IPv6Any : IPAddress.Any; SIPChannel sipChannel = null; switch (dstEp.Protocol) { case SIPProtocolsEnum.tcp: sipChannel = new SIPTCPChannel(new IPEndPoint(localAddress, DEFAULT_SIP_CLIENT_PORT)); (sipChannel as SIPTCPChannel).DisableLocalTCPSocketsCheck = true; // Allow sends to listeners on this host. break; case SIPProtocolsEnum.tls: var certificate = new X509Certificate2(@"localhost.pfx", ""); sipChannel = new SIPTLSChannel(certificate, new IPEndPoint(localAddress, DEFAULT_SIPS_CLIENT_PORT)); break; case SIPProtocolsEnum.udp: sipChannel = new SIPUDPChannel(new IPEndPoint(localAddress, DEFAULT_SIP_CLIENT_PORT)); break; case SIPProtocolsEnum.ws: sipChannel = new SIPClientWebSocketChannel(); break; case SIPProtocolsEnum.wss: sipChannel = new SIPClientWebSocketChannel(); break; default: throw new ApplicationException($"Don't know how to create SIP channel for transport {dstEp.Protocol}."); } SIPTransport sipTransport = new SIPTransport(); sipTransport.AddSIPChannel(sipChannel); if (sendCount > 0 && options.Period > 0) { await Task.Delay(options.Period * 1000); } sendCount++; DateTime sendTime = DateTime.Now; var sendTask = SendOptionsTaskAsync(sipTransport, dstUri); var result = await Task.WhenAny(sendTask, Task.Delay(options.Timeout * 1000)); TimeSpan duration = DateTime.Now.Subtract(sendTime); if (!sendTask.IsCompleted) { logger.LogWarning($"=> Request to {dstEp} did not get a response on send {sendCount} of {options.Count} after {duration.TotalMilliseconds.ToString("0")}ms."); success = false; } else if (!sendTask.Result) { logger.LogWarning($"=> Request to {dstEp} did not get the expected response on request {sendCount} of {options.Count} after {duration.TotalMilliseconds.ToString("0")}ms."); success = false; } else { logger.LogInformation($"=> Got correct response on send {sendCount} of {options.Count} in {duration.TotalMilliseconds.ToString("0")}ms."); } logger.LogDebug("Shutting down the SIP transport..."); sipTransport.Shutdown(); if (success == false) { break; } }while (sendCount < options.Count); DNSManager.Stop(); // Give the transport half a second to shutdown (puts the log messages in a better sequence). await Task.Delay(500); logger.LogInformation($"=> Command completed {((success) ? "successfully" : "with failure")}."); } catch (Exception excp) { logger.LogError($"Exception RunCommand. {excp.Message}"); } }
public void TcpTrickleReceiveTest() { TaskCompletionSource <bool> testComplete = new TaskCompletionSource <bool>(); IPEndPoint listenEP = new IPEndPoint(IPAddress.Loopback, 9067); var transport = new SIPTransport(); var tcpChannel = new SIPTCPChannel(new IPEndPoint(IPAddress.Loopback, 9066)); tcpChannel.DisableLocalTCPSocketsCheck = true; transport.AddSIPChannel(tcpChannel); int requestCount = 10; int recvdReqCount = 0; Task.Run(() => { try { TcpListener listener = new TcpListener(listenEP); listener.Start(); var tcpClient = listener.AcceptTcpClient(); logger.LogDebug($"Dummy TCP listener accepted client with remote end point {tcpClient.Client.RemoteEndPoint}."); for (int i = 0; i < requestCount; i++) { logger.LogDebug($"Sending request {i}."); var req = transport.GetRequest(SIPMethodsEnum.OPTIONS, tcpChannel.GetContactURI(SIPSchemesEnum.sip, listenEP.Address)); byte[] reqBytes = Encoding.UTF8.GetBytes(req.ToString()); tcpClient.GetStream().Write(reqBytes, 0, reqBytes.Length); tcpClient.GetStream().Flush(); Task.Delay(30).Wait(); } tcpClient.GetStream().Close(); } catch (Exception excp) { logger.LogError($"Exception on dummy TCP listener task. {excp.Message}"); testComplete.SetResult(false); } }); transport.SIPTransportRequestReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) => { logger.LogDebug($"Request received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipRequest.StatusLine}"); logger.LogDebug(sipRequest.ToString()); Interlocked.Increment(ref recvdReqCount); if (recvdReqCount == requestCount) { testComplete.SetResult(true); } }; transport.SIPTransportResponseReceived += (SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse) => { logger.LogDebug($"Response received {localSIPEndPoint.ToString()}<-{remoteEndPoint.ToString()}: {sipResponse.ShortDescription}"); logger.LogDebug(sipResponse.ToString()); }; tcpChannel.ConnectClientAsync(listenEP, null, null).Wait(); Task.WhenAny(new Task[] { testComplete.Task, Task.Delay(TRANSPORT_TEST_TIMEOUT) }).Wait(); transport.Shutdown(); // Give the SIP transport time to shutdown. Keeps exception messages out of the logs. Task.Delay(500).Wait(); Assert.True(testComplete.Task.IsCompleted); Assert.True(testComplete.Task.Result); Assert.True(requestCount == recvdReqCount, $"The count of {recvdReqCount} for the requests received did not match what was expected."); }