1013 lines
38 KiB
C#
1013 lines
38 KiB
C#
using System;
|
|
using System.Text.RegularExpressions;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
|
|
namespace Mirror.Tests
|
|
{
|
|
class StartServerNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
internal bool onStartServerInvoked;
|
|
public override void OnStartServer() => onStartServerInvoked = true;
|
|
}
|
|
|
|
class StartServerExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartServer()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StartClientExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartClient()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StartAuthorityExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartAuthority()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StartAuthorityCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartAuthority() => ++called;
|
|
}
|
|
|
|
class StopAuthorityExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopAuthority()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StopAuthorityCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopAuthority() => ++called;
|
|
}
|
|
|
|
class StartLocalPlayerExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartLocalPlayer()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StartLocalPlayerCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStartLocalPlayer() => ++called;
|
|
}
|
|
|
|
class StopClientExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopClient()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StopClientCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopClient() => ++called;
|
|
}
|
|
|
|
class StopLocalPlayerCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopLocalPlayer() => ++called;
|
|
}
|
|
|
|
class StopLocalPlayerExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopLocalPlayer()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class StopServerCalledNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopServer() => ++called;
|
|
}
|
|
|
|
class StopServerExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int called;
|
|
public override void OnStopServer()
|
|
{
|
|
++called;
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class SerializeTest1NetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int value;
|
|
public override bool OnSerialize(NetworkWriter writer, bool initialState)
|
|
{
|
|
writer.WriteInt(value);
|
|
return true;
|
|
}
|
|
public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|
{
|
|
value = reader.ReadInt();
|
|
}
|
|
}
|
|
|
|
class SerializeTest2NetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public string value;
|
|
public override bool OnSerialize(NetworkWriter writer, bool initialState)
|
|
{
|
|
writer.WriteString(value);
|
|
return true;
|
|
}
|
|
public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|
{
|
|
value = reader.ReadString();
|
|
}
|
|
}
|
|
|
|
class SerializeExceptionNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public override bool OnSerialize(NetworkWriter writer, bool initialState)
|
|
{
|
|
throw new Exception("some exception");
|
|
}
|
|
public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|
{
|
|
throw new Exception("some exception");
|
|
}
|
|
}
|
|
|
|
class SerializeMismatchNetworkBehaviour : NetworkBehaviour
|
|
{
|
|
public int value;
|
|
public override bool OnSerialize(NetworkWriter writer, bool initialState)
|
|
{
|
|
writer.WriteInt(value);
|
|
// one too many
|
|
writer.WriteInt(value);
|
|
return true;
|
|
}
|
|
public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|
{
|
|
value = reader.ReadInt();
|
|
}
|
|
}
|
|
|
|
class IsClientServerCheckComponent : NetworkBehaviour
|
|
{
|
|
// OnStartClient
|
|
internal bool OnStartClient_isClient;
|
|
internal bool OnStartClient_isServer;
|
|
internal bool OnStartClient_isLocalPlayer;
|
|
public override void OnStartClient()
|
|
{
|
|
OnStartClient_isClient = isClient;
|
|
OnStartClient_isServer = isServer;
|
|
OnStartClient_isLocalPlayer = isLocalPlayer;
|
|
}
|
|
|
|
// OnStartServer
|
|
internal bool OnStartServer_isClient;
|
|
internal bool OnStartServer_isServer;
|
|
internal bool OnStartServer_isLocalPlayer;
|
|
public override void OnStartServer()
|
|
{
|
|
OnStartServer_isClient = isClient;
|
|
OnStartServer_isServer = isServer;
|
|
OnStartServer_isLocalPlayer = isLocalPlayer;
|
|
}
|
|
|
|
// OnStartLocalPlayer
|
|
internal bool OnStartLocalPlayer_isClient;
|
|
internal bool OnStartLocalPlayer_isServer;
|
|
internal bool OnStartLocalPlayer_isLocalPlayer;
|
|
public override void OnStartLocalPlayer()
|
|
{
|
|
OnStartLocalPlayer_isClient = isClient;
|
|
OnStartLocalPlayer_isServer = isServer;
|
|
OnStartLocalPlayer_isLocalPlayer = isLocalPlayer;
|
|
}
|
|
|
|
// Start
|
|
internal bool Start_isClient;
|
|
internal bool Start_isServer;
|
|
internal bool Start_isLocalPlayer;
|
|
public void Start()
|
|
{
|
|
Start_isClient = isClient;
|
|
Start_isServer = isServer;
|
|
Start_isLocalPlayer = isLocalPlayer;
|
|
}
|
|
|
|
// OnDestroy
|
|
internal bool OnDestroy_isClient;
|
|
internal bool OnDestroy_isServer;
|
|
internal bool OnDestroy_isLocalPlayer;
|
|
public void OnDestroy()
|
|
{
|
|
OnDestroy_isClient = isClient;
|
|
OnDestroy_isServer = isServer;
|
|
OnDestroy_isLocalPlayer = isLocalPlayer;
|
|
}
|
|
}
|
|
|
|
public class NetworkIdentityTests : MirrorEditModeTest
|
|
{
|
|
[Test]
|
|
public void OnStartServerTest()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StartServerNetworkBehaviour component1, out StartServerNetworkBehaviour component2);
|
|
identity.OnStartServer();
|
|
|
|
Assert.That(component1.onStartServerInvoked);
|
|
Assert.That(component2.onStartServerInvoked);
|
|
}
|
|
|
|
// check isClient/isServer/isLocalPlayer in server-only mode
|
|
[Test]
|
|
public void ServerMode_IsFlags_Test()
|
|
{
|
|
CreateNetworked(out GameObject gameObject, out NetworkIdentity _, out IsClientServerCheckComponent component);
|
|
|
|
// start the server
|
|
NetworkServer.Listen(1000);
|
|
|
|
// spawn it
|
|
NetworkServer.Spawn(gameObject);
|
|
|
|
// OnStartServer should have been called. check the flags.
|
|
Assert.That(component.OnStartServer_isClient, Is.EqualTo(false));
|
|
Assert.That(component.OnStartServer_isLocalPlayer, Is.EqualTo(false));
|
|
Assert.That(component.OnStartServer_isServer, Is.EqualTo(true));
|
|
}
|
|
|
|
// check isClient/isServer/isLocalPlayer in host mode
|
|
[Test]
|
|
public void HostMode_IsFlags_Test()
|
|
{
|
|
CreateNetworked(out GameObject gameObject, out NetworkIdentity identity, out IsClientServerCheckComponent component);
|
|
|
|
// start the server
|
|
NetworkServer.Listen(1000);
|
|
|
|
// start the client
|
|
NetworkClient.ConnectHost();
|
|
|
|
// set is as local player
|
|
NetworkClient.InternalAddPlayer(identity);
|
|
|
|
// spawn it
|
|
NetworkServer.Spawn(gameObject);
|
|
|
|
// OnStartServer should have been called. check the flags.
|
|
Assert.That(component.OnStartServer_isClient, Is.EqualTo(true));
|
|
Assert.That(component.OnStartServer_isLocalPlayer, Is.EqualTo(true));
|
|
Assert.That(component.OnStartServer_isServer, Is.EqualTo(true));
|
|
|
|
// stop the client
|
|
NetworkServer.RemoveLocalConnection();
|
|
}
|
|
|
|
[Test]
|
|
public void GetSetAssetId()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// assign a guid
|
|
Guid guid = new Guid(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B);
|
|
identity.assetId = guid;
|
|
|
|
// did it work?
|
|
Assert.That(identity.assetId, Is.EqualTo(guid));
|
|
}
|
|
|
|
[Test]
|
|
public void SetAssetId_GivesErrorIfOneExists()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
if (identity.assetId == Guid.Empty)
|
|
{
|
|
identity.assetId = Guid.NewGuid();
|
|
}
|
|
|
|
Guid guid1 = identity.assetId;
|
|
|
|
// assign a guid
|
|
Guid guid2 = Guid.NewGuid();
|
|
LogAssert.Expect(LogType.Error, $"Can not Set AssetId on NetworkIdentity '{identity.name}' because it already had an assetId, current assetId '{guid1:N}', attempted new assetId '{guid2:N}'");
|
|
identity.assetId = guid2;
|
|
|
|
// guid was changed
|
|
Assert.That(identity.assetId, Is.EqualTo(guid1));
|
|
}
|
|
|
|
[Test]
|
|
public void SetAssetId_GivesErrorForEmptyGuid()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
if (identity.assetId == Guid.Empty)
|
|
{
|
|
identity.assetId = Guid.NewGuid();
|
|
}
|
|
|
|
Guid guid1 = identity.assetId;
|
|
|
|
// assign a guid
|
|
Guid guid2 = new Guid();
|
|
LogAssert.Expect(LogType.Error, $"Can not set AssetId to empty guid on NetworkIdentity '{identity.name}', old assetId '{guid1:N}'");
|
|
identity.assetId = guid2;
|
|
|
|
// guid was NOT changed
|
|
Assert.That(identity.assetId, Is.EqualTo(guid1));
|
|
}
|
|
|
|
[Test]
|
|
public void SetAssetId_DoesNotGiveErrorIfBothOldAndNewAreEmpty()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
Debug.Assert(identity.assetId == Guid.Empty, "assetId needs to be empty at the start of this test");
|
|
// assign a guid
|
|
Guid guid2 = new Guid();
|
|
// expect no errors
|
|
identity.assetId = guid2;
|
|
|
|
// guid was still empty
|
|
Assert.That(identity.assetId, Is.EqualTo(Guid.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void SetClientOwner()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// SetClientOwner
|
|
LocalConnectionToClient original = new LocalConnectionToClient();
|
|
identity.SetClientOwner(original);
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(original));
|
|
|
|
// setting it when it's already set shouldn't overwrite the original
|
|
LocalConnectionToClient overwrite = new LocalConnectionToClient();
|
|
// will log a warning
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.SetClientOwner(overwrite);
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(original));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
}
|
|
|
|
[Test]
|
|
public void RemoveObserver()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// call OnStartServer so that observers dict is created
|
|
identity.OnStartServer();
|
|
|
|
// add an observer connection
|
|
NetworkConnectionToClient connection = new NetworkConnectionToClient(42);
|
|
identity.observers[connection.connectionId] = connection;
|
|
|
|
// RemoveObserver with invalid connection should do nothing
|
|
identity.RemoveObserver(new NetworkConnectionToClient(43));
|
|
Assert.That(identity.observers.Count, Is.EqualTo(1));
|
|
|
|
// RemoveObserver with existing connection should remove it
|
|
identity.RemoveObserver(connection);
|
|
Assert.That(identity.observers.Count, Is.EqualTo(0));
|
|
}
|
|
|
|
[Test]
|
|
public void AssignSceneID()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// Awake will have assigned a random sceneId of format 0x00000000FFFFFFFF
|
|
// -> make sure that one was assigned, and that the left part was
|
|
// left empty for scene hash
|
|
Assert.That(identity.sceneId, !Is.Zero);
|
|
Assert.That(identity.sceneId & 0xFFFFFFFF00000000, Is.EqualTo(0x0000000000000000));
|
|
|
|
// make sure that Awake added it to sceneIds dict
|
|
Assert.That(NetworkIdentity.GetSceneIdentity(identity.sceneId), !Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void SetSceneIdSceneHashPartInternal()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// Awake will have assigned a random sceneId of format 0x00000000FFFFFFFF
|
|
// -> make sure that one was assigned, and that the left part was
|
|
// left empty for scene hash
|
|
Assert.That(identity.sceneId, !Is.Zero);
|
|
Assert.That(identity.sceneId & 0xFFFFFFFF00000000, Is.EqualTo(0x0000000000000000));
|
|
ulong rightPart = identity.sceneId;
|
|
|
|
// set scene hash
|
|
identity.SetSceneIdSceneHashPartInternal();
|
|
|
|
// make sure that the right part is still the random sceneid
|
|
Assert.That(identity.sceneId & 0x00000000FFFFFFFF, Is.EqualTo(rightPart));
|
|
|
|
// make sure that the left part is a scene hash now
|
|
Assert.That(identity.sceneId & 0xFFFFFFFF00000000, !Is.Zero);
|
|
ulong finished = identity.sceneId;
|
|
|
|
// calling it again should said the exact same hash again
|
|
identity.SetSceneIdSceneHashPartInternal();
|
|
Assert.That(identity.sceneId, Is.EqualTo(finished));
|
|
}
|
|
|
|
[Test]
|
|
public void OnValidateSetupIDsSetsEmptyAssetIDForSceneObject()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// OnValidate will have been called. make sure that assetId was set
|
|
// to 0 empty and not anything else, because this is a scene object
|
|
Assert.That(identity.assetId, Is.EqualTo(Guid.Empty));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStartServerCallsComponentsAndCatchesExceptions()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StartServerExceptionNetworkBehaviour comp);
|
|
|
|
// make sure that comp.OnStartServer was called and make sure that
|
|
// the exception was caught and not thrown in here.
|
|
// an exception in OnStartServer should be caught, so that one
|
|
// component's exception doesn't stop all other components from
|
|
// being initialized
|
|
// (an error log is expected though)
|
|
LogAssert.ignoreFailingMessages = true;
|
|
// should catch the exception internally and not throw it
|
|
identity.OnStartServer();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
}
|
|
|
|
[Test]
|
|
public void OnStartClientCallsComponentsAndCatchesExceptions()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StartClientExceptionNetworkBehaviour comp);
|
|
|
|
// make sure that comp.OnStartClient was called and make sure that
|
|
// the exception was caught and not thrown in here.
|
|
// an exception in OnStartClient should be caught, so that one
|
|
// component's exception doesn't stop all other components from
|
|
// being initialized
|
|
// (an error log is expected though)
|
|
LogAssert.ignoreFailingMessages = true;
|
|
// should catch the exception internally and not throw it
|
|
identity.OnStartClient();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
|
|
// we have checks to make sure that it's only called once.
|
|
// let's see if they work.
|
|
identity.OnStartClient();
|
|
// same as before?
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStartAuthorityCallsComponentsAndCatchesExceptions()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StartAuthorityExceptionNetworkBehaviour comp);
|
|
|
|
// make sure that comp.OnStartAuthority was called and make sure that
|
|
// the exception was caught and not thrown in here.
|
|
// an exception in OnStartAuthority should be caught, so that one
|
|
// component's exception doesn't stop all other components from
|
|
// being initialized
|
|
// (an error log is expected though)
|
|
LogAssert.ignoreFailingMessages = true;
|
|
// should catch the exception internally and not throw it
|
|
identity.OnStartAuthority();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopAuthorityCallsComponentsAndCatchesExceptions()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StopAuthorityExceptionNetworkBehaviour comp);
|
|
|
|
// make sure that comp.OnStopAuthority was called and make sure that
|
|
// the exception was caught and not thrown in here.
|
|
// an exception in OnStopAuthority should be caught, so that one
|
|
// component's exception doesn't stop all other components from
|
|
// being initialized
|
|
// (an error log is expected though)
|
|
LogAssert.ignoreFailingMessages = true;
|
|
// should catch the exception internally and not throw it
|
|
identity.OnStopAuthority();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
}
|
|
|
|
[Test]
|
|
public void AssignAndRemoveClientAuthority()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// test the callback too
|
|
int callbackCalled = 0;
|
|
NetworkConnection callbackConnection = null;
|
|
NetworkIdentity callbackIdentity = null;
|
|
bool callbackState = false;
|
|
NetworkIdentity.clientAuthorityCallback += (conn, networkIdentity, state) =>
|
|
{
|
|
++callbackCalled;
|
|
callbackConnection = conn;
|
|
callbackIdentity = identity;
|
|
callbackState = state;
|
|
};
|
|
|
|
// create connections
|
|
CreateLocalConnectionPair(out LocalConnectionToClient owner, out LocalConnectionToServer clientConnection);
|
|
owner.isReady = true;
|
|
|
|
// setup NetworkServer/Client connections so messages are handled
|
|
NetworkClient.connection = clientConnection;
|
|
NetworkServer.connections[owner.connectionId] = owner;
|
|
|
|
// add client handlers
|
|
int spawnCalled = 0;
|
|
void Handler(SpawnMessage _) => ++spawnCalled;
|
|
NetworkClient.RegisterHandler<SpawnMessage>(Handler, false);
|
|
|
|
// assigning authority should only work on server.
|
|
// if isServer is false because server isn't running yet then it
|
|
// should fail.
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
bool result = identity.AssignClientAuthority(owner);
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(result, Is.False);
|
|
|
|
// server is needed
|
|
NetworkServer.Listen(1);
|
|
|
|
// call OnStartServer so that isServer is true
|
|
identity.OnStartServer();
|
|
Assert.That(identity.isServer, Is.True);
|
|
|
|
// assign authority
|
|
result = identity.AssignClientAuthority(owner);
|
|
Assert.That(result, Is.True);
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
Assert.That(callbackConnection, Is.EqualTo(owner));
|
|
Assert.That(callbackIdentity, Is.EqualTo(identity));
|
|
Assert.That(callbackState, Is.EqualTo(true));
|
|
|
|
// shouldn't be able to assign authority while already owned by
|
|
// another connection
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
result = identity.AssignClientAuthority(new NetworkConnectionToClient(43));
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(result, Is.False);
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
|
|
// someone might try to remove authority by assigning null.
|
|
// make sure this fails.
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
result = identity.AssignClientAuthority(null);
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(result, Is.False);
|
|
|
|
// removing authority while not isServer shouldn't work.
|
|
// only allow it on server.
|
|
identity.isServer = false;
|
|
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.RemoveClientAuthority();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
|
|
// enable isServer again
|
|
identity.isServer = true;
|
|
|
|
// removing authority for the main player object shouldn't work
|
|
// set connection's player object
|
|
owner.identity = identity;
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.RemoveClientAuthority();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(identity.connectionToClient, Is.EqualTo(owner));
|
|
Assert.That(callbackCalled, Is.EqualTo(1));
|
|
|
|
// removing authority for a non-main-player object should work
|
|
owner.identity = null;
|
|
identity.RemoveClientAuthority();
|
|
Assert.That(identity.connectionToClient, Is.Null);
|
|
Assert.That(callbackCalled, Is.EqualTo(2));
|
|
// the one that was removed
|
|
Assert.That(callbackConnection, Is.EqualTo(owner));
|
|
Assert.That(callbackIdentity, Is.EqualTo(identity));
|
|
Assert.That(callbackState, Is.EqualTo(false));
|
|
}
|
|
|
|
[Test]
|
|
public void NotifyAuthorityCallsOnStartStopAuthority()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StartAuthorityCalledNetworkBehaviour compStart, out StopAuthorityCalledNetworkBehaviour compStop);
|
|
|
|
// set authority from false to true, which should call OnStartAuthority
|
|
identity.hasAuthority = true;
|
|
identity.NotifyAuthority();
|
|
// shouldn't be touched
|
|
Assert.That(identity.hasAuthority, Is.True);
|
|
// start should be called
|
|
Assert.That(compStart.called, Is.EqualTo(1));
|
|
// stop shouldn't
|
|
Assert.That(compStop.called, Is.EqualTo(0));
|
|
|
|
// set it to true again, should do nothing because already true
|
|
identity.hasAuthority = true;
|
|
identity.NotifyAuthority();
|
|
// shouldn't be touched
|
|
Assert.That(identity.hasAuthority, Is.True);
|
|
// same as before
|
|
Assert.That(compStart.called, Is.EqualTo(1));
|
|
// same as before
|
|
Assert.That(compStop.called, Is.EqualTo(0));
|
|
|
|
// set it to false, should call OnStopAuthority
|
|
identity.hasAuthority = false;
|
|
identity.NotifyAuthority();
|
|
// should be changed
|
|
Assert.That(identity.hasAuthority, Is.False);
|
|
// same as before
|
|
Assert.That(compStart.called, Is.EqualTo(1));
|
|
// stop should be called
|
|
Assert.That(compStop.called, Is.EqualTo(1));
|
|
|
|
// set it to false again, should do nothing because already false
|
|
identity.hasAuthority = false;
|
|
identity.NotifyAuthority();
|
|
// shouldn't be touched
|
|
Assert.That(identity.hasAuthority, Is.False);
|
|
// same as before
|
|
Assert.That(compStart.called, Is.EqualTo(1));
|
|
// same as before
|
|
Assert.That(compStop.called, Is.EqualTo(1));
|
|
}
|
|
|
|
// OnStartServer in host mode should set isClient=true
|
|
[Test]
|
|
public void OnStartServerInHostModeSetsIsClientTrue()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// call client connect so that internals are set up
|
|
// (it won't actually successfully connect)
|
|
NetworkClient.Connect("localhost");
|
|
|
|
// manually invoke transport.OnConnected so that NetworkClient.active is set to true
|
|
Transport.activeTransport.OnClientConnected.Invoke();
|
|
Assert.That(NetworkClient.active, Is.True);
|
|
|
|
// isClient needs to be true in OnStartServer if in host mode.
|
|
// this is a test for a bug that we fixed, where isClient was false
|
|
// in OnStartServer if in host mode because in host mode, we only
|
|
// connect the client after starting the server, hence isClient would
|
|
// be false in OnStartServer until way later.
|
|
// -> we have the workaround in OnStartServer, so let's also test to
|
|
// make sure that nobody ever breaks it again
|
|
Assert.That(identity.isClient, Is.False);
|
|
identity.OnStartServer();
|
|
Assert.That(identity.isClient, Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void CreatingNetworkBehavioursCacheShouldLogErrorForTooComponents()
|
|
{
|
|
CreateNetworked(out GameObject gameObject, out NetworkIdentity identity);
|
|
|
|
// add byte.MaxValue+1 components
|
|
for (int i = 0; i < byte.MaxValue + 1; ++i)
|
|
{
|
|
gameObject.AddComponent<SerializeTest1NetworkBehaviour>();
|
|
}
|
|
|
|
// CreateNetworked already initializes the components.
|
|
// let's reset and initialize again with the added ones.
|
|
identity.Reset();
|
|
identity.Awake();
|
|
|
|
// call NetworkBehaviours property to create the cache
|
|
LogAssert.Expect(LogType.Error, new Regex($"Only {byte.MaxValue} NetworkBehaviour components are allowed for NetworkIdentity.+"));
|
|
_ = identity.NetworkBehaviours;
|
|
}
|
|
|
|
[Test]
|
|
public void OnStartLocalPlayer()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StartLocalPlayerExceptionNetworkBehaviour compEx,
|
|
out StartLocalPlayerCalledNetworkBehaviour comp);
|
|
|
|
// make sure our test values are set to 0
|
|
Assert.That(compEx.called, Is.EqualTo(0));
|
|
Assert.That(comp.called, Is.EqualTo(0));
|
|
|
|
// call OnStartLocalPlayer in identity
|
|
// one component will throw an exception, but that shouldn't stop
|
|
// OnStartLocalPlayer from being called in the second one
|
|
// exception will log an error
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.OnStartLocalPlayer();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(compEx.called, Is.EqualTo(1));
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
|
|
// we have checks to make sure that it's only called once.
|
|
// let's see if they work.
|
|
identity.OnStartLocalPlayer();
|
|
// same as before?
|
|
Assert.That(compEx.called, Is.EqualTo(1));
|
|
// same as before?
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopLocalPlayer()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StopLocalPlayerCalledNetworkBehaviour comp);
|
|
|
|
// call OnStopLocalPlayer in identity
|
|
identity.OnStopLocalPlayer();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopLocalPlayerException()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StopLocalPlayerExceptionNetworkBehaviour compEx,
|
|
out StopLocalPlayerCalledNetworkBehaviour comp);
|
|
|
|
// call OnStopLocalPlayer in identity
|
|
// one component will throw an exception, but that shouldn't stop
|
|
// OnStopLocalPlayer from being called in the second one
|
|
// exception will log an error
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.OnStopLocalPlayer();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(compEx.called, Is.EqualTo(1));
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopClient()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StopClientCalledNetworkBehaviour comp);
|
|
|
|
// call OnStopClient in identity
|
|
identity.OnStopClient();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopClientException()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StopClientExceptionNetworkBehaviour compEx,
|
|
out StopClientCalledNetworkBehaviour comp);
|
|
|
|
// call OnStopClient in identity
|
|
// one component will throw an exception, but that shouldn't stop
|
|
// OnStopClient from being called in the second one
|
|
// exception will log an error
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.OnStopClient();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(compEx.called, Is.EqualTo(1));
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopServer()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out StopServerCalledNetworkBehaviour comp);
|
|
|
|
identity.OnStopServer();
|
|
Assert.That(comp.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void OnStopServerException()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity, out StopServerExceptionNetworkBehaviour compEx);
|
|
|
|
// make sure our test values are set to 0
|
|
Assert.That(compEx.called, Is.EqualTo(0));
|
|
|
|
// call OnStopClient in identity
|
|
// one component will throw an exception, but that shouldn't stop
|
|
// OnStopClient from being called in the second one
|
|
// exception will log an error
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.OnStopServer();
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(compEx.called, Is.EqualTo(1));
|
|
}
|
|
|
|
[Test]
|
|
public void AddObserver()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// create some connections
|
|
NetworkConnectionToClient connection1 = new NetworkConnectionToClient(42);
|
|
NetworkConnectionToClient connection2 = new NetworkConnectionToClient(43);
|
|
|
|
// AddObserver should return early if called before .observers was
|
|
// created
|
|
Assert.That(identity.observers, Is.Null);
|
|
// error log is expected
|
|
LogAssert.ignoreFailingMessages = true;
|
|
identity.AddObserver(connection1);
|
|
LogAssert.ignoreFailingMessages = false;
|
|
Assert.That(identity.observers, Is.Null);
|
|
|
|
// call OnStartServer so that observers dict is created
|
|
identity.OnStartServer();
|
|
|
|
// call AddObservers
|
|
identity.AddObserver(connection1);
|
|
identity.AddObserver(connection2);
|
|
Assert.That(identity.observers.Count, Is.EqualTo(2));
|
|
Assert.That(identity.observers.ContainsKey(connection1.connectionId));
|
|
Assert.That(identity.observers[connection1.connectionId], Is.EqualTo(connection1));
|
|
Assert.That(identity.observers.ContainsKey(connection2.connectionId));
|
|
Assert.That(identity.observers[connection2.connectionId], Is.EqualTo(connection2));
|
|
|
|
// adding a duplicate connectionId shouldn't overwrite the original
|
|
NetworkConnectionToClient duplicate = new NetworkConnectionToClient(connection1.connectionId);
|
|
identity.AddObserver(duplicate);
|
|
Assert.That(identity.observers.Count, Is.EqualTo(2));
|
|
Assert.That(identity.observers.ContainsKey(connection1.connectionId));
|
|
Assert.That(identity.observers[connection1.connectionId], Is.EqualTo(connection1));
|
|
Assert.That(identity.observers.ContainsKey(connection2.connectionId));
|
|
Assert.That(identity.observers[connection2.connectionId], Is.EqualTo(connection2));
|
|
}
|
|
|
|
[Test]
|
|
public void ClearObservers()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// call OnStartServer so that observers dict is created
|
|
identity.OnStartServer();
|
|
|
|
// add some observers
|
|
identity.observers[42] = new NetworkConnectionToClient(42);
|
|
identity.observers[43] = new NetworkConnectionToClient(43);
|
|
|
|
// call ClearObservers
|
|
identity.ClearObservers();
|
|
Assert.That(identity.observers.Count, Is.EqualTo(0));
|
|
}
|
|
|
|
[Test]
|
|
public void ClearDirtyComponentsDirtyBits()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out OnStartClientTestNetworkBehaviour compA,
|
|
out OnStartClientTestNetworkBehaviour compB);
|
|
|
|
// set syncintervals so one is always dirty, one is never dirty
|
|
compA.syncInterval = 0;
|
|
compB.syncInterval = Mathf.Infinity;
|
|
|
|
// set components dirty bits
|
|
compA.SetSyncVarDirtyBit(0x0001);
|
|
compB.SetSyncVarDirtyBit(0x1001);
|
|
// dirty because interval reached and mask != 0
|
|
Assert.That(compA.IsDirty(), Is.True);
|
|
// not dirty because syncinterval not reached
|
|
Assert.That(compB.IsDirty(), Is.False);
|
|
|
|
// call identity.ClearDirtyComponentsDirtyBits
|
|
identity.ClearDirtyComponentsDirtyBits();
|
|
// should be cleared now
|
|
Assert.That(compA.IsDirty(), Is.False);
|
|
// should be untouched
|
|
Assert.That(compB.IsDirty(), Is.False);
|
|
|
|
// set compB syncinterval to 0 to check if the masks were untouched
|
|
// (if they weren't, then it should be dirty now)
|
|
compB.syncInterval = 0;
|
|
Assert.That(compB.IsDirty(), Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void ClearAllComponentsDirtyBits()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity,
|
|
out OnStartClientTestNetworkBehaviour compA,
|
|
out OnStartClientTestNetworkBehaviour compB);
|
|
|
|
// set syncintervals so one is always dirty, one is never dirty
|
|
compA.syncInterval = 0;
|
|
compB.syncInterval = Mathf.Infinity;
|
|
|
|
// set components dirty bits
|
|
compA.SetSyncVarDirtyBit(0x0001);
|
|
compB.SetSyncVarDirtyBit(0x1001);
|
|
// dirty because interval reached and mask != 0
|
|
Assert.That(compA.IsDirty(), Is.True);
|
|
// not dirty because syncinterval not reached
|
|
Assert.That(compB.IsDirty(), Is.False);
|
|
|
|
// call identity.ClearAllComponentsDirtyBits
|
|
identity.ClearAllComponentsDirtyBits();
|
|
// should be cleared now
|
|
Assert.That(compA.IsDirty(), Is.False);
|
|
// should be cleared now
|
|
Assert.That(compB.IsDirty(), Is.False);
|
|
|
|
// set compB syncinterval to 0 to check if the masks were cleared
|
|
// (if they weren't, then it would still be dirty now)
|
|
compB.syncInterval = 0;
|
|
Assert.That(compB.IsDirty(), Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public void Reset()
|
|
{
|
|
CreateNetworked(out GameObject _, out NetworkIdentity identity);
|
|
|
|
// modify it a bit
|
|
identity.isClient = true;
|
|
// creates .observers and generates a netId
|
|
identity.OnStartServer();
|
|
identity.connectionToClient = new NetworkConnectionToClient(1);
|
|
identity.connectionToServer = new NetworkConnectionToServer();
|
|
identity.observers[43] = new NetworkConnectionToClient(2);
|
|
|
|
// mark for reset and reset
|
|
identity.Reset();
|
|
Assert.That(identity.isServer, Is.False);
|
|
Assert.That(identity.isClient, Is.False);
|
|
Assert.That(identity.isLocalPlayer, Is.False);
|
|
Assert.That(identity.netId, Is.EqualTo(0));
|
|
Assert.That(identity.connectionToClient, Is.Null);
|
|
Assert.That(identity.connectionToServer, Is.Null);
|
|
Assert.That(identity.hasAuthority, Is.False);
|
|
Assert.That(identity.observers, Is.Empty);
|
|
}
|
|
|
|
[Test, Ignore("NetworkServerTest.SendCommand does it already")]
|
|
public void HandleCommand() {}
|
|
|
|
[Test, Ignore("RpcTests do it already")]
|
|
public void HandleRpc() {}
|
|
}
|
|
}
|