using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using System.Threading;
using Hazel.Udp;
using Hazel.Udp.FewerThreads;
using System.Net.Sockets;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace Hazel.UnitTests
{
[TestClass]
public class ThreadLimitedUdpConnectionTests
{
protected ThreadLimitedUdpConnectionListener CreateListener(int numWorkers, IPEndPoint endPoint, ILogger logger, IPMode ipMode = IPMode.IPv4)
{
return new ThreadLimitedUdpConnectionListener(numWorkers, endPoint, logger, ipMode);
}
protected UdpConnection CreateConnection(IPEndPoint endPoint, ILogger logger, IPMode ipMode = IPMode.IPv4)
{
return new UdpClientConnection(logger, endPoint, ipMode);
}
[TestMethod]
public void ServerDisposeDisconnectsTest()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296);
bool serverConnected = false;
bool serverDisconnected = false;
bool clientDisconnected = false;
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger("SERVER")))
using (UdpConnection connection = this.CreateConnection(ep, new TestLogger("CLIENT")))
{
listener.NewConnection += (evt) =>
{
serverConnected = true;
evt.Connection.Disconnected += (o, et) => serverDisconnected = true;
};
connection.Disconnected += (o, evt) => clientDisconnected = true;
listener.Start();
connection.Connect();
Thread.Sleep(100); // Gotta wait for the server to set up the events.
listener.Dispose();
Thread.Sleep(100);
Assert.IsTrue(serverConnected);
Assert.IsTrue(clientDisconnected);
Assert.IsFalse(serverDisconnected);
}
}
[TestMethod]
public void ClientDisposeDisconnectTest()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296);
bool serverConnected = false;
bool serverDisconnected = false;
bool clientDisconnected = false;
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(ep, new TestLogger()))
{
listener.NewConnection += (evt) =>
{
serverConnected = true;
evt.Connection.Disconnected += (o, et) => serverDisconnected = true;
};
connection.Disconnected += (o, et) => clientDisconnected = true;
listener.Start();
connection.Connect();
Thread.Sleep(100); // Gotta wait for the server to set up the events.
connection.Dispose();
Thread.Sleep(100);
Assert.IsTrue(serverConnected);
Assert.IsTrue(serverDisconnected);
Assert.IsFalse(clientDisconnected);
}
}
///
/// Tests the fields on UdpConnection.
///
[TestMethod]
public void UdpFieldTest()
{
IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296);
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(ep, new TestLogger()))
{
listener.Start();
connection.Connect();
//Connection fields
Assert.AreEqual(ep, connection.EndPoint);
//UdpConnection fields
Assert.AreEqual(new IPEndPoint(IPAddress.Loopback, 4296), connection.EndPoint);
Assert.AreEqual(1, connection.Statistics.DataBytesSent);
Assert.AreEqual(0, connection.Statistics.DataBytesReceived);
}
}
[TestMethod]
public void UdpHandshakeTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
listener.Start();
MessageReader output = null;
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
output = e.HandshakeData.Duplicate();
};
connection.Connect(TestData);
Thread.Sleep(10);
for (int i = 0; i < TestData.Length; ++i)
{
Assert.AreEqual(TestData[i], output.ReadByte());
}
}
}
[TestMethod]
public void UdpUnreliableMessageSendTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
MessageReader output = null;
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
e.Connection.DataReceived += delegate (DataReceivedEventArgs evt)
{
output = evt.Message.Duplicate();
};
};
listener.Start();
connection.Connect();
for (int i = 0; i < 4; ++i)
{
var msg = MessageWriter.Get(SendOption.None);
msg.Write(TestData);
connection.Send(msg);
msg.Recycle();
}
Thread.Sleep(10);
for (int i = 0; i < TestData.Length; ++i)
{
Assert.AreEqual(TestData[i], output.ReadByte());
}
}
}
[TestMethod]
public void UdpReliableMessageResendTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
var listenerEp = new IPEndPoint(IPAddress.Loopback, 4296);
var captureEp = new IPEndPoint(IPAddress.Loopback, 4297);
using (SocketCapture capture = new SocketCapture(captureEp, listenerEp, new TestLogger()))
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, listenerEp.Port), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(captureEp, new TestLogger()))
using (SemaphoreSlim readLock = new SemaphoreSlim(0, 1))
{
connection.ResendTimeoutMs = 100;
connection.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
MessageReader output = null;
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
var udpConn = (UdpConnection)e.Connection;
udpConn.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
e.Connection.DataReceived += delegate (DataReceivedEventArgs evt)
{
output = evt.Message.Duplicate();
readLock.Release();
};
};
listener.Start();
connection.Connect();
capture.AssertPacketsToRemoteCountEquals(0);
const int NumberOfPacketsToResend = 4;
const int NumberOfTimesToResend = 3;
using (capture.SendToRemoteSemaphore = new Semaphore(0, int.MaxValue))
{
for (int pktCnt = 0; pktCnt < NumberOfPacketsToResend; ++pktCnt)
{
Console.WriteLine("Send blocked pkt");
var msg = MessageWriter.Get(SendOption.Reliable);
msg.Write(TestData);
connection.Send(msg);
msg.Recycle();
for (int drops = 0; drops < NumberOfTimesToResend; ++drops)
{
capture.AssertPacketsToRemoteCountEquals(1);
capture.DiscardPacketForRemote();
}
capture.AssertPacketsToRemoteCountEquals(1);
capture.SendToRemoteSemaphore.Release(); // Actually let it send.
Assert.IsTrue(readLock.Wait(1000));
for (int i = 0; i < TestData.Length; ++i)
{
Assert.AreEqual(TestData[i], output.ReadByte());
}
output = null;
}
}
Assert.AreEqual(NumberOfPacketsToResend * NumberOfTimesToResend, connection.Statistics.MessagesResent);
}
}
[TestMethod]
public void UdpReliableMessageAckTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
var listenerEp = new IPEndPoint(IPAddress.Loopback, 4296);
var captureEp = new IPEndPoint(IPAddress.Loopback, 4297);
using (SocketCapture capture = new SocketCapture(captureEp, listenerEp, new TestLogger()))
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, listenerEp.Port), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(captureEp, new TestLogger()))
{
connection.ResendTimeoutMs = 100;
connection.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
var udpConn = (UdpConnection)e.Connection;
udpConn.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
};
listener.Start();
connection.Connect();
capture.AssertPacketsToLocalCountEquals(0);
const int NumberOfPacketsToSend = 4;
using (capture.SendToLocalSemaphore = new Semaphore(0, int.MaxValue))
{
for (int pktCnt = 0; pktCnt < NumberOfPacketsToSend; ++pktCnt)
{
Console.WriteLine("Send blocked pkt");
var msg = MessageWriter.Get(SendOption.Reliable);
msg.Write(TestData);
connection.Send(msg);
msg.Recycle();
capture.AssertPacketsToLocalCountEquals(1);
var ack = capture.PeekPacketForLocal();
Assert.AreEqual(10, ack[0]); // enum SendOptionInternal.Acknowledgement
Assert.AreEqual(0, ack[1]);
Assert.AreEqual(pktCnt + 1, ack[2]);
Assert.AreEqual(255, ack[3]);
capture.SendToLocalSemaphore.Release(); // Actually let it send.
capture.AssertPacketsToLocalCountEquals(0);
}
}
// +1 for Hello packet
Thread.Sleep(100); // The final ack has to actually be processed.
Assert.AreEqual(1 + NumberOfPacketsToSend, connection.Statistics.ReliablePacketsAcknowledged);
}
}
[TestMethod]
public void UdpReliableMessageAckWithDropTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
var listenerEp = new IPEndPoint(IPAddress.Loopback, 4296);
var captureEp = new IPEndPoint(IPAddress.Loopback, 4297);
using (SocketCapture capture = new SocketCapture(captureEp, listenerEp, new TestLogger()))
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, listenerEp.Port), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(captureEp, new TestLogger()))
{
connection.ResendTimeoutMs = 10000; // No resends please
connection.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
var udpConn = (UdpConnection)e.Connection;
udpConn.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
};
listener.Start();
connection.Connect();
capture.AssertPacketsToLocalCountEquals(0);
using (capture.SendToRemoteSemaphore = new Semaphore(0, int.MaxValue))
using (capture.SendToLocalSemaphore = new Semaphore(0, int.MaxValue))
{
// Send 3 packets to remote
for (int pktCnt = 0; pktCnt < 3; ++pktCnt)
{
var msg = MessageWriter.Get(SendOption.Reliable);
msg.Write(TestData);
connection.Send(msg);
msg.Recycle();
}
// Drop the middle packet
capture.AssertPacketsToRemoteCountEquals(3);
capture.ReorderPacketsForRemote(list => list.Sort(SortByPacketId.Instance));
Console.WriteLine(capture.PacketsForRemoteToString());
capture.ReleasePacketsForRemote(1);
capture.DiscardPacketForRemote();
capture.ReleasePacketsForRemote(1);
// Receive 2 acks
capture.AssertPacketsToLocalCountEquals(2);
capture.ReorderPacketsForLocal(list => list.Sort(SortByPacketId.Instance));
Console.WriteLine(capture.PacketsForLocalToString());
var ack1 = capture.PeekPacketForLocal();
Assert.AreEqual(10, ack1[0]); // enum SendOptionInternal.Acknowledgement
Assert.AreEqual(0, ack1[1]);
Assert.AreEqual(1, ack1[2]);
Assert.AreEqual(255, ack1[3]);
capture.ReleasePacketsToLocal(1);
var ack2 = capture.PeekPacketForLocal();
Assert.AreEqual(10, ack2[0]); // enum SendOptionInternal.Acknowledgement
Assert.AreEqual(0, ack2[1]);
Assert.AreEqual(3, ack2[2]);
Assert.AreEqual(254, ack2[3]); // The server is expecting packet 2
capture.ReleasePacketsToLocal(1);
}
// +1 for Hello packet, +2 for reliable
Thread.Sleep(100); // The final ack has to actually be processed.
Assert.AreEqual(3, connection.Statistics.ReliablePacketsAcknowledged);
}
}
[TestMethod]
public void UdpReliableMessageAckFillsDroppedAcksTest()
{
byte[] TestData = new byte[] { 1, 2, 3, 4, 5, 6 };
var listenerEp = new IPEndPoint(IPAddress.Loopback, 4296);
var captureEp = new IPEndPoint(IPAddress.Loopback, 4297);
using (SocketCapture capture = new SocketCapture(captureEp, listenerEp, new TestLogger()))
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, listenerEp.Port), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(captureEp, new TestLogger("Client")))
{
connection.ResendTimeoutMs = 10000; // No resends please
connection.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
listener.NewConnection += delegate (NewConnectionEventArgs e)
{
var udpConn = (UdpConnection)e.Connection;
udpConn.KeepAliveInterval = Timeout.Infinite; // Don't let pings interfere.
};
listener.Start();
connection.Connect();
capture.AssertPacketsToLocalCountEquals(0);
using (capture.SendToLocalSemaphore = new Semaphore(0, int.MaxValue))
{
// Send 4 packets to remote
for (int pktCnt = 0; pktCnt < 4; ++pktCnt)
{
var msg = MessageWriter.Get(SendOption.Reliable);
msg.Write(TestData);
connection.Send(msg);
msg.Recycle();
}
// Receive 4 acks, Drop the middle two
capture.AssertPacketsToLocalCountEquals(4);
capture.ReorderPacketsForLocal(list => list.Sort(SortByPacketId.Instance));
var ack1 = capture.PeekPacketForLocal();
Assert.AreEqual(10, ack1[0]); // enum SendOptionInternal.Acknowledgement
Assert.AreEqual(0, ack1[1]);
Assert.AreEqual(1, ack1[2]);
Assert.AreEqual(255, ack1[3]);
capture.ReleasePacketsToLocal(1);
capture.DiscardPacketForLocal(2);
var ack4 = capture.PeekPacketForLocal();
Assert.AreEqual(10, ack4[0]); // enum SendOptionInternal.Acknowledgement
Assert.AreEqual(0, ack4[1]);
Assert.AreEqual(4, ack4[2]);
Assert.AreEqual(255, ack4[3]);
capture.ReleasePacketsToLocal(1);
}
// +1 for Hello packet, +4 for reliable despite the dropped ack
Thread.Sleep(100); // The final ack has to actually be processed.
Assert.AreEqual(3, connection.Statistics.AcknowledgementMessagesReceived);
Assert.AreEqual(5, connection.Statistics.ReliablePacketsAcknowledged);
}
}
private class SortByPacketId : IComparer
{
public static SortByPacketId Instance = new SortByPacketId();
public int Compare(ByteSpan x, ByteSpan y)
{
ushort xId = BitConverter.ToUInt16(x.GetUnderlyingArray(), 1);
ushort yId = BitConverter.ToUInt16(y.GetUnderlyingArray(), 1);
return xId.CompareTo(yId);
}
}
///
/// Tests IPv4 connectivity.
///
[TestMethod]
public void UdpIPv4ConnectionTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
listener.Start();
connection.Connect();
Assert.AreEqual(ConnectionState.Connected, connection.State);
Console.Write($"Client sent {connection.Statistics.TotalBytesSent} bytes ");
}
}
///
/// Tests IPv4 resilience to multiple hellos.
///
[TestMethod]
public void ConnectLikeAJerkTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
int connects = 0;
listener.NewConnection += (obj) =>
{
Interlocked.Increment(ref connects);
};
listener.Start();
socket.Bind(new IPEndPoint(IPAddress.Any, 0));
var bytes = new byte[2];
bytes[0] = (byte)UdpSendOption.Hello;
for (int i = 0; i < 10; ++i)
{
socket.SendTo(bytes, new IPEndPoint(IPAddress.Loopback, 4296));
}
Thread.Sleep(500);
Assert.AreEqual(0, listener.ReceiveQueueLength);
Assert.IsTrue(connects <= 1, $"Too many connections: {connects}");
}
}
///
/// Tests dual mode connectivity.
///
[TestMethod]
public void MixedConnectionTest()
{
using (ThreadLimitedUdpConnectionListener listener2 = this.CreateListener(4, new IPEndPoint(IPAddress.IPv6Any, 4296), new ConsoleLogger(true), IPMode.IPv6))
{
listener2.Start();
listener2.NewConnection += (evt) =>
{
Console.WriteLine($"Connection: {evt.Connection.EndPoint}");
};
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4296), new TestLogger()))
{
connection.Connect();
Assert.AreEqual(ConnectionState.Connected, connection.State);
}
using (UdpConnection connection2 = this.CreateConnection(new IPEndPoint(IPAddress.IPv6Loopback, 4296), new TestLogger(), IPMode.IPv6))
{
connection2.Connect();
Assert.AreEqual(ConnectionState.Connected, connection2.State);
}
}
}
///
/// Tests dual mode connectivity.
///
[TestMethod]
public void UdpIPv6ConnectionTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.IPv6Any, 4296), new TestLogger(), IPMode.IPv6))
{
listener.Start();
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4296), new TestLogger(), IPMode.IPv6))
{
connection.Connect();
}
}
}
///
/// Tests server to client unreliable communication on the UdpConnection.
///
[TestMethod]
public void UdpUnreliableServerToClientTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
TestHelper.RunServerToClientTest(listener, connection, 10, SendOption.None);
}
}
///
/// Tests server to client reliable communication on the UdpConnection.
///
[TestMethod]
public void UdpReliableServerToClientTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
TestHelper.RunServerToClientTest(listener, connection, 10, SendOption.Reliable);
}
}
///
/// Tests server to client unreliable communication on the UdpConnection.
///
[TestMethod]
public void UdpUnreliableClientToServerTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
TestHelper.RunClientToServerTest(listener, connection, 10, SendOption.None);
}
}
///
/// Tests server to client reliable communication on the UdpConnection.
///
[TestMethod]
public void UdpReliableClientToServerTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
TestHelper.RunClientToServerTest(listener, connection, 10, SendOption.Reliable);
}
}
///
/// Tests the keepalive functionality from the client,
///
[TestMethod]
public virtual void KeepAliveClientTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
listener.Start();
connection.Connect();
connection.KeepAliveInterval = 100;
Thread.Sleep(1050); //Enough time for ~10 keep alive packets
Assert.AreEqual(ConnectionState.Connected, connection.State);
Assert.IsTrue(
connection.Statistics.TotalBytesSent >= 30 &&
connection.Statistics.TotalBytesSent <= 50,
"Sent: " + connection.Statistics.TotalBytesSent
);
}
}
///
/// Tests the keepalive functionality from the client,
///
[TestMethod]
public void KeepAliveServerTest()
{
ManualResetEvent mutex = new ManualResetEvent(false);
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
UdpConnection client = null;
listener.NewConnection += delegate (NewConnectionEventArgs args)
{
client = (UdpConnection)args.Connection;
client.KeepAliveInterval = 100;
Thread timeoutThread = new Thread(() =>
{
Thread.Sleep(1050); //Enough time for ~10 keep alive packets
mutex.Set();
});
timeoutThread.Start();
};
listener.Start();
connection.Connect();
mutex.WaitOne();
Assert.AreEqual(ConnectionState.Connected, client.State);
Assert.IsTrue(
client.Statistics.TotalBytesSent >= 27 &&
client.Statistics.TotalBytesSent <= 50,
"Sent: " + client.Statistics.TotalBytesSent
);
}
}
///
/// Tests disconnection from the client.
///
[TestMethod]
public void ClientDisconnectTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
ManualResetEvent mutex = new ManualResetEvent(false);
ManualResetEvent mutex2 = new ManualResetEvent(false);
listener.NewConnection += delegate (NewConnectionEventArgs args)
{
args.Connection.Disconnected += delegate (object sender2, DisconnectedEventArgs args2)
{
mutex2.Set();
};
mutex.Set();
};
listener.Start();
connection.Connect();
mutex.WaitOne(1000);
Assert.AreEqual(ConnectionState.Connected, connection.State);
connection.Disconnect("Testing");
mutex2.WaitOne(1000);
Assert.AreEqual(ConnectionState.NotConnected, connection.State);
}
}
///
/// Tests disconnection from the server.
///
[TestMethod]
public void ServerDisconnectTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
SemaphoreSlim mutex = new SemaphoreSlim(0, 100);
ManualResetEventSlim serverMutex = new ManualResetEventSlim(false);
connection.Disconnected += delegate (object sender, DisconnectedEventArgs args)
{
mutex.Release();
};
listener.NewConnection += delegate (NewConnectionEventArgs args)
{
mutex.Release();
// This has to be on a new thread because the client will go straight from Connecting to NotConnected
ThreadPool.QueueUserWorkItem(_ =>
{
serverMutex.Wait(500);
args.Connection.Disconnect("Testing");
});
};
listener.Start();
connection.Connect();
mutex.Wait(500);
Assert.AreEqual(ConnectionState.Connected, connection.State);
serverMutex.Set();
mutex.Wait(500);
Assert.AreEqual(ConnectionState.NotConnected, connection.State);
}
}
///
/// Tests disconnection from the server.
///
[TestMethod]
public void ServerExtraDataDisconnectTest()
{
using (ThreadLimitedUdpConnectionListener listener = this.CreateListener(2, new IPEndPoint(IPAddress.Any, 4296), new TestLogger()))
using (UdpConnection connection = this.CreateConnection(new IPEndPoint(IPAddress.Loopback, 4296), new TestLogger()))
{
string received = null;
ManualResetEvent mutex = new ManualResetEvent(false);
connection.Disconnected += delegate (object sender, DisconnectedEventArgs args)
{
// We don't own the message, we have to read the string now
received = args.Message.ReadString();
mutex.Set();
};
listener.NewConnection += delegate (NewConnectionEventArgs args)
{
MessageWriter writer = MessageWriter.Get(SendOption.None);
writer.Write("Goodbye");
args.Connection.Disconnect("Testing", writer);
};
listener.Start();
connection.Connect();
mutex.WaitOne(5000);
Assert.IsNotNull(received);
Assert.AreEqual("Goodbye", received);
}
}
}
}