diff options
Diffstat (limited to 'Tools/Hazel-Networking/Hazel.UnitTests/UnityUdpConnectionTests.cs')
-rw-r--r-- | Tools/Hazel-Networking/Hazel.UnitTests/UnityUdpConnectionTests.cs | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/Tools/Hazel-Networking/Hazel.UnitTests/UnityUdpConnectionTests.cs b/Tools/Hazel-Networking/Hazel.UnitTests/UnityUdpConnectionTests.cs new file mode 100644 index 0000000..0745578 --- /dev/null +++ b/Tools/Hazel-Networking/Hazel.UnitTests/UnityUdpConnectionTests.cs @@ -0,0 +1,489 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Net; +using System.Threading; +using Hazel.Udp; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace Hazel.UnitTests +{ + [TestClass] + public class UnityUdpConnectionTests + { + private ILogger logger = new ConsoleLogger(true); + + [TestMethod] + public void ServerDisposeDisconnectsTest() + { + IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296); + + bool serverConnected = false; + bool serverDisconnected = false; + bool clientDisconnected = false; + + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, ep)) + { + 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 ClientServerDisposeDisconnectsTest() + { + IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296); + + bool serverConnected = false; + bool serverDisconnected = false; + bool clientDisconnected = false; + + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, ep)) + { + 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); + } + } + + /// <summary> + /// Tests the fields on UdpConnection. + /// </summary> + [TestMethod] + public void UdpFieldTest() + { + IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 4296); + + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, ep)) + { + 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 (ManualResetEventSlim mutex = new ManualResetEventSlim(false)) + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + listener.Start(); + + MessageReader output = null; + listener.NewConnection += delegate (NewConnectionEventArgs e) + { + output = e.HandshakeData.Duplicate(); + mutex.Set(); + }; + + connection.Connect(TestData); + mutex.Wait(5000); + + 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 (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + MessageReader output = null; + listener.NewConnection += delegate (NewConnectionEventArgs e) + { + e.Connection.DataReceived += delegate (DataReceivedEventArgs evt) + { + output = evt.Message; + }; + }; + + 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()); + } + } + } + + /// <summary> + /// Tests IPv4 connectivity. + /// </summary> + [TestMethod] + public void UdpIPv4ConnectionTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + listener.Start(); + + connection.Connect(); + } + } + + /// <summary> + /// Tests dual mode connectivity. + /// </summary> + [TestMethod] + public void MixedConnectionTest() + { + using (UdpConnectionListener listener2 = new UdpConnectionListener(new IPEndPoint(IPAddress.IPv6Any, 4296), IPMode.IPv6)) + { + listener2.Start(); + + listener2.NewConnection += (evt) => + { + Console.WriteLine("v6 connection: " + ((NetworkConnection)evt.Connection).GetIP4Address()); + }; + + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4296))) + { + connection.Connect(); + Assert.AreEqual(ConnectionState.Connected, connection.State); + } + + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.IPv6Loopback, 4296), IPMode.IPv6)) + { + connection.Connect(); + Assert.AreEqual(ConnectionState.Connected, connection.State); + } + } + } + + /// <summary> + /// Tests IPv4 resilience to non-hello connections. + /// </summary> + [TestMethod] + public void FalseConnectionTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + 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)32; + for (int i = 0; i < 10; ++i) + { + socket.SendTo(bytes, new IPEndPoint(IPAddress.Loopback, 4296)); + } + + Thread.Sleep(500); + + Assert.AreEqual(0, connects); + } + } + + /// <summary> + /// Tests IPv4 resilience to multiple hellos. + /// </summary> + [TestMethod] + public void ConnectLikeAJerkTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + 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(1, connects); + } + } + + /// <summary> + /// Tests dual mode connectivity. + /// </summary> + [TestMethod] + public void UdpIPv6ConnectionTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.IPv6Any, 4296), IPMode.IPv6)) + { + listener.Start(); + + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4296), IPMode.IPv6)) + { + connection.Connect(); + } + } + } + + /// <summary> + /// Tests server to client unreliable communication on the UdpConnection. + /// </summary> + [TestMethod] + public void UdpUnreliableServerToClientTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunServerToClientTest(listener, connection, 10, SendOption.None); + } + } + + /// <summary> + /// Tests server to client reliable communication on the UdpConnection. + /// </summary> + [TestMethod] + public void UdpReliableServerToClientTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunServerToClientTest(listener, connection, 10, SendOption.Reliable); + } + } + + /// <summary> + /// Tests server to client unreliable communication on the UdpConnection. + /// </summary> + [TestMethod] + public void UdpUnreliableClientToServerTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunClientToServerTest(listener, connection, 10, SendOption.None); + } + } + + /// <summary> + /// Tests server to client reliable communication on the UdpConnection. + /// </summary> + [TestMethod] + public void UdpReliableClientToServerTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunClientToServerTest(listener, connection, 10, SendOption.Reliable); + } + } + + /// <summary> + /// Tests the keepalive functionality from the client, + /// </summary> + [TestMethod] + public void KeepAliveClientTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + 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 + ); + } + } + + /// <summary> + /// Tests the keepalive functionality from the client, + /// </summary> + [TestMethod] + public void KeepAliveServerTest() + { + ManualResetEvent mutex = new ManualResetEvent(false); + + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + UdpConnection client = null; + listener.NewConnection += delegate (NewConnectionEventArgs args) + { + client = (UdpConnection)args.Connection; + client.KeepAliveInterval = 100; + + Thread.Sleep(1050); //Enough time for ~10 keep alive packets + + mutex.Set(); + }; + + 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 + ); + } + } + + /// <summary> + /// Tests disconnection from the client. + /// </summary> + [TestMethod] + public void ClientDisconnectTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunClientDisconnectTest(listener, connection); + } + } + + /// <summary> + /// Test that a disconnect is sent when the client is disposed. + /// </summary> + public void ClientDisconnectOnDisposeTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunClientDisconnectOnDisposeTest(listener, connection); + } + } + + /// <summary> + /// Tests disconnection from the server. + /// </summary> + [TestMethod] + public void ServerDisconnectTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + TestHelper.RunServerDisconnectTest(listener, connection); + } + } + + /// <summary> + /// Tests disconnection from the server. + /// </summary> + [TestMethod] + public void ServerExtraDataDisconnectTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, 4296))) + using (UdpConnection connection = new UnityUdpClientConnection(logger, new IPEndPoint(IPAddress.Loopback, 4296))) + { + 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) + { + // As it turns out, the UdpConnectionListener can have an issue on loopback where the disconnect can happen before the hello confirm + // Tossing it on a different thread makes this test more reliable. Perhaps something to think about elsewhere though. + Task.Run(async () => + { + await Task.Delay(1); + MessageWriter writer = MessageWriter.Get(SendOption.None); + writer.Write("Goodbye"); + args.Connection.Disconnect("Testing", writer); + }); + }; + + listener.Start(); + + connection.Connect(); + + mutex.WaitOne(); + + Assert.IsNotNull(received); + Assert.AreEqual("Goodbye", received); + } + } + } +} |