diff --git a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs index ab53839f2e..c14fbaf1af 100644 --- a/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs +++ b/com.unity.multiplayer.transport.utp/Runtime/UTPTransport.cs @@ -367,6 +367,11 @@ private void Update() } + private void OnDestroy() + { + DisposeDriver(); + } + private static unsafe ulong ParseClientId(NetworkConnection utpConnectionId) { return *(ulong*)&utpConnectionId; @@ -397,9 +402,7 @@ public override void DisconnectLocalClient() public override void DisconnectRemoteClient(ulong clientId) { - Debug.Assert(m_State == State.Connected, "DisconnectRemoteClient should be called on a listening server"); - - Debug.Log("Disconnecting"); + Debug.Assert(m_State == State.Listening, "DisconnectRemoteClient should be called on a listening server"); if (m_State == State.Listening) { @@ -474,24 +477,22 @@ public override void Send(ulong clientId, ArraySegment data, NetworkChanne Debug.LogError("Error sending the message"); } - public override void Shutdown() - { - DisposeDriver(); - } - public override SocketTasks StartClient() { - var task = SocketTask.Working; + if (m_Driver.IsCreated) + return SocketTask.Fault.AsTasks(); + var task = SocketTask.Working; StartCoroutine(ClientBindAndConnect(task)); - return task.AsTasks(); } public override SocketTasks StartServer() { - var task = SocketTask.Working; + if (m_Driver.IsCreated) + return SocketTask.Fault.AsTasks(); + var task = SocketTask.Working; switch (m_ProtocolType) { case ProtocolType.UnityTransport: @@ -501,8 +502,12 @@ public override SocketTasks StartServer() StartCoroutine(StartRelayServer(task)); break; } - return task.AsTasks(); } + + public override void Shutdown() + { + DisposeDriver(); + } } } diff --git a/com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs b/com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs deleted file mode 100644 index 40fabf1933..0000000000 --- a/com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.TestTools; -using NUnit.Framework; -using Unity.Networking.Transport; -using MLAPI.Transports; - -namespace MLAPI.UTP.RuntimeTests -{ - public class BasicUTPTest : MonoBehaviour - { - [Test] - public void BasicUTPInitializationTest() - { - var o = new GameObject(); - var utpTransport = (UTPTransport)o.AddComponent(typeof(UTPTransport)); - utpTransport.Init(); - - Assert.True(utpTransport.ServerClientId == 0); - - utpTransport.Shutdown(); - } - } -} - - diff --git a/com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs b/com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs new file mode 100644 index 0000000000..dbfabf0dfa --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs @@ -0,0 +1,97 @@ +using NUnit.Framework; + +using MLAPI.Transports; +using MLAPI.Transports.Tasks; +using Unity.Networking.Transport; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.UTP.EditorTests +{ + public class UTPTransportTests + { + // Check that starting a server doesn't immediately result in faulted tasks. + [Test] + public void BasicInitServer() + { + UTPTransport transport = new GameObject().AddComponent(); + transport.Init(); + + var tasks = transport.StartServer(); + Assert.False(tasks.IsDone && !tasks.Success); + + transport.Shutdown(); + } + + // Check that starting a client doesn't immediately result in faulted tasks. + [Test] + public void BasicInitClient() + { + UTPTransport transport = new GameObject().AddComponent(); + transport.Init(); + + var tasks = transport.StartClient(); + Assert.False(tasks.IsDone && !tasks.Success); + + transport.Shutdown(); + } + + // Check that we can't restart a server. + [Test] + public void NoRestartServer() + { + UTPTransport transport = new GameObject().AddComponent(); + transport.Init(); + + transport.StartServer(); + var tasks = transport.StartServer(); + Assert.True(tasks.IsDone && !tasks.AnySuccess); + + transport.Shutdown(); + } + + // Check that we can't restart a client. + [Test] + public void NoRestartClient() + { + UTPTransport transport = new GameObject().AddComponent(); + transport.Init(); + + transport.StartClient(); + var tasks = transport.StartClient(); + Assert.True(tasks.IsDone && !tasks.AnySuccess); + + transport.Shutdown(); + } + + // Check that we can't start both a server and client on the same transport. + [Test] + public void NotBothServerAndClient() + { + UTPTransport transport; + SocketTasks tasks; + + // Start server then client. + transport = new GameObject().AddComponent(); + transport.Init(); + + transport.StartServer(); + tasks = transport.StartClient(); + Assert.True(tasks.IsDone && !tasks.AnySuccess); + + transport.Shutdown(); + + // Start client then server. + transport = new GameObject().AddComponent(); + transport.Init(); + + transport.StartClient(); + tasks = transport.StartServer(); + Assert.True(tasks.IsDone && !tasks.AnySuccess); + + transport.Shutdown(); + } + } +} + + diff --git a/com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs.meta b/com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs.meta similarity index 83% rename from com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs.meta rename to com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs.meta index b984108d7f..0f68020ec5 100644 --- a/com.unity.multiplayer.transport.utp/Tests/Editor/BasicUTPTest.cs.meta +++ b/com.unity.multiplayer.transport.utp/Tests/Editor/UTPTransportTests.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4d51a9ee9a7131d47acc9ecb8c99dd65 +guid: 1559305d14837ed449c15c194aff6e6b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs b/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs new file mode 100644 index 0000000000..b88f5d92ce --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs @@ -0,0 +1,292 @@ +using NUnit.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using MLAPI.Transports; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.UTP.RuntimeTests +{ + using static RuntimeTestsHelpers; + + public class ConnectionTests + { + // For tests using multiple clients. + private const int NumClients = 5; + + // Check connection with a single client. + [UnityTest] + public IEnumerator ConnectSingleClient() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + // Check we've received Connect event on client too. + Assert.AreEqual(1, clientEvents.Count); + Assert.AreEqual(NetworkEvent.Connect, clientEvents[0].Type); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check connection with multiple clients. + [UnityTest] + public IEnumerator ConnectMultipleClients() + { + UTPTransport server; + var clients = new UTPTransport[NumClients]; + + List serverEvents; + var clientsEvents = new List[NumClients]; + + InitializeTransport(out server, out serverEvents); + server.StartServer(); + + for (int i = 0; i < NumClients; i++) + { + InitializeTransport(out clients[i], out clientsEvents[i]); + clients[i].StartClient(); + } + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + // Check that every client also received a Connect event. + Assert.True(clientsEvents.All(evs => evs.Count == 1)); + Assert.True(clientsEvents.All(evs => evs[0].Type == NetworkEvent.Connect)); + + server.Shutdown(); + for (int i = 0; i < NumClients; i++) + clients[i].Shutdown(); + + yield return null; + } + + // Check server disconnection with a single client. + [UnityTest] + public IEnumerator ServerDisconnectSingleClient() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + server.DisconnectRemoteClient(serverEvents[0].ClientID); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, clientEvents); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check server disconnection with multiple clients. + [UnityTest] + public IEnumerator ServerDisconnectMultipleClients() + { + UTPTransport server; + var clients = new UTPTransport[NumClients]; + + List serverEvents; + var clientsEvents = new List[NumClients]; + + InitializeTransport(out server, out serverEvents); + server.StartServer(); + + for (int i = 0; i < NumClients; i++) + { + InitializeTransport(out clients[i], out clientsEvents[i]); + clients[i].StartClient(); + } + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + // Disconnect a single client. + server.DisconnectRemoteClient(serverEvents[0].ClientID); + + // Need to manually wait since we don't know which client will get the Disconnect. + yield return new WaitForSeconds(MaxNetworkEventWaitTime); + + // Check that we received a Disconnect event on only one client. + Assert.AreEqual(1, clientsEvents.Count(evs => evs.Count == 2 && evs[1].Type == NetworkEvent.Disconnect)); + + // Disconnect all the other clients. + for (int i = 1; i < NumClients; i++) + server.DisconnectRemoteClient(serverEvents[i].ClientID); + + // Need to manually wait since we don't know which client will got the Disconnect. + yield return new WaitForSeconds(MaxNetworkEventWaitTime); + + // Check that all clients got a Disconnect event. + Assert.True(clientsEvents.All(evs => evs.Count == 2)); + Assert.True(clientsEvents.All(evs => evs[1].Type == NetworkEvent.Disconnect)); + + server.Shutdown(); + for (int i = 0; i < NumClients; i++) + clients[i].Shutdown(); + + yield return null; + } + + // Check client disconnection from a single client. + [UnityTest] + public IEnumerator ClientDisconnectSingleClient() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + client.DisconnectLocalClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, serverEvents); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check client disconnection with multiple clients. + [UnityTest] + public IEnumerator ClientDisconnectMultipleClients() + { + UTPTransport server; + var clients = new UTPTransport[NumClients]; + + List serverEvents; + var clientsEvents = new List[NumClients]; + + InitializeTransport(out server, out serverEvents); + server.StartServer(); + + for (int i = 0; i < NumClients; i++) + { + InitializeTransport(out clients[i], out clientsEvents[i]); + clients[i].StartClient(); + } + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + // Disconnect a single client. + clients[0].DisconnectLocalClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, serverEvents); + + // Disconnect all the other clients. + for (int i = 1; i < NumClients; i++) + clients[i].DisconnectLocalClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, serverEvents); + + // Check that we got the correct number of Disconnect events on the server. + Assert.AreEqual(NumClients * 2, serverEvents.Count); + Assert.AreEqual(NumClients, serverEvents.Count(e => e.Type == NetworkEvent.Disconnect)); + + server.Shutdown(); + for (int i = 0; i < NumClients; i++) + clients[i].Shutdown(); + + yield return null; + } + + // Check that server re-disconnects are no-ops. + [UnityTest] + public IEnumerator RepeatedServerDisconnectsNoop() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + server.DisconnectRemoteClient(serverEvents[0].ClientID); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, clientEvents); + + var previousServerEventsCount = serverEvents.Count; + var previousClientEventsCount = clientEvents.Count; + + server.DisconnectRemoteClient(serverEvents[0].ClientID); + + // Need to wait manually since no event should be generated. + yield return new WaitForSeconds(MaxNetworkEventWaitTime); + + // Check we haven't received anything else on the client or server. + Assert.AreEqual(serverEvents.Count, previousServerEventsCount); + Assert.AreEqual(clientEvents.Count, previousClientEventsCount); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check that client re-disconnects are no-ops. + [UnityTest] + public IEnumerator RepeatedClientDisconnectsNoop() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + client.DisconnectLocalClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Disconnect, serverEvents); + + var previousServerEventsCount = serverEvents.Count; + var previousClientEventsCount = clientEvents.Count; + + client.DisconnectLocalClient(); + + // Need to wait manually since no event should be generated. + yield return new WaitForSeconds(MaxNetworkEventWaitTime); + + // Check we haven't received anything else on the client or server. + Assert.AreEqual(serverEvents.Count, previousServerEventsCount); + Assert.AreEqual(clientEvents.Count, previousClientEventsCount); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + } +} diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs.meta b/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs.meta new file mode 100644 index 0000000000..18635a6b14 --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/ConnectionTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1692ce08a2f72e459680dc1524327a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers.meta b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers.meta new file mode 100644 index 0000000000..27015e3540 --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc69b0a277c4d024eb9f7813ad4db7d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs new file mode 100644 index 0000000000..298f812fe8 --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs @@ -0,0 +1,85 @@ +using NUnit.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using MLAPI.Transports; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.UTP.RuntimeTests +{ + public static class RuntimeTestsHelpers + { + // 50ms should be plenty enough for any network interaction to occur (even roundtrips). + public const float MaxNetworkEventWaitTime = 0.05f; + + // Wait for an event to appear in the given event list (must be the very next event). + public static IEnumerator WaitForNetworkEvent(NetworkEvent type, List events) + { + int initialCount = events.Count; + float startTime = Time.realtimeSinceStartup; + + while (Time.realtimeSinceStartup - startTime < MaxNetworkEventWaitTime) + { + if (events.Count > initialCount) + { + Assert.AreEqual(type, events[initialCount].Type); + yield break; + } + + yield return null; + } + + Assert.Fail("Timed out while waiting for network event."); + } + + // Common code to initialize a UTPTransport that logs its events. + public static void InitializeTransport(out UTPTransport transport, out List events) + { + var logger = new TransportEventLogger(); + events = logger.Events; + + transport = new GameObject().AddComponent(); + transport.OnTransportEvent += logger.HandleEvent; + transport.Init(); + } + + // Information about an event generated by a transport (basically just the parameters that + // are normally passed along to a TransportEventDelegate). + public struct TransportEvent + { + public NetworkEvent Type; + public ulong ClientID; + public NetworkChannel Channel; + public ArraySegment Data; + public float ReceiveTime; + } + + // Utility class that logs events generated by a UTPTransport. Set it up by adding the + // HandleEvent method as an OnTransportEvent delegate of the transport. The list of events + // (in order in which they were generated) can be accessed through the Events property. + public class TransportEventLogger + { + private readonly List m_Events = new List(); + public List Events => m_Events; + + public void HandleEvent(NetworkEvent type, ulong clientID, NetworkChannel channel, ArraySegment data, float receiveTime) + { + // Copy the data since the backing array will be reused for future messages. + if (data != default(ArraySegment)) + data = new ArraySegment(data.ToArray()); + + m_Events.Add(new TransportEvent + { + Type = type, + ClientID = clientID, + Channel = channel, + Data = data, + ReceiveTime = receiveTime + }); + } + } + } +} diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs.meta b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs.meta new file mode 100644 index 0000000000..9943be2562 --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/Helpers/RuntimeTestsHelpers.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9e62c313ec32744c810875f6738b767 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs b/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs new file mode 100644 index 0000000000..4990e46c2b --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs @@ -0,0 +1,216 @@ +using NUnit.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using MLAPI.Transports; +using UnityEngine; +using UnityEngine.TestTools; + +namespace MLAPI.UTP.RuntimeTests +{ + using static RuntimeTestsHelpers; + + public class TransportTests + { + // Check if can make a simple data exchange. + [UnityTest] + public IEnumerator PingPong() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + var ping = new ArraySegment(Encoding.ASCII.GetBytes("ping")); + client.Send(client.ServerClientId, ping, NetworkChannel.Internal); + + yield return WaitForNetworkEvent(NetworkEvent.Data, serverEvents); + + Assert.That(serverEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); + + var pong = new ArraySegment(Encoding.ASCII.GetBytes("pong")); + server.Send(serverEvents[0].ClientID, pong, NetworkChannel.Internal); + + yield return WaitForNetworkEvent(NetworkEvent.Data, clientEvents); + + Assert.That(clientEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check if can make a simple data exchange (both ways at a time). + [UnityTest] + public IEnumerator PingPongSimultaneous() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + var ping = new ArraySegment(Encoding.ASCII.GetBytes("ping")); + server.Send(serverEvents[0].ClientID, ping, NetworkChannel.Internal); + client.Send(client.ServerClientId, ping, NetworkChannel.Internal); + + // Once one event is in the other should be too. + yield return WaitForNetworkEvent(NetworkEvent.Data, serverEvents); + + Assert.That(serverEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); + Assert.That(clientEvents[1].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("ping"))); + + var pong = new ArraySegment(Encoding.ASCII.GetBytes("pong")); + server.Send(serverEvents[0].ClientID, pong, NetworkChannel.Internal); + client.Send(client.ServerClientId, pong, NetworkChannel.Internal); + + // Once one event is in the other should be too. + yield return WaitForNetworkEvent(NetworkEvent.Data, serverEvents); + + Assert.That(serverEvents[2].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); + Assert.That(clientEvents[2].Data, Is.EquivalentTo(Encoding.ASCII.GetBytes("pong"))); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check making multiple sends to a client in a single frame. + [UnityTest] + public IEnumerator MultipleSendsSingleFrame() + { + UTPTransport server, client; + List serverEvents, clientEvents; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client, out clientEvents); + + server.StartServer(); + client.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + var data1 = new ArraySegment(new byte [] { 11 }); + client.Send(client.ServerClientId, data1, NetworkChannel.Internal); + + var data2 = new ArraySegment(new byte [] { 22 }); + client.Send(client.ServerClientId, data2, NetworkChannel.Internal); + + yield return WaitForNetworkEvent(NetworkEvent.Data, serverEvents); + + Assert.AreEqual(3, serverEvents.Count); + Assert.AreEqual(NetworkEvent.Data, serverEvents[2].Type); + + Assert.AreEqual(11, serverEvents[1].Data.First()); + Assert.AreEqual(22, serverEvents[2].Data.First()); + + server.Shutdown(); + client.Shutdown(); + + yield return null; + } + + // Check sending data to multiple clients. + [UnityTest] + public IEnumerator SendMultipleClients() + { + UTPTransport server, client1, client2; + List serverEvents, client1Events, client2Events; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client1, out client1Events); + InitializeTransport(out client2, out client2Events); + + server.StartServer(); + client1.StartClient(); + client2.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, serverEvents); + + // Ensure we got both Connect events. + Assert.AreEqual(2, serverEvents.Count); + + var data1 = new ArraySegment(new byte [] { 11 }); + server.Send(serverEvents[0].ClientID, data1, NetworkChannel.Internal); + + var data2 = new ArraySegment(new byte [] { 22 }); + server.Send(serverEvents[1].ClientID, data2, NetworkChannel.Internal); + + // Once one has received its data, the other should have too. + yield return WaitForNetworkEvent(NetworkEvent.Data, client1Events); + + // Do make sure the other client got its Data event. + Assert.AreEqual(2, client2Events.Count); + Assert.AreEqual(NetworkEvent.Data, client2Events[1].Type); + + byte c1Data = client1Events[1].Data.First(); + byte c2Data = client2Events[1].Data.First(); + Assert.True((c1Data == 11 && c2Data == 22) || (c1Data == 22 && c2Data == 11)); + + server.Shutdown(); + client1.Shutdown(); + client2.Shutdown(); + + yield return null; + } + + // Check receiving data from multiple clients. + [UnityTest] + public IEnumerator ReceiveMultipleClients() + { + UTPTransport server, client1, client2; + List serverEvents, client1Events, client2Events; + + InitializeTransport(out server, out serverEvents); + InitializeTransport(out client1, out client1Events); + InitializeTransport(out client2, out client2Events); + + server.StartServer(); + client1.StartClient(); + client2.StartClient(); + + yield return WaitForNetworkEvent(NetworkEvent.Connect, client1Events); + + // Ensure we got the Connect event on the other client too. + Assert.AreEqual(1, client2Events.Count); + + var data1 = new ArraySegment(new byte [] { 11 }); + client1.Send(client1.ServerClientId, data1, NetworkChannel.Internal); + + var data2 = new ArraySegment(new byte [] { 22 }); + client2.Send(client2.ServerClientId, data2, NetworkChannel.Internal); + + yield return WaitForNetworkEvent(NetworkEvent.Data, serverEvents); + + // Make sure we got both data messages. + Assert.AreEqual(4, serverEvents.Count); + Assert.AreEqual(NetworkEvent.Data, serverEvents[3].Type); + + byte sData1 = serverEvents[2].Data.First(); + byte sData2 = serverEvents[3].Data.First(); + Assert.True((sData1 == 11 && sData2 == 22) || (sData1 == 22 && sData2 == 11)); + + server.Shutdown(); + client1.Shutdown(); + client2.Shutdown(); + + yield return null; + } + } +} diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs.meta b/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs.meta new file mode 100644 index 0000000000..6d81e3bad8 --- /dev/null +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/TransportTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c4fedf1be1a7d84ba34595aae75f8da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.multiplayer.transport.utp/Tests/Runtime/com.unity.multiplayer.transport.utp.runtimetests.asmdef b/com.unity.multiplayer.transport.utp/Tests/Runtime/com.unity.multiplayer.transport.utp.runtimetests.asmdef index 16811cc2b1..0683d67241 100644 --- a/com.unity.multiplayer.transport.utp/Tests/Runtime/com.unity.multiplayer.transport.utp.runtimetests.asmdef +++ b/com.unity.multiplayer.transport.utp/Tests/Runtime/com.unity.multiplayer.transport.utp.runtimetests.asmdef @@ -5,7 +5,7 @@ "Unity.Multiplayer.MLAPI.Runtime", "UnityEngine.TestRunner", "UnityEditor.TestRunner", - "Unity MLAPI Transport", + "Unity.Multiplayer.Transport.UTP", "Unity.Networking.Transport" ], "includePlatforms": [],