You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
11 KiB
C#
265 lines
11 KiB
C#
1 week ago
|
using System;
|
||
|
using System.Collections;
|
||
|
using NUnit.Framework;
|
||
|
using Unity.BossRoom.Infrastructure;
|
||
|
using Unity.Netcode;
|
||
|
using UnityEngine;
|
||
|
using Unity.Netcode.TestHelpers.Runtime;
|
||
|
using UnityEngine.TestTools;
|
||
|
using VContainer;
|
||
|
using Assert = UnityEngine.Assertions.Assert;
|
||
|
|
||
|
namespace Unity.BossRoom.Tests.Runtime
|
||
|
{
|
||
|
public class NetworkedMessageChannelTests : NetcodeIntegrationTest
|
||
|
{
|
||
|
struct EmptyMessage : INetworkSerializeByMemcpy { }
|
||
|
|
||
|
struct GenericMessage : INetworkSerializeByMemcpy
|
||
|
{
|
||
|
public bool value;
|
||
|
}
|
||
|
|
||
|
protected override int NumberOfClients => 2;
|
||
|
|
||
|
DisposableGroup m_Subscriptions;
|
||
|
|
||
|
IObjectResolver[] m_ClientScopes;
|
||
|
IObjectResolver m_ServerScope;
|
||
|
|
||
|
int m_NbMessagesReceived;
|
||
|
|
||
|
protected override IEnumerator OnSetup()
|
||
|
{
|
||
|
m_NbMessagesReceived = 0;
|
||
|
return base.OnSetup();
|
||
|
}
|
||
|
|
||
|
protected override void OnServerAndClientsCreated()
|
||
|
{
|
||
|
m_ClientScopes = new IObjectResolver[NumberOfClients];
|
||
|
for (int i = 0; i < NumberOfClients; i++)
|
||
|
{
|
||
|
var clientBuilder = new ContainerBuilder();
|
||
|
clientBuilder.RegisterInstance(m_ClientNetworkManagers[i]);
|
||
|
m_ClientScopes[i] = clientBuilder.Build();
|
||
|
m_ClientNetworkManagers[i].NetworkConfig.EnableSceneManagement = false;
|
||
|
}
|
||
|
|
||
|
var serverBuilder = new ContainerBuilder();
|
||
|
serverBuilder.RegisterInstance(m_ServerNetworkManager);
|
||
|
m_ServerScope = serverBuilder.Build();
|
||
|
m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = false;
|
||
|
|
||
|
base.OnServerAndClientsCreated();
|
||
|
}
|
||
|
|
||
|
protected override IEnumerator OnTearDown()
|
||
|
{
|
||
|
m_Subscriptions.Dispose();
|
||
|
for (int i = 0; i < NumberOfClients; i++)
|
||
|
{
|
||
|
m_ClientScopes[i].Dispose();
|
||
|
}
|
||
|
m_ServerScope.Dispose();
|
||
|
return base.OnTearDown();
|
||
|
}
|
||
|
|
||
|
void InitializeNetworkedMessageChannels<T>(int nbClients, int nbSubscribers, T expectedValue, out NetworkedMessageChannel<T>[] emptyMessageChannelClients, out NetworkedMessageChannel<T> emptyMessageChannelServer) where T : unmanaged, INetworkSerializeByMemcpy
|
||
|
{
|
||
|
emptyMessageChannelClients = new NetworkedMessageChannel<T>[nbClients];
|
||
|
for (int i = 0; i < nbClients; i++)
|
||
|
{
|
||
|
emptyMessageChannelClients[i] = new NetworkedMessageChannel<T>();
|
||
|
m_ClientScopes[i].Inject(emptyMessageChannelClients[i]);
|
||
|
}
|
||
|
|
||
|
emptyMessageChannelServer = new NetworkedMessageChannel<T>();
|
||
|
m_ServerScope.Inject(emptyMessageChannelServer);
|
||
|
|
||
|
m_Subscriptions = new DisposableGroup();
|
||
|
for (int i = 0; i < nbClients; i++)
|
||
|
{
|
||
|
for (int j = 0; j < nbSubscribers; j++)
|
||
|
{
|
||
|
var numClient = i;
|
||
|
var numSub = j;
|
||
|
m_Subscriptions.Add(emptyMessageChannelClients[i].Subscribe(message =>
|
||
|
{
|
||
|
Debug.Log($"Received message on client {numClient} in subscription {numSub}.");
|
||
|
m_NbMessagesReceived++;
|
||
|
Assert.AreEqual(expectedValue, message, "Message received with unexpected value.");
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (int j = 0; j < nbSubscribers; j++)
|
||
|
{
|
||
|
var numSub = j;
|
||
|
m_Subscriptions.Add(emptyMessageChannelServer.Subscribe(message =>
|
||
|
{
|
||
|
Debug.Log($"Received message on server in subscription {numSub}.");
|
||
|
m_NbMessagesReceived++;
|
||
|
Assert.AreEqual(expectedValue, message, "Message received with unexpected value.");
|
||
|
}));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator EmptyNetworkedMessageIsReceivedByAllSubscribersOnAllClientsAndServer([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual((nbClients + 1) * nbSubscribers, m_NbMessagesReceived);
|
||
|
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessageContentIsProperlyReceivedOnAllClientsAndServer([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new GenericMessage() { value = true }, out var genericMessageChannelClients, out var genericMessageChannelServer);
|
||
|
|
||
|
genericMessageChannelServer.Publish(new GenericMessage() { value = true });
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the client
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual((nbClients + 1) * nbSubscribers, m_NbMessagesReceived);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessagesAreStillReceivedAfterNetworkManagerShutsDownAndRestarts([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual((nbClients + 1) * nbSubscribers, m_NbMessagesReceived);
|
||
|
|
||
|
m_NbMessagesReceived = 0;
|
||
|
|
||
|
m_PlayerPrefab.SetActive(false); // to prevent NM from destroying the prefab on shutdown. This flow isn't great and is hackish, should be reworked
|
||
|
// Shutdown the server and clients
|
||
|
m_ServerNetworkManager.Shutdown();
|
||
|
m_ClientNetworkManagers[0].Shutdown();
|
||
|
m_ClientNetworkManagers[1].Shutdown();
|
||
|
|
||
|
yield return new WaitWhile(() => m_ServerNetworkManager.ShutdownInProgress);
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[0].ShutdownInProgress);
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[1].ShutdownInProgress);
|
||
|
|
||
|
m_PlayerPrefab.SetActive(true); // reactivating after destroy prevention
|
||
|
|
||
|
// Restart the server and clients
|
||
|
m_ServerNetworkManager.StartHost();
|
||
|
NetcodeIntegrationTestHelpers.StartOneClient(m_ClientNetworkManagers[0]);
|
||
|
NetcodeIntegrationTestHelpers.StartOneClient(m_ClientNetworkManagers[1]);
|
||
|
|
||
|
yield return WaitForClientsConnectedOrTimeOut();
|
||
|
|
||
|
// Test sending a message a second time
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual((nbClients + 1) * nbSubscribers, m_NbMessagesReceived);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessagesAreReceivedIfClientsSubscribeBeforeConnecting([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
// Shutdown the clients
|
||
|
NetcodeIntegrationTestHelpers.StopOneClient(m_ClientNetworkManagers[0], false);
|
||
|
NetcodeIntegrationTestHelpers.StopOneClient(m_ClientNetworkManagers[1], false);
|
||
|
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[0].ShutdownInProgress);
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[1].ShutdownInProgress);
|
||
|
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
// Restart the clients
|
||
|
NetcodeIntegrationTestHelpers.StartOneClient(m_ClientNetworkManagers[0]);
|
||
|
NetcodeIntegrationTestHelpers.StartOneClient(m_ClientNetworkManagers[1]);
|
||
|
|
||
|
yield return WaitForClientsConnectedOrTimeOut();
|
||
|
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual((nbClients + 1) * nbSubscribers, m_NbMessagesReceived);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessagesAreNotReceivedWhenClientsAreShutDown([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
// Shutdown the clients
|
||
|
NetcodeIntegrationTestHelpers.StopOneClient(m_ClientNetworkManagers[0], false);
|
||
|
NetcodeIntegrationTestHelpers.StopOneClient(m_ClientNetworkManagers[1], false);
|
||
|
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[0].ShutdownInProgress);
|
||
|
yield return new WaitWhile(() => m_ClientNetworkManagers[1].ShutdownInProgress);
|
||
|
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual(nbSubscribers, m_NbMessagesReceived);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessagesAreNotReceivedWhenServerIsShutDown([Values(0, 1, 2)] int nbClients, [Values(0, 1, 2)] int nbSubscribers)
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(nbClients, nbSubscribers, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
// Shutdown the server
|
||
|
NetcodeIntegrationTestHelpers.StopOneClient(m_ServerNetworkManager, false);
|
||
|
|
||
|
yield return new WaitWhile(() => m_ServerNetworkManager.ShutdownInProgress);
|
||
|
|
||
|
LogAssert.Expect(LogType.Error, "Only a server can publish in a NetworkedMessageChannel");
|
||
|
emptyMessageChannelServer.Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual(0, m_NbMessagesReceived);
|
||
|
}
|
||
|
|
||
|
[UnityTest]
|
||
|
public IEnumerator NetworkedMessagesCannotBePublishedFromClient()
|
||
|
{
|
||
|
InitializeNetworkedMessageChannels(2, 1, new EmptyMessage(), out var emptyMessageChannelClients, out var emptyMessageChannelServer);
|
||
|
|
||
|
LogAssert.Expect(LogType.Error, "Only a server can publish in a NetworkedMessageChannel");
|
||
|
emptyMessageChannelClients[0].Publish(new EmptyMessage());
|
||
|
|
||
|
// wait for the custom named message to be sent on the server and received on the clients
|
||
|
yield return null;
|
||
|
yield return null;
|
||
|
|
||
|
Assert.AreEqual(0, m_NbMessagesReceived);
|
||
|
}
|
||
|
}
|
||
|
}
|