using System; using System.Collections; using System.Collections.Generic; using NUnit.Framework; using Unity.Collections; using Unity.Netcode.TestHelpers.Runtime; using UnityEngine.TestTools; namespace Unity.Netcode.RuntimeTests { internal class NamedMessageTests : NetcodeIntegrationTest { protected override int NumberOfClients => 2; private NetworkManager FirstClient => m_ClientNetworkManagers[0]; private NetworkManager SecondClient => m_ClientNetworkManagers[1]; protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() { // Don't spin up and shutdown NetworkManager instances for each test // within this set of integration tests. return NetworkManagerInstatiationMode.AllTests; } [UnityTest] public IEnumerator NamedMessageIsReceivedOnClientWithContent() { var messageName = Guid.NewGuid().ToString(); ulong receivedMessageSender = 0; var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { receivedMessageSender = sender; reader.ReadValueSafe(out receivedMessageContent); }); var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); var writer = new FastBufferWriter(1300, Allocator.Temp); using (writer) { writer.WriteValueSafe(messageContent); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( messageName, FirstClient.LocalClientId, writer); } yield return WaitForMessageReceived(new List { FirstClient }); Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); } [Test] public void NamedMessageIsReceivedOnHostWithContent() { var messageName = Guid.NewGuid().ToString(); ulong receivedMessageSender = 0; var receivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { receivedMessageSender = sender; reader.ReadValueSafe(out receivedMessageContent); }); var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); var writer = new FastBufferWriter(1300, Allocator.Temp); using (writer) { writer.WriteValueSafe(messageContent); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( messageName, m_ServerNetworkManager.LocalClientId, writer); } Assert.AreEqual(messageContent.Value, receivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender); } private void MockNamedMessageCallback(ulong sender, FastBufferReader reader) { } [Test] public void NullOrEmptyNamedMessageDoesNotThrowException() { LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.RegisterNamedMessageHandler)}] Cannot register a named message of type null or empty!"); m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(string.Empty, MockNamedMessageCallback); LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.RegisterNamedMessageHandler)}] Cannot register a named message of type null or empty!"); m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(null, MockNamedMessageCallback); LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.UnregisterNamedMessageHandler)}] Cannot unregister a named message of type null or empty!"); m_ServerNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(string.Empty); LogAssert.Expect(UnityEngine.LogType.Error, $"[{nameof(CustomMessagingManager.UnregisterNamedMessageHandler)}] Cannot unregister a named message of type null or empty!"); m_ServerNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(null); } [UnityTest] public IEnumerator NamedMessageIsReceivedOnMultipleClientsWithContent() { var messageName = Guid.NewGuid().ToString(); ulong firstReceivedMessageSender = 0; var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { firstReceivedMessageSender = sender; reader.ReadValueSafe(out firstReceivedMessageContent); }); ulong secondReceivedMessageSender = 0; var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); SecondClient.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { secondReceivedMessageSender = sender; reader.ReadValueSafe(out secondReceivedMessageContent); }); ulong thirdReceivedMessageSender = 0; var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { thirdReceivedMessageSender = sender; reader.ReadValueSafe(out thirdReceivedMessageContent); }); var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); var writer = new FastBufferWriter(1300, Allocator.Temp); using (writer) { writer.WriteValueSafe(messageContent); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage( messageName, new List { m_ServerNetworkManager.LocalClientId, FirstClient.LocalClientId, SecondClient.LocalClientId }, writer); } yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); } [UnityTest] public IEnumerator WhenSendingNamedMessageToAll_AllClientsReceiveIt() { var messageName = Guid.NewGuid().ToString(); ulong firstReceivedMessageSender = 0; var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); FirstClient.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { firstReceivedMessageSender = sender; reader.ReadValueSafe(out firstReceivedMessageContent); }); ulong secondReceivedMessageSender = 0; var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); SecondClient.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { secondReceivedMessageSender = sender; reader.ReadValueSafe(out secondReceivedMessageContent); }); ulong thirdReceivedMessageSender = 0; var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy(new Guid()); m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler( messageName, (ulong sender, FastBufferReader reader) => { thirdReceivedMessageSender = sender; reader.ReadValueSafe(out thirdReceivedMessageContent); }); var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); var writer = new FastBufferWriter(1300, Allocator.Temp); using (writer) { writer.WriteValueSafe(messageContent); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessageToAll(messageName, writer); } yield return WaitForMessageReceived(new List { FirstClient, SecondClient }); Assert.AreEqual(messageContent.Value, firstReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, firstReceivedMessageSender); Assert.AreEqual(messageContent.Value, secondReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, secondReceivedMessageSender); Assert.AreEqual(messageContent.Value, thirdReceivedMessageContent.Value); Assert.AreEqual(m_ServerNetworkManager.LocalClientId, thirdReceivedMessageSender); } [Test] public void WhenSendingNamedMessageToNullClientList_ArgumentNullExceptionIsThrown() { var messageName = Guid.NewGuid().ToString(); var messageContent = new ForceNetworkSerializeByMemcpy(Guid.NewGuid()); var writer = new FastBufferWriter(1300, Allocator.Temp); using (writer) { writer.WriteValueSafe(messageContent); Assert.Throws( () => { m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, null, writer); }); } } [Test] public unsafe void ErrorMessageIsPrintedWhenAttemptingToSendNamedMessageWithTooBigBuffer() { // First try a valid send with the maximum allowed size (this is atm 1264) var msgSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize - FastBufferWriter.GetWriteSize() - sizeof(ulong)/*MessageName hash*/ - sizeof(NetworkBatchHeader); var bufferSize = m_ServerNetworkManager.MessageManager.NonFragmentedMessageMaxSize; var messageName = Guid.NewGuid().ToString(); var messageContent = new byte[msgSize]; var writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); using (writer) { writer.TryBeginWrite(msgSize); writer.WriteBytes(messageContent, msgSize, 0); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, new List { FirstClient.LocalClientId }, writer); m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, FirstClient.LocalClientId, writer); } msgSize++; messageContent = new byte[msgSize]; writer = new FastBufferWriter(bufferSize, Allocator.Temp, bufferSize * 2); using (writer) { writer.TryBeginWrite(msgSize); writer.WriteBytes(messageContent, msgSize, 0); var message = Assert.Throws( () => { m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, new List { FirstClient.LocalClientId }, writer); }).Message; Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); message = Assert.Throws( () => { m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(messageName, FirstClient.LocalClientId, writer); }).Message; Assert.IsTrue(message.Contains($"Given message size ({msgSize} bytes) is greater than the maximum"), $"Unexpected exception: {message}"); } } } }