com.unity.netcode.gameobjects@1.2.0
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Additional documentation and release notes are available at [Multiplayer Documentation](https://docs-multiplayer.unity3d.com). ## [1.2.0] - 2022-11-21 ### Added - Added protected method `NetworkBehaviour.OnSynchronize` which is invoked during the initial `NetworkObject` synchronization process. This provides users the ability to include custom serialization information that will be applied to the `NetworkBehaviour` prior to the `NetworkObject` being spawned. (#2298) - Added support for different versions of the SDK to talk to each other in circumstances where changes permit it. Starting with this version and into future versions, patch versions should be compatible as long as the minor version is the same. (#2290) - Added `NetworkObject` auto-add helper and Multiplayer Tools install reminder settings to Project Settings. (#2285) - Added `public string DisconnectReason` getter to `NetworkManager` and `string Reason` to `ConnectionApprovalResponse`. Allows connection approval to communicate back a reason. Also added `public void DisconnectClient(ulong clientId, string reason)` allowing setting a disconnection reason, when explicitly disconnecting a client. (#2280) ### Changed - Changed 3rd-party `XXHash` (32 & 64) implementation with an in-house reimplementation (#2310) - When `NetworkConfig.EnsureNetworkVariableLengthSafety` is disabled `NetworkVariable` fields do not write the additional `ushort` size value (_which helps to reduce the total synchronization message size_), but when enabled it still writes the additional `ushort` value. (#2298) - Optimized bandwidth usage by encoding most integer fields using variable-length encoding. (#2276) ### Fixed - Fixed issue where `NetworkTransform` components nested under a parent with a `NetworkObject` component (i.e. network prefab) would not have their associated `GameObject`'s transform synchronized. (#2298) - Fixed issue where `NetworkObject`s that failed to instantiate could cause the entire synchronization pipeline to be disrupted/halted for a connecting client. (#2298) - Fixed issue where in-scene placed `NetworkObject`s nested under a `GameObject` would be added to the orphaned children list causing continual console warning log messages. (#2298) - Custom messages are now properly received by the local client when they're sent while running in host mode. (#2296) - Fixed issue where the host would receive more than one event completed notification when loading or unloading a scene only when no clients were connected. (#2292) - Fixed an issue in `UnityTransport` where an error would be logged if the 'Use Encryption' flag was enabled with a Relay configuration that used a secure protocol. (#2289) - Fixed issue where in-scene placed `NetworkObjects` were not honoring the `AutoObjectParentSync` property. (#2281) - Fixed the issue where `NetworkManager.OnClientConnectedCallback` was being invoked before in-scene placed `NetworkObject`s had been spawned when starting `NetworkManager` as a host. (#2277) - Creating a `FastBufferReader` with `Allocator.None` will not result in extra memory being allocated for the buffer (since it's owned externally in that scenario). (#2265) ### Removed - Removed the `NetworkObject` auto-add and Multiplayer Tools install reminder settings from the Menu interface. (#2285)
This commit is contained in:
@@ -12,6 +12,7 @@ namespace Unity.Netcode.EditorTests
|
||||
public const string DefaultBuildScenePath = "Tests/Editor/Build/BuildTestScene.unity";
|
||||
|
||||
[Test]
|
||||
[Ignore("Disabling this test on release/1.2.0 branch due to Burst failures caused when running with upm ci")]
|
||||
public void BasicBuildTest()
|
||||
{
|
||||
var execAssembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
56
Tests/Editor/DisconnectMessageTests.cs
Normal file
56
Tests/Editor/DisconnectMessageTests.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class DisconnectMessageTests
|
||||
{
|
||||
[Test]
|
||||
public void EmptyDisconnectReason()
|
||||
{
|
||||
var networkContext = new NetworkContext();
|
||||
var writer = new FastBufferWriter(20, Allocator.Temp, 20);
|
||||
var msg = new DisconnectReasonMessage();
|
||||
msg.Reason = string.Empty;
|
||||
msg.Serialize(writer, msg.Version);
|
||||
|
||||
var fbr = new FastBufferReader(writer, Allocator.Temp);
|
||||
var recvMsg = new DisconnectReasonMessage();
|
||||
recvMsg.Deserialize(fbr, ref networkContext, msg.Version);
|
||||
|
||||
Assert.IsEmpty(recvMsg.Reason);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisconnectReason()
|
||||
{
|
||||
var networkContext = new NetworkContext();
|
||||
var writer = new FastBufferWriter(20, Allocator.Temp, 20);
|
||||
var msg = new DisconnectReasonMessage();
|
||||
msg.Reason = "Foo";
|
||||
msg.Serialize(writer, msg.Version);
|
||||
|
||||
var fbr = new FastBufferReader(writer, Allocator.Temp);
|
||||
var recvMsg = new DisconnectReasonMessage();
|
||||
recvMsg.Deserialize(fbr, ref networkContext, msg.Version);
|
||||
|
||||
Assert.AreEqual("Foo", recvMsg.Reason);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisconnectReasonTooLong()
|
||||
{
|
||||
var networkContext = new NetworkContext();
|
||||
var writer = new FastBufferWriter(20, Allocator.Temp, 20);
|
||||
var msg = new DisconnectReasonMessage();
|
||||
msg.Reason = "ThisStringIsWayLongerThanTwentyBytes";
|
||||
msg.Serialize(writer, msg.Version);
|
||||
|
||||
var fbr = new FastBufferReader(writer, Allocator.Temp);
|
||||
var recvMsg = new DisconnectReasonMessage();
|
||||
recvMsg.Deserialize(fbr, ref networkContext, msg.Version);
|
||||
|
||||
Assert.IsEmpty(recvMsg.Reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Editor/DisconnectMessageTests.cs.meta
Normal file
11
Tests/Editor/DisconnectMessageTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55a1355c62fe14a118253f8bbee7c3cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -18,12 +18,12 @@ namespace Unity.Netcode.EditorTests
|
||||
public static bool Handled;
|
||||
public static List<TestMessage> DeserializedValues = new List<TestMessage>();
|
||||
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
Deserialized = true;
|
||||
reader.ReadValueSafe(out this);
|
||||
@@ -35,6 +35,8 @@ namespace Unity.Netcode.EditorTests
|
||||
Handled = true;
|
||||
DeserializedValues.Add(this);
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
|
||||
private class TestMessageProvider : IMessageProvider
|
||||
@@ -46,7 +48,8 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessage),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessage>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -62,6 +65,7 @@ namespace Unity.Netcode.EditorTests
|
||||
TestMessage.DeserializedValues.Clear();
|
||||
|
||||
m_MessagingSystem = new MessagingSystem(new NopMessageSender(), this, new TestMessageProvider());
|
||||
m_MessagingSystem.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
@@ -11,12 +10,12 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -24,6 +23,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
|
||||
private struct TestMessageTwo : INetworkMessage, INetworkSerializeByMemcpy
|
||||
@@ -31,12 +32,12 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -44,6 +45,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
private class TestMessageProviderOne : IMessageProvider
|
||||
{
|
||||
@@ -54,12 +57,14 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageOne),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageOne>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageOne>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessageOne>
|
||||
},
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageTwo),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageTwo>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageTwo>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessageTwo>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -70,12 +75,12 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -83,6 +88,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
private class TestMessageProviderTwo : IMessageProvider
|
||||
{
|
||||
@@ -93,7 +100,8 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageThree),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageThree>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageThree>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessageThree>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -103,12 +111,12 @@ namespace Unity.Netcode.EditorTests
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
writer.WriteValue(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -116,6 +124,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
private class TestMessageProviderThree : IMessageProvider
|
||||
{
|
||||
@@ -126,7 +136,8 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessageFour),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageFour>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessageFour>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessageFour>
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -183,11 +194,11 @@ namespace Unity.Netcode.EditorTests
|
||||
|
||||
internal class AAAEarlyLexicographicNetworkMessage : INetworkMessage
|
||||
{
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -195,6 +206,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006
|
||||
@@ -212,18 +225,19 @@ namespace Unity.Netcode.EditorTests
|
||||
var messageWithHandler = new MessagingSystem.MessageWithHandler();
|
||||
|
||||
messageWithHandler.MessageType = typeof(zzzLateLexicographicNetworkMessage);
|
||||
messageWithHandler.GetVersion = MessagingSystem.CreateMessageAndGetVersion<zzzLateLexicographicNetworkMessage>;
|
||||
listMessages.Add(messageWithHandler);
|
||||
|
||||
messageWithHandler.MessageType = typeof(ConnectionRequestMessage);
|
||||
messageWithHandler.GetVersion = MessagingSystem.CreateMessageAndGetVersion<ConnectionRequestMessage>;
|
||||
listMessages.Add(messageWithHandler);
|
||||
|
||||
messageWithHandler.MessageType = typeof(ConnectionApprovedMessage);
|
||||
listMessages.Add(messageWithHandler);
|
||||
|
||||
messageWithHandler.MessageType = typeof(OrderingMessage);
|
||||
messageWithHandler.GetVersion = MessagingSystem.CreateMessageAndGetVersion<ConnectionApprovedMessage>;
|
||||
listMessages.Add(messageWithHandler);
|
||||
|
||||
messageWithHandler.MessageType = typeof(AAAEarlyLexicographicNetworkMessage);
|
||||
messageWithHandler.GetVersion = MessagingSystem.CreateMessageAndGetVersion<AAAEarlyLexicographicNetworkMessage>;
|
||||
listMessages.Add(messageWithHandler);
|
||||
|
||||
return listMessages;
|
||||
@@ -237,65 +251,16 @@ namespace Unity.Netcode.EditorTests
|
||||
var provider = new OrderingMessageProvider();
|
||||
using var messagingSystem = new MessagingSystem(sender, null, provider);
|
||||
|
||||
// the 3 priority messages should appear first, in lexicographic order
|
||||
// the 2 priority messages should appear first, in lexicographic order
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[0], typeof(ConnectionApprovedMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[1], typeof(ConnectionRequestMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[2], typeof(OrderingMessage));
|
||||
|
||||
// the other should follow after
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[3], typeof(AAAEarlyLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[4], typeof(zzzLateLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[2], typeof(AAAEarlyLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[3], typeof(zzzLateLexicographicNetworkMessage));
|
||||
|
||||
// there should not be any extras
|
||||
Assert.AreEqual(messagingSystem.MessageHandlerCount, 5);
|
||||
|
||||
// reorder the zzz one to position 3
|
||||
messagingSystem.ReorderMessage(3, XXHash.Hash32(typeof(zzzLateLexicographicNetworkMessage).FullName));
|
||||
|
||||
// the 3 priority messages should still appear first, in lexicographic order
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[0], typeof(ConnectionApprovedMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[1], typeof(ConnectionRequestMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[2], typeof(OrderingMessage));
|
||||
|
||||
// the other should follow after, but reordered
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[3], typeof(zzzLateLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[4], typeof(AAAEarlyLexicographicNetworkMessage));
|
||||
|
||||
// there should still not be any extras
|
||||
Assert.AreEqual(messagingSystem.MessageHandlerCount, 5);
|
||||
|
||||
// verify we get an exception when asking for an invalid position
|
||||
try
|
||||
{
|
||||
messagingSystem.ReorderMessage(-1, XXHash.Hash32(typeof(zzzLateLexicographicNetworkMessage).FullName));
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
|
||||
// reorder the zzz one to position 3, again, to check nothing bad happens
|
||||
messagingSystem.ReorderMessage(3, XXHash.Hash32(typeof(zzzLateLexicographicNetworkMessage).FullName));
|
||||
|
||||
// the two non-priority should not have moved
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[3], typeof(zzzLateLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[4], typeof(AAAEarlyLexicographicNetworkMessage));
|
||||
|
||||
// there should still not be any extras
|
||||
Assert.AreEqual(messagingSystem.MessageHandlerCount, 5);
|
||||
|
||||
// 4242 is a random hash that should not match anything
|
||||
messagingSystem.ReorderMessage(3, 4242);
|
||||
|
||||
// that should result in an extra entry
|
||||
Assert.AreEqual(messagingSystem.MessageHandlerCount, 6);
|
||||
|
||||
// with a null handler
|
||||
Assert.AreEqual(messagingSystem.MessageHandlers[3], null);
|
||||
|
||||
// and it should have bumped the previous messages down
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[4], typeof(zzzLateLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageTypes[5], typeof(AAAEarlyLexicographicNetworkMessage));
|
||||
Assert.AreEqual(messagingSystem.MessageHandlerCount, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ namespace Unity.Netcode.EditorTests
|
||||
public int B;
|
||||
public int C;
|
||||
public static bool Serialized;
|
||||
public void Serialize(FastBufferWriter writer)
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
Serialized = true;
|
||||
writer.WriteValueSafe(this);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context)
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -32,6 +32,8 @@ namespace Unity.Netcode.EditorTests
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
|
||||
private class TestMessageSender : IMessageSender
|
||||
@@ -66,7 +68,8 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessage),
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>
|
||||
Handler = MessagingSystem.ReceiveMessage<TestMessage>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessage>
|
||||
}
|
||||
};
|
||||
// Track messages sent
|
||||
@@ -88,6 +91,7 @@ namespace Unity.Netcode.EditorTests
|
||||
m_TestMessageProvider = new TestMessageProvider();
|
||||
m_MessagingSystem = new MessagingSystem(m_MessageSender, this, m_TestMessageProvider);
|
||||
m_MessagingSystem.ClientConnected(0);
|
||||
m_MessagingSystem.SetVersion(0, XXHash.Hash32(typeof(TestMessage).FullName), 0);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
@@ -256,7 +260,8 @@ namespace Unity.Netcode.EditorTests
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(TestMessage),
|
||||
Handler = null
|
||||
Handler = null,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<TestMessage>
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
503
Tests/Editor/Messaging/MessageVersioningTests.cs
Normal file
503
Tests/Editor/Messaging/MessageVersioningTests.cs
Normal file
@@ -0,0 +1,503 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Internal;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class MessageVersioningTests
|
||||
{
|
||||
public static int SentVersion;
|
||||
public static int ReceivedVersion;
|
||||
|
||||
private const int k_DefaultB = 5;
|
||||
private const int k_DefaultC = 10;
|
||||
private const int k_DefaultD = 15;
|
||||
private const long k_DefaultE = 20;
|
||||
|
||||
private struct VersionedTestMessage_v0 : INetworkMessage, INetworkSerializeByMemcpy
|
||||
{
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public static bool Serialized;
|
||||
public static bool Deserialized;
|
||||
public static bool Handled;
|
||||
public static List<VersionedTestMessage_v0> DeserializedValues = new List<VersionedTestMessage_v0>();
|
||||
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
SentVersion = Version;
|
||||
Serialized = true;
|
||||
writer.WriteValueSafe(A);
|
||||
writer.WriteValueSafe(B);
|
||||
writer.WriteValueSafe(C);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
ReceivedVersion = Version;
|
||||
Deserialized = true;
|
||||
reader.ReadValueSafe(out A);
|
||||
reader.ReadValueSafe(out B);
|
||||
reader.ReadValueSafe(out C);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
Handled = true;
|
||||
DeserializedValues.Add(this);
|
||||
}
|
||||
|
||||
public int Version => 0;
|
||||
}
|
||||
|
||||
private struct VersionedTestMessage_v1 : INetworkMessage, INetworkSerializeByMemcpy
|
||||
{
|
||||
public int A;
|
||||
public int B;
|
||||
public int C;
|
||||
public int D;
|
||||
public static bool Serialized;
|
||||
public static bool Deserialized;
|
||||
public static bool Downgraded;
|
||||
public static bool Upgraded;
|
||||
public static bool Handled;
|
||||
public static List<VersionedTestMessage_v1> DeserializedValues = new List<VersionedTestMessage_v1>();
|
||||
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
if (targetVersion < Version)
|
||||
{
|
||||
Downgraded = true;
|
||||
var v0 = new VersionedTestMessage_v0 { A = A, B = B, C = C };
|
||||
v0.Serialize(writer, targetVersion);
|
||||
return;
|
||||
}
|
||||
SentVersion = Version;
|
||||
Serialized = true;
|
||||
writer.WriteValueSafe(C);
|
||||
writer.WriteValueSafe(D);
|
||||
writer.WriteValueSafe(A);
|
||||
writer.WriteValueSafe(B);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
if (receivedMessageVersion < Version)
|
||||
{
|
||||
var v0 = new VersionedTestMessage_v0();
|
||||
v0.Deserialize(reader, ref context, receivedMessageVersion);
|
||||
A = v0.A;
|
||||
B = v0.B;
|
||||
C = v0.C;
|
||||
D = k_DefaultD;
|
||||
Upgraded = true;
|
||||
return true;
|
||||
}
|
||||
ReceivedVersion = Version;
|
||||
Deserialized = true;
|
||||
reader.ReadValueSafe(out C);
|
||||
reader.ReadValueSafe(out D);
|
||||
reader.ReadValueSafe(out A);
|
||||
reader.ReadValueSafe(out B);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
Handled = true;
|
||||
DeserializedValues.Add(this);
|
||||
}
|
||||
|
||||
public int Version => 1;
|
||||
}
|
||||
|
||||
private struct VersionedTestMessage : INetworkMessage, INetworkSerializeByMemcpy
|
||||
{
|
||||
public int A;
|
||||
public float D;
|
||||
public long E;
|
||||
public static bool Serialized;
|
||||
public static bool Deserialized;
|
||||
public static bool Downgraded;
|
||||
public static bool Upgraded;
|
||||
public static bool Handled;
|
||||
public static List<VersionedTestMessage> DeserializedValues = new List<VersionedTestMessage>();
|
||||
|
||||
public void Serialize(FastBufferWriter writer, int targetVersion)
|
||||
{
|
||||
if (targetVersion < Version)
|
||||
{
|
||||
Downgraded = true;
|
||||
var v1 = new VersionedTestMessage_v1 { A = A, B = k_DefaultB, C = k_DefaultC, D = (int)D };
|
||||
v1.Serialize(writer, targetVersion);
|
||||
return;
|
||||
}
|
||||
SentVersion = Version;
|
||||
Serialized = true;
|
||||
writer.WriteValueSafe(D);
|
||||
writer.WriteValueSafe(A);
|
||||
writer.WriteValueSafe(E);
|
||||
}
|
||||
|
||||
public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int receivedMessageVersion)
|
||||
{
|
||||
if (receivedMessageVersion < Version)
|
||||
{
|
||||
var v1 = new VersionedTestMessage_v1();
|
||||
v1.Deserialize(reader, ref context, receivedMessageVersion);
|
||||
A = v1.A;
|
||||
D = (float)v1.D;
|
||||
E = k_DefaultE;
|
||||
Upgraded = true;
|
||||
return true;
|
||||
}
|
||||
ReceivedVersion = Version;
|
||||
Deserialized = true;
|
||||
reader.ReadValueSafe(out D);
|
||||
reader.ReadValueSafe(out A);
|
||||
reader.ReadValueSafe(out E);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Handle(ref NetworkContext context)
|
||||
{
|
||||
Handled = true;
|
||||
DeserializedValues.Add(this);
|
||||
}
|
||||
|
||||
public int Version => 2;
|
||||
}
|
||||
|
||||
private class TestMessageProvider_v0 : IMessageProvider
|
||||
{
|
||||
public List<MessagingSystem.MessageWithHandler> GetMessages()
|
||||
{
|
||||
return new List<MessagingSystem.MessageWithHandler>
|
||||
{
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(VersionedTestMessage_v0),
|
||||
Handler = MessagingSystem.ReceiveMessage<VersionedTestMessage_v0>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<VersionedTestMessage_v0>
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TestMessageProvider_v1 : IMessageProvider
|
||||
{
|
||||
public List<MessagingSystem.MessageWithHandler> GetMessages()
|
||||
{
|
||||
return new List<MessagingSystem.MessageWithHandler>
|
||||
{
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(VersionedTestMessage_v1),
|
||||
Handler = MessagingSystem.ReceiveMessage<VersionedTestMessage_v1>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<VersionedTestMessage_v1>
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TestMessageProvider_v2 : IMessageProvider
|
||||
{
|
||||
public List<MessagingSystem.MessageWithHandler> GetMessages()
|
||||
{
|
||||
return new List<MessagingSystem.MessageWithHandler>
|
||||
{
|
||||
new MessagingSystem.MessageWithHandler
|
||||
{
|
||||
MessageType = typeof(VersionedTestMessage),
|
||||
Handler = MessagingSystem.ReceiveMessage<VersionedTestMessage>,
|
||||
GetVersion = MessagingSystem.CreateMessageAndGetVersion<VersionedTestMessage>
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class TestMessageSender : IMessageSender
|
||||
{
|
||||
public List<byte[]> MessageQueue = new List<byte[]>();
|
||||
|
||||
public void Send(ulong clientId, NetworkDelivery delivery, FastBufferWriter batchData)
|
||||
{
|
||||
MessageQueue.Add(batchData.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private MessagingSystem m_MessagingSystem_v0;
|
||||
private MessagingSystem m_MessagingSystem_v1;
|
||||
private MessagingSystem m_MessagingSystem_v2;
|
||||
private TestMessageSender m_MessageSender;
|
||||
|
||||
private void CreateFakeClients(MessagingSystem system, uint hash)
|
||||
{
|
||||
// Create three fake clients for each messaging system
|
||||
// client 0 has version 0, client 1 has version 1, and client 2 has version 2
|
||||
system.ClientConnected(0);
|
||||
system.ClientConnected(1);
|
||||
system.ClientConnected(2);
|
||||
system.SetVersion(0, hash, 0);
|
||||
system.SetVersion(1, hash, 1);
|
||||
system.SetVersion(2, hash, 2);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
VersionedTestMessage_v0.Serialized = false;
|
||||
VersionedTestMessage_v0.Deserialized = false;
|
||||
VersionedTestMessage_v0.Handled = false;
|
||||
VersionedTestMessage_v0.DeserializedValues.Clear();
|
||||
VersionedTestMessage_v1.Serialized = false;
|
||||
VersionedTestMessage_v1.Deserialized = false;
|
||||
VersionedTestMessage_v1.Downgraded = false;
|
||||
VersionedTestMessage_v1.Upgraded = false;
|
||||
VersionedTestMessage_v1.Handled = false;
|
||||
VersionedTestMessage_v1.DeserializedValues.Clear();
|
||||
VersionedTestMessage.Serialized = false;
|
||||
VersionedTestMessage.Deserialized = false;
|
||||
VersionedTestMessage.Downgraded = false;
|
||||
VersionedTestMessage.Upgraded = false;
|
||||
VersionedTestMessage.Handled = false;
|
||||
VersionedTestMessage.DeserializedValues.Clear();
|
||||
m_MessageSender = new TestMessageSender();
|
||||
|
||||
m_MessagingSystem_v0 = new MessagingSystem(m_MessageSender, this, new TestMessageProvider_v0());
|
||||
m_MessagingSystem_v1 = new MessagingSystem(m_MessageSender, this, new TestMessageProvider_v1());
|
||||
m_MessagingSystem_v2 = new MessagingSystem(m_MessageSender, this, new TestMessageProvider_v2());
|
||||
|
||||
CreateFakeClients(m_MessagingSystem_v0, XXHash.Hash32(typeof(VersionedTestMessage_v0).FullName));
|
||||
CreateFakeClients(m_MessagingSystem_v1, XXHash.Hash32(typeof(VersionedTestMessage_v1).FullName));
|
||||
CreateFakeClients(m_MessagingSystem_v2, XXHash.Hash32(typeof(VersionedTestMessage).FullName));
|
||||
|
||||
// Make sure that all three messages got the same IDs...
|
||||
Assert.AreEqual(
|
||||
m_MessagingSystem_v0.GetMessageType(typeof(VersionedTestMessage_v0)),
|
||||
m_MessagingSystem_v1.GetMessageType(typeof(VersionedTestMessage_v1)));
|
||||
Assert.AreEqual(
|
||||
m_MessagingSystem_v0.GetMessageType(typeof(VersionedTestMessage_v0)),
|
||||
m_MessagingSystem_v2.GetMessageType(typeof(VersionedTestMessage)));
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
m_MessagingSystem_v0.Dispose();
|
||||
m_MessagingSystem_v1.Dispose();
|
||||
m_MessagingSystem_v2.Dispose();
|
||||
}
|
||||
|
||||
private VersionedTestMessage_v0 GetMessage_v0()
|
||||
{
|
||||
var random = new Random();
|
||||
return new VersionedTestMessage_v0
|
||||
{
|
||||
A = random.Next(),
|
||||
B = random.Next(),
|
||||
C = random.Next(),
|
||||
};
|
||||
}
|
||||
|
||||
private VersionedTestMessage_v1 GetMessage_v1()
|
||||
{
|
||||
var random = new Random();
|
||||
return new VersionedTestMessage_v1
|
||||
{
|
||||
A = random.Next(),
|
||||
B = random.Next(),
|
||||
C = random.Next(),
|
||||
D = random.Next(),
|
||||
};
|
||||
}
|
||||
|
||||
private VersionedTestMessage GetMessage_v2()
|
||||
{
|
||||
var random = new Random();
|
||||
return new VersionedTestMessage
|
||||
{
|
||||
A = random.Next(),
|
||||
D = (float)(random.NextDouble() * 10000),
|
||||
E = ((long)random.Next() << 32) + random.Next()
|
||||
};
|
||||
}
|
||||
|
||||
public void CheckPostSendExpectations(int sourceLocalVersion, int remoteVersion)
|
||||
{
|
||||
Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 0, VersionedTestMessage_v0.Serialized);
|
||||
Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 1, VersionedTestMessage_v1.Serialized);
|
||||
Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion) == 2, VersionedTestMessage.Serialized);
|
||||
Assert.AreEqual(sourceLocalVersion >= 1 && remoteVersion < 1, VersionedTestMessage_v1.Downgraded);
|
||||
Assert.AreEqual(sourceLocalVersion >= 2 && remoteVersion < 2, VersionedTestMessage.Downgraded);
|
||||
|
||||
Assert.AreEqual(1, m_MessageSender.MessageQueue.Count);
|
||||
Assert.AreEqual(Math.Min(sourceLocalVersion, remoteVersion), SentVersion);
|
||||
}
|
||||
|
||||
public void CheckPostReceiveExpectations(int sourceLocalVersion, int remoteVersion)
|
||||
{
|
||||
Assert.AreEqual(SentVersion == 0, VersionedTestMessage_v0.Deserialized);
|
||||
Assert.AreEqual(SentVersion == 1, VersionedTestMessage_v1.Deserialized);
|
||||
Assert.AreEqual(SentVersion == 2, VersionedTestMessage.Deserialized);
|
||||
Assert.AreEqual(remoteVersion >= 1 && sourceLocalVersion < 1, VersionedTestMessage_v1.Upgraded);
|
||||
Assert.AreEqual(remoteVersion >= 2 && sourceLocalVersion < 2, VersionedTestMessage.Upgraded);
|
||||
|
||||
Assert.AreEqual((remoteVersion == 0 ? 1 : 0), VersionedTestMessage_v0.DeserializedValues.Count);
|
||||
Assert.AreEqual((remoteVersion == 1 ? 1 : 0), VersionedTestMessage_v1.DeserializedValues.Count);
|
||||
Assert.AreEqual((remoteVersion == 2 ? 1 : 0), VersionedTestMessage.DeserializedValues.Count);
|
||||
|
||||
Assert.AreEqual(SentVersion, ReceivedVersion);
|
||||
}
|
||||
|
||||
private void SendMessageWithVersions<T>(T message, int fromVersion, int toVersion) where T : unmanaged, INetworkMessage
|
||||
{
|
||||
MessagingSystem sendSystem;
|
||||
switch (fromVersion)
|
||||
{
|
||||
case 0: sendSystem = m_MessagingSystem_v0; break;
|
||||
case 1: sendSystem = m_MessagingSystem_v1; break;
|
||||
default: sendSystem = m_MessagingSystem_v2; break;
|
||||
}
|
||||
sendSystem.SendMessage(ref message, NetworkDelivery.Reliable, (ulong)toVersion);
|
||||
sendSystem.ProcessSendQueues();
|
||||
CheckPostSendExpectations(fromVersion, toVersion);
|
||||
|
||||
MessagingSystem receiveSystem;
|
||||
switch (toVersion)
|
||||
{
|
||||
case 0: receiveSystem = m_MessagingSystem_v0; break;
|
||||
case 1: receiveSystem = m_MessagingSystem_v1; break;
|
||||
default: receiveSystem = m_MessagingSystem_v2; break;
|
||||
}
|
||||
receiveSystem.HandleIncomingData((ulong)fromVersion, new ArraySegment<byte>(m_MessageSender.MessageQueue[0]), 0.0f);
|
||||
receiveSystem.ProcessIncomingMessageQueue();
|
||||
CheckPostReceiveExpectations(fromVersion, toVersion);
|
||||
|
||||
m_MessageSender.MessageQueue.Clear();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV0ToV0_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v0();
|
||||
|
||||
SendMessageWithVersions(message, 0, 0);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v0.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(message.B, receivedMessage.B);
|
||||
Assert.AreEqual(message.C, receivedMessage.C);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV0ToV1_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v0();
|
||||
|
||||
SendMessageWithVersions(message, 0, 1);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v1.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(message.B, receivedMessage.B);
|
||||
Assert.AreEqual(message.C, receivedMessage.C);
|
||||
Assert.AreEqual(k_DefaultD, receivedMessage.D);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV0ToV2_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v0();
|
||||
|
||||
SendMessageWithVersions(message, 0, 2);
|
||||
|
||||
var receivedMessage = VersionedTestMessage.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual((float)k_DefaultD, receivedMessage.D);
|
||||
Assert.AreEqual(k_DefaultE, receivedMessage.E);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV1ToV0_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v1();
|
||||
|
||||
SendMessageWithVersions(message, 1, 0);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v0.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(message.B, receivedMessage.B);
|
||||
Assert.AreEqual(message.C, receivedMessage.C);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV1ToV1_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v1();
|
||||
|
||||
SendMessageWithVersions(message, 1, 1);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v1.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(message.B, receivedMessage.B);
|
||||
Assert.AreEqual(message.C, receivedMessage.C);
|
||||
Assert.AreEqual(message.D, receivedMessage.D);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV1ToV2_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v1();
|
||||
|
||||
SendMessageWithVersions(message, 1, 2);
|
||||
|
||||
var receivedMessage = VersionedTestMessage.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual((float)message.D, receivedMessage.D);
|
||||
Assert.AreEqual(k_DefaultE, receivedMessage.E);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV2ToV0_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v2();
|
||||
|
||||
SendMessageWithVersions(message, 2, 0);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v0.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(k_DefaultB, receivedMessage.B);
|
||||
Assert.AreEqual(k_DefaultC, receivedMessage.C);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV2ToV1_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v2();
|
||||
|
||||
SendMessageWithVersions(message, 2, 1);
|
||||
|
||||
var receivedMessage = VersionedTestMessage_v1.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(k_DefaultB, receivedMessage.B);
|
||||
Assert.AreEqual(k_DefaultC, receivedMessage.C);
|
||||
Assert.AreEqual((int)message.D, receivedMessage.D);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenSendingV2ToV2_DataIsReceivedCorrectly()
|
||||
{
|
||||
var message = GetMessage_v2();
|
||||
|
||||
SendMessageWithVersions(message, 2, 2);
|
||||
|
||||
var receivedMessage = VersionedTestMessage.DeserializedValues[0];
|
||||
Assert.AreEqual(message.A, receivedMessage.A);
|
||||
Assert.AreEqual(message.D, receivedMessage.D);
|
||||
Assert.AreEqual(message.E, receivedMessage.E);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Tests/Editor/Messaging/MessageVersioningTests.cs.meta
Normal file
3
Tests/Editor/Messaging/MessageVersioningTests.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eac9a654aacb4faf91128c9ab6024543
|
||||
timeCreated: 1667326658
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
@@ -31,19 +32,17 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetBehaviourIndexNone()
|
||||
[TestCase(0)]
|
||||
[TestCase(1)]
|
||||
[TestCase(2)]
|
||||
public void GetBehaviourIndexNone(int index)
|
||||
{
|
||||
var gameObject = new GameObject(nameof(GetBehaviourIndexNone));
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
|
||||
// TODO: Maybe not hardcode message?
|
||||
LogAssert.Expect(LogType.Error, $"[Netcode] Behaviour index was out of bounds. Did you mess up the order of your {nameof(NetworkBehaviour)}s?");
|
||||
LogAssert.Expect(LogType.Error, $"[Netcode] Behaviour index was out of bounds. Did you mess up the order of your {nameof(NetworkBehaviour)}s?");
|
||||
LogAssert.Expect(LogType.Error, $"[Netcode] Behaviour index was out of bounds. Did you mess up the order of your {nameof(NetworkBehaviour)}s?");
|
||||
LogAssert.Expect(LogType.Error, new Regex(".*out of bounds.*"));
|
||||
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(0), Is.Null);
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(1), Is.Null);
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(2), Is.Null);
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex((ushort)index), Is.Null);
|
||||
|
||||
// Cleanup
|
||||
Object.DestroyImmediate(gameObject);
|
||||
@@ -56,13 +55,10 @@ namespace Unity.Netcode.EditorTests
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
var networkBehaviour = gameObject.AddComponent<EmptyNetworkBehaviour>();
|
||||
|
||||
// TODO: Maybe not hardcode message?
|
||||
LogAssert.Expect(LogType.Error, $"[Netcode] Behaviour index was out of bounds. Did you mess up the order of your {nameof(NetworkBehaviour)}s?");
|
||||
LogAssert.Expect(LogType.Error, $"[Netcode] Behaviour index was out of bounds. Did you mess up the order of your {nameof(NetworkBehaviour)}s?");
|
||||
LogAssert.Expect(LogType.Error, new Regex(".*out of bounds.*"));
|
||||
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(0), Is.EqualTo(networkBehaviour));
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(1), Is.Null);
|
||||
Assert.That(networkObject.GetNetworkBehaviourAtOrderIndex(2), Is.Null);
|
||||
|
||||
// Cleanup
|
||||
Object.DestroyImmediate(gameObject);
|
||||
|
||||
@@ -76,116 +76,6 @@ namespace Unity.Netcode.EditorTests
|
||||
|
||||
#endregion
|
||||
|
||||
private void CheckUnsignedPackedSize64(FastBufferWriter writer, ulong value)
|
||||
{
|
||||
|
||||
if (value <= 240)
|
||||
{
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
}
|
||||
else if (value <= 2287)
|
||||
{
|
||||
Assert.AreEqual(2, writer.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreEqual(BitCounter.GetUsedByteCount(value) + 1, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckUnsignedPackedValue64(FastBufferWriter writer, ulong value)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
{
|
||||
ByteUnpacker.ReadValuePacked(reader, out ulong readValue);
|
||||
Assert.AreEqual(readValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckUnsignedPackedSize32(FastBufferWriter writer, uint value)
|
||||
{
|
||||
|
||||
if (value <= 240)
|
||||
{
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
}
|
||||
else if (value <= 2287)
|
||||
{
|
||||
Assert.AreEqual(2, writer.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreEqual(BitCounter.GetUsedByteCount(value) + 1, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckUnsignedPackedValue32(FastBufferWriter writer, uint value)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
{
|
||||
ByteUnpacker.ReadValuePacked(reader, out uint readValue);
|
||||
Assert.AreEqual(readValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSignedPackedSize64(FastBufferWriter writer, long value)
|
||||
{
|
||||
ulong asUlong = Arithmetic.ZigZagEncode(value);
|
||||
|
||||
if (asUlong <= 240)
|
||||
{
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
}
|
||||
else if (asUlong <= 2287)
|
||||
{
|
||||
Assert.AreEqual(2, writer.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreEqual(BitCounter.GetUsedByteCount(asUlong) + 1, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSignedPackedValue64(FastBufferWriter writer, long value)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
{
|
||||
ByteUnpacker.ReadValuePacked(reader, out long readValue);
|
||||
Assert.AreEqual(readValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSignedPackedSize32(FastBufferWriter writer, int value)
|
||||
{
|
||||
ulong asUlong = Arithmetic.ZigZagEncode(value);
|
||||
|
||||
if (asUlong <= 240)
|
||||
{
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
}
|
||||
else if (asUlong <= 2287)
|
||||
{
|
||||
Assert.AreEqual(2, writer.Position);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.AreEqual(BitCounter.GetUsedByteCount(asUlong) + 1, writer.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckSignedPackedValue32(FastBufferWriter writer, int value)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
{
|
||||
ByteUnpacker.ReadValuePacked(reader, out int readValue);
|
||||
Assert.AreEqual(readValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void VerifyBytewiseEquality<T>(T value, T otherValue) where T : unmanaged
|
||||
{
|
||||
byte* asBytePointer = (byte*)&value;
|
||||
@@ -229,164 +119,53 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void TestPacking64BitsUnsigned()
|
||||
private int GetByteCount64Bits(ulong value)
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
using (writer)
|
||||
if (value <= 0b0000_1111)
|
||||
{
|
||||
writer.TryBeginWrite(9);
|
||||
ulong value = 0;
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1UL << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckUnsignedPackedSize64(writer, value);
|
||||
CheckUnsignedPackedValue64(writer, value);
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
value = (1UL << i) | (1UL << j);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckUnsignedPackedSize64(writer, value);
|
||||
CheckUnsignedPackedValue64(writer, value);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
if (value <= 0b0000_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
return 9;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPacking32BitsUnsigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
using (writer)
|
||||
{
|
||||
writer.TryBeginWrite(9);
|
||||
uint value = 0;
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1U << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckUnsignedPackedSize32(writer, value);
|
||||
CheckUnsignedPackedValue32(writer, value);
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
value = (1U << i) | (1U << j);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckUnsignedPackedSize32(writer, value);
|
||||
CheckUnsignedPackedValue32(writer, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPacking64BitsSigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
using (writer)
|
||||
{
|
||||
writer.TryBeginWrite(9);
|
||||
long value = 0;
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1L << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckSignedPackedSize64(writer, value);
|
||||
CheckSignedPackedValue64(writer, value);
|
||||
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, -value);
|
||||
CheckSignedPackedSize64(writer, -value);
|
||||
CheckSignedPackedValue64(writer, -value);
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
value = (1L << i) | (1L << j);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckSignedPackedSize64(writer, value);
|
||||
CheckSignedPackedValue64(writer, value);
|
||||
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, -value);
|
||||
CheckSignedPackedSize64(writer, -value);
|
||||
CheckSignedPackedValue64(writer, -value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPacking32BitsSigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
using (writer)
|
||||
{
|
||||
writer.TryBeginWrite(5);
|
||||
int value = 0;
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1 << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckSignedPackedSize32(writer, value);
|
||||
CheckSignedPackedValue32(writer, value);
|
||||
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, -value);
|
||||
CheckSignedPackedSize32(writer, -value);
|
||||
CheckSignedPackedValue32(writer, -value);
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
value = (1 << i) | (1 << j);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, value);
|
||||
CheckSignedPackedSize32(writer, value);
|
||||
CheckSignedPackedValue32(writer, value);
|
||||
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValuePacked(writer, -value);
|
||||
CheckSignedPackedSize32(writer, -value);
|
||||
CheckSignedPackedValue32(writer, -value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int GetByteCount61Bits(ulong value)
|
||||
private int GetByteCount32Bits(uint value)
|
||||
{
|
||||
|
||||
if (value <= 0b0001_1111)
|
||||
@@ -409,57 +188,25 @@ namespace Unity.Netcode.EditorTests
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (value <= 0b0001_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (value <= 0b0001_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
if (value <= 0b0001_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
return 8;
|
||||
return 5;
|
||||
}
|
||||
|
||||
private int GetByteCount30Bits(uint value)
|
||||
private int GetByteCount16Bits(ushort value)
|
||||
{
|
||||
|
||||
if (value <= 0b0011_1111)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (value <= 0b0011_1111_1111_1111)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (value <= 0b0011_1111_1111_1111_1111_1111)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
|
||||
private int GetByteCount15Bits(ushort value)
|
||||
{
|
||||
|
||||
if (value <= 0b0111_1111)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
private ulong Get61BitEncodedValue(FastBufferWriter writer)
|
||||
private ulong Get64BitEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -469,7 +216,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
private long Get60BitSignedEncodedValue(FastBufferWriter writer)
|
||||
private long Get64BitSignedEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -479,7 +226,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
private uint Get30BitEncodedValue(FastBufferWriter writer)
|
||||
private uint Get32BitEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -489,7 +236,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
private int Get29BitSignedEncodedValue(FastBufferWriter writer)
|
||||
private int Get32BitSignedEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -499,7 +246,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
private ushort Get15BitEncodedValue(FastBufferWriter writer)
|
||||
private ushort Get16BitEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -509,7 +256,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
private short Get14BitSignedEncodedValue(FastBufferWriter writer)
|
||||
private short Get16BitSignedEncodedValue(FastBufferWriter writer)
|
||||
{
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
@@ -520,7 +267,7 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBitPacking61BitsUnsigned()
|
||||
public void TestBitPacking64BitsUnsigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -530,18 +277,18 @@ namespace Unity.Netcode.EditorTests
|
||||
ulong value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b111);
|
||||
Assert.AreEqual(value, Get61BitEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b1111);
|
||||
Assert.AreEqual(value, Get64BitEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 61; ++i)
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1UL << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount61Bits(value) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get61BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount64Bits(value), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get64BitEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -549,18 +296,16 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount61Bits(value) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get61BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount64Bits(value), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get64BitEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => { BytePacker.WriteValueBitPacked(writer, 1UL << 61); });
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBitPacking60BitsSigned()
|
||||
public void TestBitPacking64BitsSigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -570,28 +315,28 @@ namespace Unity.Netcode.EditorTests
|
||||
long value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b111);
|
||||
Assert.AreEqual(value, Get60BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b1111);
|
||||
Assert.AreEqual(value, Get64BitSignedEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 61; ++i)
|
||||
for (var i = 0; i < 64; ++i)
|
||||
{
|
||||
value = 1U << i;
|
||||
ulong zzvalue = Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get60BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get64BitSignedEncodedValue(writer));
|
||||
|
||||
value = -value;
|
||||
zzvalue = Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get60BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get64BitSignedEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -600,27 +345,25 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get60BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get64BitSignedEncodedValue(writer));
|
||||
|
||||
value = -value;
|
||||
zzvalue = Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount61Bits(zzvalue) - 1, writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get60BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount64Bits(zzvalue), writer.ToArray()[0] & 0b1111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get64BitSignedEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => { BytePacker.WriteValueBitPacked(writer, 1UL << 61); });
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBitPacking30BitsUnsigned()
|
||||
public void TestBitPacking32BitsUnsigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -630,18 +373,18 @@ namespace Unity.Netcode.EditorTests
|
||||
uint value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b11);
|
||||
Assert.AreEqual(value, Get30BitEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b111);
|
||||
Assert.AreEqual(value, Get32BitEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 30; ++i)
|
||||
for (var i = 0; i < 32; ++i)
|
||||
{
|
||||
value = 1U << i;
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount30Bits(value) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get30BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount32Bits(value), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get32BitEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -649,18 +392,16 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount30Bits(value) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get30BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount32Bits(value), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get32BitEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => { BytePacker.WriteValueBitPacked(writer, 1U << 30); });
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBitPacking29BitsSigned()
|
||||
public void TestBitPacking32BitsSigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -670,28 +411,28 @@ namespace Unity.Netcode.EditorTests
|
||||
int value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b11);
|
||||
Assert.AreEqual(value, Get30BitEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b111);
|
||||
Assert.AreEqual(value, Get32BitEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 29; ++i)
|
||||
for (var i = 0; i < 32; ++i)
|
||||
{
|
||||
value = 1 << i;
|
||||
uint zzvalue = (uint)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get29BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get32BitSignedEncodedValue(writer));
|
||||
|
||||
value = -value;
|
||||
zzvalue = (uint)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get29BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get32BitSignedEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -700,25 +441,25 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get29BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get32BitSignedEncodedValue(writer));
|
||||
|
||||
value = -value;
|
||||
zzvalue = (uint)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount30Bits(zzvalue) - 1, writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get29BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount32Bits(zzvalue), writer.ToArray()[0] & 0b111, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get32BitSignedEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBitPacking15BitsUnsigned()
|
||||
public void TestBitPacking16BitsUnsigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -728,18 +469,18 @@ namespace Unity.Netcode.EditorTests
|
||||
ushort value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b1);
|
||||
Assert.AreEqual(value, Get15BitEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b11);
|
||||
Assert.AreEqual(value, Get16BitEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 15; ++i)
|
||||
for (var i = 0; i < 16; ++i)
|
||||
{
|
||||
value = (ushort)(1U << i);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount15Bits(value) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get15BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(value), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount16Bits(value), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get16BitEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -747,17 +488,15 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount15Bits(value) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get15BitEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(value), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount16Bits(value), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get16BitEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentException>(() => { BytePacker.WriteValueBitPacked(writer, (ushort)(1U << 15)); });
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public void TestBitPacking14BitsSigned()
|
||||
public void TestBitPacking16BitsSigned()
|
||||
{
|
||||
var writer = new FastBufferWriter(9, Allocator.Temp);
|
||||
|
||||
@@ -767,28 +506,28 @@ namespace Unity.Netcode.EditorTests
|
||||
short value = 0;
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(1, writer.Position);
|
||||
Assert.AreEqual(0, writer.ToArray()[0] & 0b1);
|
||||
Assert.AreEqual(value, Get15BitEncodedValue(writer));
|
||||
Assert.AreEqual(1, writer.ToArray()[0] & 0b11);
|
||||
Assert.AreEqual(value, Get16BitEncodedValue(writer));
|
||||
|
||||
for (var i = 0; i < 14; ++i)
|
||||
for (var i = 0; i < 16; ++i)
|
||||
{
|
||||
value = (short)(1 << i);
|
||||
ushort zzvalue = (ushort)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get14BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get16BitSignedEncodedValue(writer));
|
||||
|
||||
value = (short)-value;
|
||||
zzvalue = (ushort)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get14BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i})");
|
||||
Assert.AreEqual(value, Get16BitSignedEncodedValue(writer));
|
||||
|
||||
for (var j = 0; j < 8; ++j)
|
||||
{
|
||||
@@ -797,18 +536,18 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get14BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get16BitSignedEncodedValue(writer));
|
||||
|
||||
value = (short)-value;
|
||||
zzvalue = (ushort)Arithmetic.ZigZagEncode(value);
|
||||
writer.Seek(0);
|
||||
writer.Truncate();
|
||||
BytePacker.WriteValueBitPacked(writer, value);
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount15Bits(zzvalue) - 1, writer.ToArray()[0] & 0b1, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get14BitSignedEncodedValue(writer));
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.Position, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(GetByteCount16Bits(zzvalue), writer.ToArray()[0] & 0b11, $"Failed on {value} ({i}, {j})");
|
||||
Assert.AreEqual(value, Get16BitSignedEncodedValue(writer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,5 +126,40 @@ namespace Unity.Netcode.EditorTests
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
|
||||
#if UTP_TRANSPORT_2_0_ABOVE
|
||||
[Test]
|
||||
public void UnityTransport_EmptySecurityStringsShouldThrow([Values("", null)] string cert, [Values("", null)] string secret)
|
||||
{
|
||||
var supportingGO = new GameObject();
|
||||
try
|
||||
{
|
||||
var networkManager = supportingGO.AddComponent<NetworkManager>(); // NM is required for UTP to work with certificates.
|
||||
networkManager.NetworkConfig = new NetworkConfig();
|
||||
UnityTransport transport = supportingGO.AddComponent<UnityTransport>();
|
||||
networkManager.NetworkConfig.NetworkTransport = transport;
|
||||
transport.Initialize();
|
||||
transport.SetServerSecrets(serverCertificate: cert, serverPrivateKey: secret);
|
||||
|
||||
// Use encryption, but don't set certificate and check for exception
|
||||
transport.UseEncryption = true;
|
||||
Assert.Throws<System.Exception>(() =>
|
||||
{
|
||||
networkManager.StartServer();
|
||||
});
|
||||
// Make sure StartServer failed
|
||||
Assert.False(transport.NetworkDriver.IsCreated);
|
||||
Assert.False(networkManager.IsServer);
|
||||
Assert.False(networkManager.IsListening);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (supportingGO != null)
|
||||
{
|
||||
Object.DestroyImmediate(supportingGO);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f672293e0efc41a6a7e930fd7ff14436
|
||||
timeCreated: 1631650280
|
||||
@@ -1,15 +0,0 @@
|
||||
using Unity.Netcode.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
internal static class UITestHelpers
|
||||
{
|
||||
[MenuItem("Netcode/UI/Reset Multiplayer Tools Tip Status")]
|
||||
private static void ResetMultiplayerToolsTipStatus()
|
||||
{
|
||||
PlayerPrefs.DeleteKey(NetworkManagerEditor.InstallMultiplayerToolsTipDismissedPlayerPrefKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bde5fc3349494f77bebd0be12a6957e1
|
||||
timeCreated: 1631650292
|
||||
31
Tests/Editor/XXHashTests.cs
Normal file
31
Tests/Editor/XXHashTests.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class XXHashTests
|
||||
{
|
||||
[Test]
|
||||
public void TestXXHash32Short()
|
||||
{
|
||||
Assert.That("TestStuff".Hash32(), Is.EqualTo(0x64e10c4c));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestXXHash32Long()
|
||||
{
|
||||
Assert.That("TestingHashingWithLongStringValues".Hash32(), Is.EqualTo(0xba3d1783));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestXXHas64Short()
|
||||
{
|
||||
Assert.That("TestStuff".Hash64(), Is.EqualTo(0x4c3be8d82d14a5a9));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestXXHash64Long()
|
||||
{
|
||||
Assert.That("TestingHashingWithLongStringValues".Hash64(), Is.EqualTo(0x5b374f98b10bf246));
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Editor/XXHashTests.cs.meta
Normal file
11
Tests/Editor/XXHashTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9bdc7200b66410286810307554534b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -32,6 +32,11 @@
|
||||
"name": "Unity",
|
||||
"expression": "(0,2022.2.0a5)",
|
||||
"define": "UNITY_UNET_PRESENT"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.transport",
|
||||
"expression": "2.0.0-exp",
|
||||
"define": "UTP_TRANSPORT_2_0_ABOVE"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,14 +45,18 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
private EmptyComponent GetObjectForClient(ulong clientId)
|
||||
{
|
||||
foreach (var component in Object.FindObjectsOfType<EmptyComponent>())
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var emptyComponents = Object.FindObjectsByType<EmptyComponent>(FindObjectsSortMode.InstanceID);
|
||||
#else
|
||||
var emptyComponents = Object.FindObjectsOfType<EmptyComponent>();
|
||||
#endif
|
||||
foreach (var component in emptyComponents)
|
||||
{
|
||||
if (component.IsSpawned && component.NetworkManager.LocalClientId == clientId)
|
||||
{
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -271,14 +271,19 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
private T GetComponentForClient<T>(ulong clientId) where T : NetworkBehaviour
|
||||
{
|
||||
foreach (var component in Object.FindObjectsOfType<T>())
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var componentsToFind = Object.FindObjectsByType<T>(FindObjectsSortMode.InstanceID);
|
||||
#else
|
||||
var componentsToFind = Object.FindObjectsOfType<T>();
|
||||
#endif
|
||||
|
||||
foreach (var component in componentsToFind)
|
||||
{
|
||||
if (component.IsSpawned && component.NetworkManager.LocalClientId == clientId)
|
||||
{
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -639,6 +644,8 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool LogAllMessages => true;
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator WhenMultipleSpawnTriggeredMessagesAreDeferred_TheyAreAllProcessedOnSpawn()
|
||||
{
|
||||
@@ -658,7 +665,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
serverObject.GetComponent<NetworkObject>().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
yield return WaitForAllClientsToReceive<ChangeOwnershipMessage>();
|
||||
yield return WaitForAllClientsToReceive<ChangeOwnershipMessage, NetworkVariableDeltaMessage>();
|
||||
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
{
|
||||
@@ -666,9 +673,9 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.IsTrue(manager.DeferMessageCalled);
|
||||
Assert.IsFalse(manager.ProcessTriggersCalled);
|
||||
|
||||
Assert.AreEqual(3, manager.DeferredMessageCountTotal());
|
||||
Assert.AreEqual(3, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnSpawn));
|
||||
Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredMessageManager.TriggerType.OnSpawn, serverObject.GetComponent<NetworkObject>().NetworkObjectId));
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountTotal());
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnSpawn));
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountForKey(IDeferredMessageManager.TriggerType.OnSpawn, serverObject.GetComponent<NetworkObject>().NetworkObjectId));
|
||||
Assert.AreEqual(0, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnAddPrefab));
|
||||
AddPrefabsToClient(client);
|
||||
}
|
||||
@@ -751,7 +758,13 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
var found1 = false;
|
||||
var found2 = false;
|
||||
foreach (var component in Object.FindObjectsOfType<DeferredMessageTestRpcComponent>())
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var deferredMessageTestRpcComponents = Object.FindObjectsByType<DeferredMessageTestRpcComponent>(FindObjectsSortMode.None);
|
||||
#else
|
||||
var deferredMessageTestRpcComponents = Object.FindObjectsOfType<DeferredMessageTestRpcComponent>();
|
||||
#endif
|
||||
|
||||
foreach (var component in deferredMessageTestRpcComponents)
|
||||
{
|
||||
if (component.IsSpawned && component.NetworkManager.LocalClientId == client.LocalClientId)
|
||||
{
|
||||
@@ -794,7 +807,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
serverObject.GetComponent<NetworkObject>().ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
yield return WaitForAllClientsToReceive<ChangeOwnershipMessage>();
|
||||
yield return WaitForAllClientsToReceive<ChangeOwnershipMessage, NetworkVariableDeltaMessage>();
|
||||
|
||||
// Validate messages are deferred and pending
|
||||
foreach (var client in m_ClientNetworkManagers)
|
||||
@@ -802,9 +815,11 @@ namespace Unity.Netcode.RuntimeTests
|
||||
var manager = (TestDeferredMessageManager)client.DeferredMessageManager;
|
||||
Assert.IsTrue(manager.DeferMessageCalled);
|
||||
Assert.IsFalse(manager.ProcessTriggersCalled);
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountTotal());
|
||||
Assert.AreEqual(3, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnSpawn));
|
||||
Assert.AreEqual(3, manager.DeferredMessageCountForKey(IDeferredMessageManager.TriggerType.OnSpawn, serverObject.GetComponent<NetworkObject>().NetworkObjectId));
|
||||
|
||||
Assert.AreEqual(5, manager.DeferredMessageCountTotal());
|
||||
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnSpawn));
|
||||
Assert.AreEqual(4, manager.DeferredMessageCountForKey(IDeferredMessageManager.TriggerType.OnSpawn, serverObject.GetComponent<NetworkObject>().NetworkObjectId));
|
||||
Assert.AreEqual(1, manager.DeferredMessageCountForType(IDeferredMessageManager.TriggerType.OnAddPrefab));
|
||||
Assert.AreEqual(1, manager.DeferredMessageCountForKey(IDeferredMessageManager.TriggerType.OnAddPrefab, serverObject.GetComponent<NetworkObject>().GlobalObjectIdHash));
|
||||
AddPrefabsToClient(client);
|
||||
|
||||
@@ -29,10 +29,15 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
// Check the condition for this test and automatically handle varying processing
|
||||
// environments and conditions
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsByType<NetworkVisibilityComponent>(FindObjectsSortMode.None).Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
#else
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsOfType<NetworkVisibilityComponent>().Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
|
||||
#endif
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " +
|
||||
"to be detected!");
|
||||
}
|
||||
@@ -64,9 +69,15 @@ namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
// Check the condition for this test and automatically handle varying processing
|
||||
// environments and conditions
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsByType<NetworkVisibilityComponent>(FindObjectsSortMode.None).Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
#else
|
||||
yield return WaitForConditionOrTimeOut(() =>
|
||||
Object.FindObjectsOfType<NetworkVisibilityComponent>().Where(
|
||||
(c) => c.IsSpawned).Count() == 2);
|
||||
#endif
|
||||
|
||||
Assert.False(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for instances " +
|
||||
"to be detected!");
|
||||
|
||||
93
Tests/Runtime/Messaging/DisconnectReasonTests.cs
Normal file
93
Tests/Runtime/Messaging/DisconnectReasonTests.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Text.RegularExpressions;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class DisconnectReasonObject : NetworkBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class DisconnectReasonTests : NetcodeIntegrationTest
|
||||
{
|
||||
protected override int NumberOfClients => 2;
|
||||
|
||||
private GameObject m_PrefabToSpawn;
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_PrefabToSpawn = CreateNetworkObjectPrefab("DisconnectReasonObject");
|
||||
m_PrefabToSpawn.AddComponent<DisconnectReasonObject>();
|
||||
}
|
||||
|
||||
private int m_DisconnectCount;
|
||||
private bool m_ThrowOnDisconnect = false;
|
||||
|
||||
public void OnClientDisconnectCallback(ulong clientId)
|
||||
{
|
||||
m_DisconnectCount++;
|
||||
if (m_ThrowOnDisconnect)
|
||||
{
|
||||
throw new SystemException("whatever");
|
||||
}
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator DisconnectReasonTest()
|
||||
{
|
||||
float startTime = Time.realtimeSinceStartup;
|
||||
m_ThrowOnDisconnect = false;
|
||||
m_DisconnectCount = 0;
|
||||
|
||||
// Add a callback for both clients, when they get disconnected
|
||||
m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback;
|
||||
m_ClientNetworkManagers[1].OnClientDisconnectCallback += OnClientDisconnectCallback;
|
||||
|
||||
// Disconnect both clients, from the server
|
||||
m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[0].LocalClientId, "Bogus reason 1");
|
||||
m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[1].LocalClientId, "Bogus reason 2");
|
||||
|
||||
while (m_DisconnectCount < 2 && Time.realtimeSinceStartup < startTime + 10.0f)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Assert.AreEqual(m_ClientNetworkManagers[0].DisconnectReason, "Bogus reason 1");
|
||||
Assert.AreEqual(m_ClientNetworkManagers[1].DisconnectReason, "Bogus reason 2");
|
||||
|
||||
Debug.Assert(m_DisconnectCount == 2);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator DisconnectExceptionTest()
|
||||
{
|
||||
m_ThrowOnDisconnect = true;
|
||||
m_DisconnectCount = 0;
|
||||
float startTime = Time.realtimeSinceStartup;
|
||||
|
||||
// Add a callback for first client, when they get disconnected
|
||||
m_ClientNetworkManagers[0].OnClientDisconnectCallback += OnClientDisconnectCallback;
|
||||
m_ClientNetworkManagers[1].OnClientDisconnectCallback += OnClientDisconnectCallback;
|
||||
|
||||
// Disconnect first client, from the server
|
||||
LogAssert.Expect(LogType.Exception, new Regex(".*whatever.*"));
|
||||
m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// Disconnect second client, from the server
|
||||
LogAssert.Expect(LogType.Exception, new Regex(".*whatever.*"));
|
||||
m_ServerNetworkManager.DisconnectClient(m_ClientNetworkManagers[1].LocalClientId);
|
||||
|
||||
while (m_DisconnectCount < 2 && Time.realtimeSinceStartup < startTime + 10.0f)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Debug.Assert(m_DisconnectCount == 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Tests/Runtime/Messaging/DisconnectReasonTests.cs.meta
Normal file
11
Tests/Runtime/Messaging/DisconnectReasonTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93141fa15824f406b89dbc6f32c8910d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -3,7 +3,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
@@ -27,16 +26,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator NamedMessageIsReceivedOnClientWithContent()
|
||||
{
|
||||
var messageName = Guid.NewGuid().ToString();
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(
|
||||
messageName,
|
||||
FirstClient.LocalClientId,
|
||||
writer);
|
||||
}
|
||||
|
||||
ulong receivedMessageSender = 0;
|
||||
var receivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
@@ -49,7 +38,49 @@ namespace Unity.Netcode.RuntimeTests
|
||||
reader.ReadValueSafe(out receivedMessageContent);
|
||||
});
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(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<NamedMessage>(new List<NetworkManager> { 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<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
receivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out receivedMessageContent);
|
||||
});
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(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);
|
||||
@@ -59,16 +90,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
public IEnumerator NamedMessageIsReceivedOnMultipleClientsWithContent()
|
||||
{
|
||||
var messageName = Guid.NewGuid().ToString();
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(
|
||||
messageName,
|
||||
new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId },
|
||||
writer);
|
||||
}
|
||||
|
||||
ulong firstReceivedMessageSender = 0;
|
||||
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
@@ -92,19 +113,78 @@ namespace Unity.Netcode.RuntimeTests
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
});
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
ulong thirdReceivedMessageSender = 0;
|
||||
var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
thirdReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out thirdReceivedMessageContent);
|
||||
});
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendNamedMessage(
|
||||
messageName,
|
||||
new List<ulong> { m_ServerNetworkManager.LocalClientId, FirstClient.LocalClientId, SecondClient.LocalClientId },
|
||||
writer);
|
||||
}
|
||||
|
||||
yield return WaitForMessageReceived<NamedMessage>(new List<NetworkManager> { 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<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
firstReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out firstReceivedMessageContent);
|
||||
});
|
||||
|
||||
ulong secondReceivedMessageSender = 0;
|
||||
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
SecondClient.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
secondReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
});
|
||||
|
||||
ulong thirdReceivedMessageSender = 0;
|
||||
var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
thirdReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out thirdReceivedMessageContent);
|
||||
});
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
@@ -113,35 +193,16 @@ namespace Unity.Netcode.RuntimeTests
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendNamedMessageToAll(messageName, writer);
|
||||
}
|
||||
|
||||
ulong firstReceivedMessageSender = 0;
|
||||
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
firstReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out firstReceivedMessageContent);
|
||||
});
|
||||
|
||||
ulong secondReceivedMessageSender = 0;
|
||||
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
SecondClient.CustomMessagingManager.RegisterNamedMessageHandler(
|
||||
messageName,
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
secondReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
});
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return WaitForMessageReceived<NamedMessage>(new List<NetworkManager> { 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]
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
@@ -19,16 +18,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator UnnamedMessageIsReceivedOnClientWithContent()
|
||||
{
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(
|
||||
FirstClient.LocalClientId,
|
||||
writer);
|
||||
}
|
||||
|
||||
ulong receivedMessageSender = 0;
|
||||
var receivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
@@ -39,7 +28,44 @@ namespace Unity.Netcode.RuntimeTests
|
||||
reader.ReadValueSafe(out receivedMessageContent);
|
||||
};
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(
|
||||
FirstClient.LocalClientId,
|
||||
writer);
|
||||
}
|
||||
|
||||
yield return WaitForMessageReceived<UnnamedMessage>(new List<NetworkManager> { FirstClient });
|
||||
|
||||
Assert.AreEqual(messageContent.Value, receivedMessageContent.Value);
|
||||
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnnamedMessageIsReceivedOnHostWithContent()
|
||||
{
|
||||
ulong receivedMessageSender = 0;
|
||||
var receivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
receivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out receivedMessageContent);
|
||||
};
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(
|
||||
m_ServerNetworkManager.LocalClientId,
|
||||
writer);
|
||||
}
|
||||
|
||||
Assert.AreEqual(messageContent.Value, receivedMessageContent.Value);
|
||||
Assert.AreEqual(m_ServerNetworkManager.LocalClientId, receivedMessageSender);
|
||||
@@ -48,16 +74,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator UnnamedMessageIsReceivedOnMultipleClientsWithContent()
|
||||
{
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(
|
||||
new List<ulong> { FirstClient.LocalClientId, SecondClient.LocalClientId },
|
||||
writer);
|
||||
}
|
||||
|
||||
ulong firstReceivedMessageSender = 0;
|
||||
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
@@ -78,18 +94,71 @@ namespace Unity.Netcode.RuntimeTests
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
};
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
ulong thirdReceivedMessageSender = 0;
|
||||
var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
thirdReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out thirdReceivedMessageContent);
|
||||
};
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
{
|
||||
writer.WriteValueSafe(messageContent);
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessage(
|
||||
new List<ulong> { m_ServerNetworkManager.LocalClientId, FirstClient.LocalClientId, SecondClient.LocalClientId },
|
||||
writer);
|
||||
}
|
||||
|
||||
yield return WaitForMessageReceived<UnnamedMessage>(new List<NetworkManager> { 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 WhenSendingUnnamedMessageToAll_AllClientsReceiveIt()
|
||||
{
|
||||
ulong firstReceivedMessageSender = 0;
|
||||
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
firstReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out firstReceivedMessageContent);
|
||||
};
|
||||
|
||||
ulong secondReceivedMessageSender = 0;
|
||||
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
SecondClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
secondReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
};
|
||||
|
||||
ulong thirdReceivedMessageSender = 0;
|
||||
var thirdReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
m_ServerNetworkManager.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
thirdReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out thirdReceivedMessageContent);
|
||||
};
|
||||
|
||||
var messageContent = new ForceNetworkSerializeByMemcpy<Guid>(Guid.NewGuid());
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp);
|
||||
using (writer)
|
||||
@@ -98,33 +167,16 @@ namespace Unity.Netcode.RuntimeTests
|
||||
m_ServerNetworkManager.CustomMessagingManager.SendUnnamedMessageToAll(writer);
|
||||
}
|
||||
|
||||
ulong firstReceivedMessageSender = 0;
|
||||
var firstReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
FirstClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
firstReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out firstReceivedMessageContent);
|
||||
};
|
||||
|
||||
ulong secondReceivedMessageSender = 0;
|
||||
var secondReceivedMessageContent = new ForceNetworkSerializeByMemcpy<Guid>(new Guid());
|
||||
SecondClient.CustomMessagingManager.OnUnnamedMessage +=
|
||||
(ulong sender, FastBufferReader reader) =>
|
||||
{
|
||||
secondReceivedMessageSender = sender;
|
||||
|
||||
reader.ReadValueSafe(out secondReceivedMessageContent);
|
||||
};
|
||||
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
yield return WaitForMessageReceived<UnnamedMessage>(new List<NetworkManager> { 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]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
@@ -43,6 +44,18 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
return networkObject;
|
||||
}
|
||||
|
||||
private int GetWriteSizeForOwnerChange(NetworkObject networkObject, ulong newOwner)
|
||||
{
|
||||
var message = new ChangeOwnershipMessage
|
||||
{
|
||||
NetworkObjectId = networkObject.NetworkObjectId,
|
||||
OwnerClientId = newOwner
|
||||
};
|
||||
using var writer = new FastBufferWriter(1024, Allocator.Temp);
|
||||
message.Serialize(writer, message.Version);
|
||||
return writer.Length;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackOwnershipChangeSentMetric()
|
||||
{
|
||||
@@ -68,7 +81,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
ownershipChangeSent = metricValues.Last();
|
||||
Assert.AreEqual(networkObject.NetworkObjectId, ownershipChangeSent.NetworkId.NetworkId);
|
||||
Assert.AreEqual(Client.LocalClientId, ownershipChangeSent.Connection.Id);
|
||||
Assert.AreEqual(FastBufferWriter.GetWriteSize<ChangeOwnershipMessage>() + k_MessageHeaderSize, ownershipChangeSent.BytesCount);
|
||||
|
||||
var serializedLength = GetWriteSizeForOwnerChange(networkObject, 1);
|
||||
Assert.AreEqual(serializedLength + k_MessageHeaderSize, ownershipChangeSent.BytesCount);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
@@ -89,7 +104,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
|
||||
var ownershipChangeReceived = metricValues.First();
|
||||
Assert.AreEqual(networkObject.NetworkObjectId, ownershipChangeReceived.NetworkId.NetworkId);
|
||||
Assert.AreEqual(FastBufferWriter.GetWriteSize<ChangeOwnershipMessage>(), ownershipChangeReceived.BytesCount);
|
||||
|
||||
var serializedLength = GetWriteSizeForOwnerChange(networkObject, 1);
|
||||
Assert.AreEqual(serializedLength, ownershipChangeReceived.BytesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Multiplayer.Tools.MetricTypes;
|
||||
using UnityEngine.TestTools;
|
||||
using Unity.Netcode.TestHelpers.Runtime.Metrics;
|
||||
@@ -11,10 +12,8 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
{
|
||||
internal class ServerLogsMetricTests : SingleClientMetricTestBase
|
||||
{
|
||||
// Header is dynamically sized due to packing, will be 2 bytes for all test messages.
|
||||
private const int k_MessageHeaderSize = 2;
|
||||
private static readonly int k_ServerLogSentMessageOverhead = 2 + k_MessageHeaderSize;
|
||||
private static readonly int k_ServerLogReceivedMessageOverhead = 2;
|
||||
// Header is dynamically sized due to packing, will be 3 bytes for all test messages.
|
||||
private const int k_MessageHeaderSize = 3;
|
||||
|
||||
protected override IEnumerator OnSetup()
|
||||
{
|
||||
@@ -22,6 +21,19 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
return base.OnSetup();
|
||||
}
|
||||
|
||||
|
||||
private int GetWriteSizeForLog(NetworkLog.LogType logType, string logMessage)
|
||||
{
|
||||
var message = new ServerLogMessage
|
||||
{
|
||||
LogType = logType,
|
||||
Message = logMessage
|
||||
};
|
||||
using var writer = new FastBufferWriter(1024, Allocator.Temp);
|
||||
message.Serialize(writer, message.Version);
|
||||
return writer.Length;
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator TrackServerLogSentMetric()
|
||||
{
|
||||
@@ -41,7 +53,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
var sentMetric = sentMetrics.First();
|
||||
Assert.AreEqual(Server.LocalClientId, sentMetric.Connection.Id);
|
||||
Assert.AreEqual((uint)NetworkLog.LogType.Warning, (uint)sentMetric.LogLevel);
|
||||
Assert.AreEqual(message.Length + k_ServerLogSentMessageOverhead, sentMetric.BytesCount);
|
||||
|
||||
var serializedLength = GetWriteSizeForLog(NetworkLog.LogType.Warning, message);
|
||||
Assert.AreEqual(serializedLength + k_MessageHeaderSize, sentMetric.BytesCount);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
@@ -64,7 +78,9 @@ namespace Unity.Netcode.RuntimeTests.Metrics
|
||||
var receivedMetric = receivedMetrics.First();
|
||||
Assert.AreEqual(Client.LocalClientId, receivedMetric.Connection.Id);
|
||||
Assert.AreEqual((uint)NetworkLog.LogType.Warning, (uint)receivedMetric.LogLevel);
|
||||
Assert.AreEqual(message.Length + k_ServerLogReceivedMessageOverhead, receivedMetric.BytesCount);
|
||||
|
||||
var serializedLength = GetWriteSizeForLog(NetworkLog.LogType.Warning, message);
|
||||
Assert.AreEqual(serializedLength, receivedMetric.BytesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,12 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.IsFalse(serverBehaviour.IsOwnedByServer);
|
||||
Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, serverBehaviour.OwnerClientId);
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var clientObject = Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.InstanceID).Where((obj) => obj.NetworkManagerOwner == m_ClientNetworkManagers[0]).FirstOrDefault();
|
||||
#else
|
||||
var clientObject = Object.FindObjectsOfType<NetworkObject>().Where((obj) => obj.NetworkManagerOwner == m_ClientNetworkManagers[0]).FirstOrDefault();
|
||||
#endif
|
||||
|
||||
|
||||
Assert.IsNotNull(clientObject);
|
||||
Assert.IsTrue(clientObject.IsOwner);
|
||||
|
||||
@@ -1,233 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkObjectSceneSerializationTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The purpose behind this test is to assure that in-scene NetworkObjects
|
||||
/// that are serialized into a single stream (approval or switch scene this happens)
|
||||
/// will continue to be processed even if one of the NetworkObjects is invalid.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NetworkObjectSceneSerializationFailure()
|
||||
{
|
||||
var networkObjectsToTest = new List<GameObject>();
|
||||
|
||||
var writer = new FastBufferWriter(1300, Allocator.Temp, 4096000);
|
||||
var invalidNetworkObjectOffsets = new List<long>();
|
||||
var invalidNetworkObjectIdCount = new List<int>();
|
||||
var invalidNetworkObjects = new List<GameObject>();
|
||||
var invalidNetworkObjectFrequency = 3;
|
||||
using (writer)
|
||||
{
|
||||
// Construct 50 NetworkObjects
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
// Inject an invalid NetworkObject every [invalidNetworkObjectFrequency] entry
|
||||
if ((i % invalidNetworkObjectFrequency) == 0)
|
||||
{
|
||||
// Create the invalid NetworkObject
|
||||
var gameObject = new GameObject($"InvalidTestObject{i}");
|
||||
|
||||
Assert.IsNotNull(gameObject);
|
||||
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
|
||||
Assert.IsNotNull(networkObject);
|
||||
|
||||
var networkVariableComponent = gameObject.AddComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
Assert.IsNotNull(networkVariableComponent);
|
||||
|
||||
// Add invalid NetworkObject's starting position before serialization to handle trapping for the Debug.LogError message
|
||||
// that we know will be thrown
|
||||
invalidNetworkObjectOffsets.Add(writer.Position);
|
||||
|
||||
networkObject.GlobalObjectIdHash = (uint)(i);
|
||||
invalidNetworkObjectIdCount.Add(i);
|
||||
|
||||
invalidNetworkObjects.Add(gameObject);
|
||||
|
||||
writer.WriteValueSafe((int)networkObject.GetSceneOriginHandle());
|
||||
// Serialize the invalid NetworkObject
|
||||
var sceneObject = networkObject.GetMessageSceneObject(0);
|
||||
var prePosition = writer.Position;
|
||||
sceneObject.Serialize(writer);
|
||||
|
||||
Debug.Log(
|
||||
$"Invalid {nameof(NetworkObject)} Size {writer.Position - prePosition}");
|
||||
|
||||
// Now adjust how frequent we will inject invalid NetworkObjects
|
||||
invalidNetworkObjectFrequency = Random.Range(2, 5);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a valid NetworkObject
|
||||
var gameObject = new GameObject($"TestObject{i}");
|
||||
|
||||
Assert.IsNotNull(gameObject);
|
||||
|
||||
var networkObject = gameObject.AddComponent<NetworkObject>();
|
||||
|
||||
var networkVariableComponent = gameObject.AddComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
Assert.IsNotNull(networkVariableComponent);
|
||||
|
||||
Assert.IsNotNull(networkObject);
|
||||
|
||||
networkObject.GlobalObjectIdHash = (uint)(i + 4096);
|
||||
|
||||
networkObjectsToTest.Add(gameObject);
|
||||
|
||||
writer.WriteValueSafe(networkObject.GetSceneOriginHandle());
|
||||
|
||||
// Handle populating the scenes loaded list
|
||||
var scene = networkObject.gameObject.scene;
|
||||
|
||||
if (!NetworkManagerHelper.NetworkManagerObject.SceneManager.ScenesLoaded.ContainsKey(
|
||||
scene.handle))
|
||||
{
|
||||
NetworkManagerHelper.NetworkManagerObject.SceneManager.ScenesLoaded
|
||||
.Add(scene.handle, scene);
|
||||
}
|
||||
var handle = networkObject.GetSceneOriginHandle();
|
||||
// Since this is a unit test, we will fake the server to client handle lookup by just adding the same handle key and value
|
||||
if (!NetworkManagerHelper.NetworkManagerObject.SceneManager.ServerSceneHandleToClientSceneHandle
|
||||
.ContainsKey(handle))
|
||||
{
|
||||
NetworkManagerHelper.NetworkManagerObject.SceneManager.ServerSceneHandleToClientSceneHandle
|
||||
.Add(handle, handle);
|
||||
}
|
||||
|
||||
// Serialize the valid NetworkObject
|
||||
var sceneObject = networkObject.GetMessageSceneObject(0);
|
||||
sceneObject.Serialize(writer);
|
||||
|
||||
if (!NetworkManagerHelper.NetworkManagerObject.SceneManager.ScenePlacedObjects.ContainsKey(
|
||||
networkObject.GlobalObjectIdHash))
|
||||
{
|
||||
NetworkManagerHelper.NetworkManagerObject.SceneManager.ScenePlacedObjects.Add(
|
||||
networkObject.GlobalObjectIdHash, new Dictionary<int, NetworkObject>());
|
||||
}
|
||||
|
||||
// Add this valid NetworkObject into the ScenePlacedObjects list
|
||||
NetworkManagerHelper.NetworkManagerObject.SceneManager
|
||||
.ScenePlacedObjects[networkObject.GlobalObjectIdHash]
|
||||
.Add(SceneManager.GetActiveScene().handle, networkObject);
|
||||
}
|
||||
}
|
||||
|
||||
var totalBufferSize = writer.Position;
|
||||
|
||||
var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
using (reader)
|
||||
{
|
||||
|
||||
var networkObjectsDeSerialized = new List<NetworkObject>();
|
||||
var currentLogLevel = NetworkManager.Singleton.LogLevel;
|
||||
var invalidNetworkObjectCount = 0;
|
||||
while (reader.Position != totalBufferSize)
|
||||
{
|
||||
// If we reach the point where we expect it to fail, then make sure we let TestRunner know it should expect this log error message
|
||||
if (invalidNetworkObjectOffsets.Count > 0 &&
|
||||
reader.Position == invalidNetworkObjectOffsets[0])
|
||||
{
|
||||
invalidNetworkObjectOffsets.RemoveAt(0);
|
||||
|
||||
// Turn off Network Logging to avoid other errors that we know will happen after the below LogAssert.Expect message occurs.
|
||||
NetworkManager.Singleton.LogLevel = LogLevel.Nothing;
|
||||
|
||||
// Trap for this specific error message so we don't make Test Runner think we failed (it will fail on Debug.LogError)
|
||||
UnityEngine.TestTools.LogAssert.Expect(LogType.Error,
|
||||
$"Failed to spawn {nameof(NetworkObject)} for Hash {invalidNetworkObjectIdCount[invalidNetworkObjectCount]}.");
|
||||
|
||||
invalidNetworkObjectCount++;
|
||||
}
|
||||
|
||||
|
||||
reader.ReadValueSafe(out int handle);
|
||||
NetworkManagerHelper.NetworkManagerObject.SceneManager.SetTheSceneBeingSynchronized(handle);
|
||||
var sceneObject = new NetworkObject.SceneObject();
|
||||
sceneObject.Deserialize(reader);
|
||||
|
||||
var deserializedNetworkObject = NetworkObject.AddSceneObject(sceneObject, reader,
|
||||
NetworkManagerHelper.NetworkManagerObject);
|
||||
if (deserializedNetworkObject != null)
|
||||
{
|
||||
networkObjectsDeSerialized.Add(deserializedNetworkObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Under this condition, we are expecting null (i.e. no NetworkObject instantiated)
|
||||
// and will set our log level back to the original value to assure the valid NetworkObjects
|
||||
// aren't causing any log Errors to occur
|
||||
NetworkManager.Singleton.LogLevel = currentLogLevel;
|
||||
}
|
||||
}
|
||||
|
||||
// Now validate all NetworkObjects returned against the original NetworkObjects we created
|
||||
// after they validate, destroy the objects
|
||||
foreach (var entry in networkObjectsToTest)
|
||||
{
|
||||
var entryNetworkObject = entry.GetComponent<NetworkObject>();
|
||||
Assert.IsTrue(networkObjectsDeSerialized.Contains(entryNetworkObject));
|
||||
Object.Destroy(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the invalid network objects
|
||||
foreach (var entry in invalidNetworkObjects)
|
||||
{
|
||||
Object.Destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
// Create, instantiate, and host
|
||||
NetworkManagerHelper.StartNetworkManager(out NetworkManager networkManager, NetworkManagerHelper.NetworkManagerOperatingMode.None);
|
||||
networkManager.NetworkConfig.EnableSceneManagement = true;
|
||||
networkManager.StartHost();
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
// Stop, shutdown, and destroy
|
||||
NetworkManagerHelper.ShutdownNetworkManager();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A simple test class that will provide varying NetworkBuffer stream sizes
|
||||
/// when the NetworkVariable is serialized
|
||||
/// </summary>
|
||||
public class NetworkBehaviourWithNetworkVariables : NetworkBehaviour
|
||||
{
|
||||
private const uint k_MinDataBlocks = 1;
|
||||
private const uint k_MaxDataBlocks = 64;
|
||||
|
||||
public NetworkList<ulong> NetworkVariableData;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
var dataBlocksAssigned = new List<ulong>();
|
||||
var numberDataBlocks = Random.Range(k_MinDataBlocks, k_MaxDataBlocks);
|
||||
for (var i = 0; i < numberDataBlocks; i++)
|
||||
{
|
||||
dataBlocksAssigned.Add((ulong)Random.Range(0.0f, float.MaxValue));
|
||||
}
|
||||
|
||||
NetworkVariableData = new NetworkList<ulong>(dataBlocksAssigned);
|
||||
}
|
||||
}
|
||||
}
|
||||
624
Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs
Normal file
624
Tests/Runtime/NetworkObject/NetworkObjectSynchronizationTests.cs
Normal file
@@ -0,0 +1,624 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.TestHelpers.Runtime;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
[TestFixture(VariableLengthSafety.DisableNetVarSafety, HostOrServer.Host)]
|
||||
[TestFixture(VariableLengthSafety.EnabledNetVarSafety, HostOrServer.Host)]
|
||||
[TestFixture(VariableLengthSafety.DisableNetVarSafety, HostOrServer.Server)]
|
||||
[TestFixture(VariableLengthSafety.EnabledNetVarSafety, HostOrServer.Server)]
|
||||
public class NetworkObjectSynchronizationTests : NetcodeIntegrationTest
|
||||
{
|
||||
private const int k_NumberToSpawn = 30;
|
||||
protected override int NumberOfClients => 0;
|
||||
|
||||
private GameObject m_NetworkPrefab;
|
||||
private GameObject m_InValidNetworkPrefab;
|
||||
private GameObject m_SynchronizationPrefab;
|
||||
private GameObject m_OnSynchronizePrefab;
|
||||
private VariableLengthSafety m_VariableLengthSafety;
|
||||
|
||||
private LogLevel m_CurrentLogLevel;
|
||||
|
||||
public enum VariableLengthSafety
|
||||
{
|
||||
DisableNetVarSafety,
|
||||
EnabledNetVarSafety,
|
||||
}
|
||||
|
||||
public NetworkObjectSynchronizationTests(VariableLengthSafety variableLengthSafety, HostOrServer hostOrServer)
|
||||
{
|
||||
m_VariableLengthSafety = variableLengthSafety;
|
||||
m_UseHost = hostOrServer == HostOrServer.Host;
|
||||
}
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
m_PlayerPrefab.AddComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
base.OnCreatePlayerPrefab();
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
|
||||
// Set the NetworkVariable Safety Check setting
|
||||
m_ServerNetworkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety;
|
||||
|
||||
// Ignore the errors generated during this test (they are expected)
|
||||
m_ServerNetworkManager.LogLevel = LogLevel.Nothing;
|
||||
|
||||
// Disable forcing the same prefabs to avoid failed connections
|
||||
m_ServerNetworkManager.NetworkConfig.ForceSamePrefabs = false;
|
||||
|
||||
// Create the valid network prefab
|
||||
m_NetworkPrefab = CreateNetworkObjectPrefab("ValidObject");
|
||||
m_NetworkPrefab.AddComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
|
||||
// Create the invalid network prefab (that will fail on client side)
|
||||
m_InValidNetworkPrefab = CreateNetworkObjectPrefab("InvalidObject");
|
||||
m_InValidNetworkPrefab.AddComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
|
||||
// Create the synchronization network prefab (some pass and some fail)
|
||||
m_SynchronizationPrefab = CreateNetworkObjectPrefab("SyncObject");
|
||||
m_SynchronizationPrefab.AddComponent<NetworkBehaviourSynchronizeFailureComponent>();
|
||||
m_SynchronizationPrefab.AddComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
|
||||
m_OnSynchronizePrefab = CreateNetworkObjectPrefab("OnSyncObject");
|
||||
m_OnSynchronizePrefab.AddComponent<NetworkBehaviourOnSynchronizeComponent>();
|
||||
|
||||
base.OnServerAndClientsCreated();
|
||||
}
|
||||
|
||||
protected override void OnNewClientCreated(NetworkManager networkManager)
|
||||
{
|
||||
networkManager.NetworkConfig.PlayerPrefab = m_PlayerPrefab;
|
||||
networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety = m_VariableLengthSafety == VariableLengthSafety.EnabledNetVarSafety;
|
||||
foreach (var networkPrefab in m_ServerNetworkManager.NetworkConfig.NetworkPrefabs)
|
||||
{
|
||||
// To simulate a failure, we exclude the m_InValidNetworkPrefab from the connecting
|
||||
// client's side.
|
||||
if (networkPrefab.Prefab.name != m_InValidNetworkPrefab.name)
|
||||
{
|
||||
networkManager.NetworkConfig.NetworkPrefabs.Add(networkPrefab);
|
||||
}
|
||||
}
|
||||
// Disable forcing the same prefabs to avoid failed connections
|
||||
networkManager.NetworkConfig.ForceSamePrefabs = false;
|
||||
networkManager.LogLevel = m_CurrentLogLevel;
|
||||
base.OnNewClientCreated(networkManager);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkObjectDeserializationFailure()
|
||||
{
|
||||
m_CurrentLogLevel = LogLevel.Nothing;
|
||||
var validSpawnedNetworkObjects = new List<GameObject>();
|
||||
NetworkBehaviourWithNetworkVariables.ResetSpawnCount();
|
||||
|
||||
// Spawn NetworkObjects on the server side with half of them being the
|
||||
// invalid network prefabs to simulate NetworkObject synchronization failure
|
||||
for (int i = 0; i < k_NumberToSpawn; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
SpawnObject(m_InValidNetworkPrefab, m_ServerNetworkManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep track of the prefabs that should successfully spawn on the client side
|
||||
validSpawnedNetworkObjects.Add(SpawnObject(m_NetworkPrefab, m_ServerNetworkManager));
|
||||
}
|
||||
}
|
||||
|
||||
// Assure the server-side spawned all NetworkObjects
|
||||
yield return WaitForConditionOrTimeOut(() => NetworkBehaviourWithNetworkVariables.ServerSpawnCount == k_NumberToSpawn);
|
||||
|
||||
// Now spawn and connect a client that will fail to spawn half of the NetworkObjects spawned
|
||||
yield return CreateAndStartNewClient();
|
||||
|
||||
if (m_UseHost)
|
||||
{
|
||||
var serverSideClientPlayerComponent = m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId][m_ClientNetworkManagers[0].LocalClientId].GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var serverSideHostPlayerComponent = m_ServerNetworkManager.LocalClient.PlayerObject.GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientSidePlayerComponent = m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientSideHostPlayerComponent = m_PlayerNetworkObjects[m_ClientNetworkManagers[0].LocalClientId][m_ServerNetworkManager.LocalClientId].GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
|
||||
// Validate that the client side player values match the server side value of the client's player
|
||||
Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData1.Value == clientSidePlayerComponent.NetworkVariableData1.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Client Player] Client side value ({serverSideClientPlayerComponent.NetworkVariableData1.Value})" +
|
||||
$" does not equal the server side value ({serverSideClientPlayerComponent.NetworkVariableData1.Value})!");
|
||||
Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData2.Value == clientSidePlayerComponent.NetworkVariableData2.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Client Player] Client side value ({serverSideClientPlayerComponent.NetworkVariableData2.Value})" +
|
||||
$" does not equal the server side value ({serverSideClientPlayerComponent.NetworkVariableData2.Value})!");
|
||||
Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData3.Value == clientSidePlayerComponent.NetworkVariableData3.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Client Player] Client side value ({serverSideClientPlayerComponent.NetworkVariableData3.Value})" +
|
||||
$" does not equal the server side value ({serverSideClientPlayerComponent.NetworkVariableData3.Value})!");
|
||||
Assert.IsTrue(serverSideClientPlayerComponent.NetworkVariableData4.Value == clientSidePlayerComponent.NetworkVariableData4.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Client Player] Client side value ({serverSideClientPlayerComponent.NetworkVariableData4.Value})" +
|
||||
$" does not equal the server side value ({serverSideClientPlayerComponent.NetworkVariableData4.Value})!");
|
||||
|
||||
|
||||
// Validate that only the 2nd and 4th NetworkVariable on the client side instance of the host's player is the same and the other two do not match
|
||||
// (i.e. NetworkVariables owned by the server should not get synchronized on client)
|
||||
Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData1.Value != clientSideHostPlayerComponent.NetworkVariableData1.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Host Player] Client side value ({serverSideHostPlayerComponent.NetworkVariableData1.Value})" +
|
||||
$" should not be equal to the server side value ({clientSideHostPlayerComponent.NetworkVariableData1.Value})!");
|
||||
Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData2.Value == clientSideHostPlayerComponent.NetworkVariableData2.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Host Player] Client side value ({serverSideHostPlayerComponent.NetworkVariableData2.Value})" +
|
||||
$" does not equal the server side value ({clientSideHostPlayerComponent.NetworkVariableData2.Value})!");
|
||||
Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData3.Value != clientSideHostPlayerComponent.NetworkVariableData3.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Host Player] Client side value ({serverSideHostPlayerComponent.NetworkVariableData3.Value})" +
|
||||
$" should not be equal to the server side value ({clientSideHostPlayerComponent.NetworkVariableData3.Value})!");
|
||||
Assert.IsTrue(serverSideHostPlayerComponent.NetworkVariableData4.Value == clientSideHostPlayerComponent.NetworkVariableData4.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Host Player] Client side value ({serverSideHostPlayerComponent.NetworkVariableData4.Value})" +
|
||||
$" does not equal the server side value ({clientSideHostPlayerComponent.NetworkVariableData4.Value})!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Spawn and connect another client when running as a server
|
||||
yield return CreateAndStartNewClient();
|
||||
yield return WaitForConditionOrTimeOut(() => m_PlayerNetworkObjects[2].Count > 1);
|
||||
AssertOnTimeout($"Timed out waiting for second client to have access to the first client's cloned player object!");
|
||||
|
||||
var clientSide1PlayerComponent = m_ClientNetworkManagers[0].LocalClient.PlayerObject.GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientSide2Player1Clone = m_PlayerNetworkObjects[2][clientSide1PlayerComponent.OwnerClientId].GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientOneId = clientSide1PlayerComponent.OwnerClientId;
|
||||
|
||||
var clientSide2PlayerComponent = m_ClientNetworkManagers[1].LocalClient.PlayerObject.GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientSide1Player2Clone = m_PlayerNetworkObjects[1][clientSide2PlayerComponent.OwnerClientId].GetComponent<NetworkBehaviourWithOwnerNetworkVariables>();
|
||||
var clientTwoId = clientSide2PlayerComponent.OwnerClientId;
|
||||
|
||||
// Validate that client one's 2nd and 4th NetworkVariables for the local and clone instances match and the other two do not
|
||||
Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData1.Value != clientSide2Player1Clone.NetworkVariableData1.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData1.Value})" +
|
||||
$" should not be equal to Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData1.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData2.Value == clientSide2Player1Clone.NetworkVariableData2.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData2.Value})" +
|
||||
$" does not equal Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData2.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData3.Value != clientSide2Player1Clone.NetworkVariableData3.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData3.Value})" +
|
||||
$" should not be equal to Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData3.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide1PlayerComponent.NetworkVariableData4.Value == clientSide2Player1Clone.NetworkVariableData4.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Player-{clientOneId}] Client-{clientOneId} value ({clientSide1PlayerComponent.NetworkVariableData4.Value})" +
|
||||
$" does not equal Client-{clientTwoId}'s clone side value ({clientSide2Player1Clone.NetworkVariableData4.Value})!");
|
||||
|
||||
|
||||
// Validate that client two's 2nd and 4th NetworkVariables for the local and clone instances match and the other two do not
|
||||
Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData1.Value != clientSide1Player2Clone.NetworkVariableData1.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData1)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData1.Value})" +
|
||||
$" should not be equal to Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData1.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData2.Value == clientSide1Player2Clone.NetworkVariableData2.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData2)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData2.Value})" +
|
||||
$" does not equal Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData2.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData3.Value != clientSide1Player2Clone.NetworkVariableData3.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData3)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData3.Value})" +
|
||||
$" should not be equal to Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData3.Value})!");
|
||||
|
||||
Assert.IsTrue(clientSide2PlayerComponent.NetworkVariableData4.Value == clientSide1Player2Clone.NetworkVariableData4.Value,
|
||||
$"[{nameof(NetworkBehaviourWithOwnerNetworkVariables.NetworkVariableData4)}][Player-{clientTwoId}] Client-{clientTwoId} value ({clientSide2PlayerComponent.NetworkVariableData4.Value})" +
|
||||
$" does not equal Client-{clientOneId}'s clone side value ({clientSide1Player2Clone.NetworkVariableData4.Value})!");
|
||||
}
|
||||
|
||||
// Now validate all of the NetworkVariable values match to assure everything synchronized properly
|
||||
foreach (var spawnedObject in validSpawnedNetworkObjects)
|
||||
{
|
||||
foreach (var clientNetworkManager in m_ClientNetworkManagers)
|
||||
{
|
||||
//Validate that the connected client has spawned all of the instances that shouldn't have failed.
|
||||
var clientSideNetworkObjects = s_GlobalNetworkObjects[clientNetworkManager.LocalClientId];
|
||||
|
||||
Assert.IsTrue(NetworkBehaviourWithNetworkVariables.ClientSpawnCount[clientNetworkManager.LocalClientId] == validSpawnedNetworkObjects.Count, $"Client-{clientNetworkManager.LocalClientId} spawned " +
|
||||
$"({NetworkBehaviourWithNetworkVariables.ClientSpawnCount}) {nameof(NetworkObject)}s but the expected number of {nameof(NetworkObject)}s should have been ({validSpawnedNetworkObjects.Count})!");
|
||||
|
||||
var spawnedNetworkObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
Assert.IsTrue(clientSideNetworkObjects.ContainsKey(spawnedNetworkObject.NetworkObjectId), $"Failed to find valid spawned {nameof(NetworkObject)} on the client-side with a " +
|
||||
$"{nameof(NetworkObject.NetworkObjectId)} of {spawnedNetworkObject.NetworkObjectId}");
|
||||
|
||||
var clientSideObject = clientSideNetworkObjects[spawnedNetworkObject.NetworkObjectId];
|
||||
Assert.IsTrue(clientSideObject.NetworkManager == clientNetworkManager, $"Client-side object {clientSideObject}'s {nameof(NetworkManager)} is not valid!");
|
||||
|
||||
ValidateNetworkBehaviourWithNetworkVariables(spawnedNetworkObject, clientSideObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateNetworkBehaviourWithNetworkVariables(NetworkObject serverSideNetworkObject, NetworkObject clientSideNetworkObject)
|
||||
{
|
||||
var serverSideComponent = serverSideNetworkObject.GetComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
var clientSideComponent = clientSideNetworkObject.GetComponent<NetworkBehaviourWithNetworkVariables>();
|
||||
|
||||
string netVarName1 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1);
|
||||
string netVarName2 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1);
|
||||
string netVarName3 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1);
|
||||
string netVarName4 = nameof(NetworkBehaviourWithNetworkVariables.NetworkVariableData1);
|
||||
|
||||
Assert.IsTrue(serverSideComponent.NetworkVariableData1.Count == clientSideComponent.NetworkVariableData1.Count, $"[{serverSideComponent.name}:{netVarName1}] Server side {nameof(NetworkList<byte>)} " +
|
||||
$"count ({serverSideComponent.NetworkVariableData1.Count}) does not match the client side {nameof(NetworkList<byte>)} count ({clientSideComponent.NetworkVariableData1.Count})!");
|
||||
|
||||
for (int i = 0; i < serverSideComponent.NetworkVariableData1.Count; i++)
|
||||
{
|
||||
Assert.IsTrue(serverSideComponent.NetworkVariableData1[i] == clientSideComponent.NetworkVariableData1[i], $"[{serverSideComponent.name}:{netVarName1}][Index:{i}] Server side instance value " +
|
||||
$"({serverSideComponent.NetworkVariableData1[i]}) does not match the client side instance value ({clientSideComponent.NetworkVariableData1[i]})!");
|
||||
}
|
||||
|
||||
Assert.IsTrue(serverSideComponent.NetworkVariableData2.Value == clientSideComponent.NetworkVariableData2.Value, $"[{serverSideComponent.name}:{netVarName2}] Server side instance value ({serverSideComponent.NetworkVariableData2.Value}) " +
|
||||
$"does not match the client side instance value ({clientSideComponent.NetworkVariableData2.Value})!");
|
||||
Assert.IsTrue(serverSideComponent.NetworkVariableData3.Value == clientSideComponent.NetworkVariableData3.Value, $"[{serverSideComponent.name}:{netVarName3}] Server side instance value ({serverSideComponent.NetworkVariableData3.Value}) " +
|
||||
$"does not match the client side instance value ({clientSideComponent.NetworkVariableData3.Value})!");
|
||||
Assert.IsTrue(serverSideComponent.NetworkVariableData4.Value == clientSideComponent.NetworkVariableData4.Value, $"[{serverSideComponent.name}:{netVarName4}] Server side instance value ({serverSideComponent.NetworkVariableData4.Value}) " +
|
||||
$"does not match the client side instance value ({clientSideComponent.NetworkVariableData4.Value})!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This validates that when a NetworkBehaviour fails serialization or deserialization during synchronizations that other NetworkBehaviours
|
||||
/// will still be initialized properly
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkBehaviourSynchronization()
|
||||
{
|
||||
m_ServerNetworkManager.LogLevel = LogLevel.Normal;
|
||||
m_CurrentLogLevel = LogLevel.Normal;
|
||||
NetworkBehaviourSynchronizeFailureComponent.ResetBehaviour();
|
||||
|
||||
var spawnedObjectList = new List<GameObject>();
|
||||
var numberOfObjectsToSpawn = NetworkBehaviourSynchronizeFailureComponent.NumberOfFailureTypes * 4;
|
||||
// Spawn 11 more NetworkObjects where there should be 4 of each failure type
|
||||
for (int i = 0; i < numberOfObjectsToSpawn; i++)
|
||||
{
|
||||
var synchronizationObject = SpawnObject(m_SynchronizationPrefab, m_ServerNetworkManager);
|
||||
var synchronizationBehaviour = synchronizationObject.GetComponent<NetworkBehaviourSynchronizeFailureComponent>();
|
||||
synchronizationBehaviour.AssignNextFailureType();
|
||||
spawnedObjectList.Add(synchronizationObject);
|
||||
}
|
||||
|
||||
// Now spawn and connect a client that will fail to spawn half of the NetworkObjects spawned
|
||||
yield return CreateAndStartNewClient();
|
||||
|
||||
// Validate that when a NetworkBehaviour fails to synchronize and is skipped over it does not
|
||||
// impact the rest of the NetworkBehaviours.
|
||||
var clientSideNetworkObjects = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId];
|
||||
foreach (var spawnedObject in spawnedObjectList)
|
||||
{
|
||||
var serverSideSpawnedNetworkObject = spawnedObject.GetComponent<NetworkObject>();
|
||||
var clientSideObject = clientSideNetworkObjects[serverSideSpawnedNetworkObject.NetworkObjectId];
|
||||
var clientSideSpawnedNetworkObject = clientSideObject.GetComponent<NetworkObject>();
|
||||
|
||||
ValidateNetworkBehaviourWithNetworkVariables(serverSideSpawnedNetworkObject, clientSideSpawnedNetworkObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A basic validation for the NetworkBehaviour.OnSynchronize method
|
||||
/// </summary>
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkBehaviourOnSynchronize()
|
||||
{
|
||||
var serverSideInstance = SpawnObject(m_OnSynchronizePrefab, m_ServerNetworkManager).GetComponent<NetworkBehaviourOnSynchronizeComponent>();
|
||||
|
||||
// Now spawn and connect a client that will have custom serialized data applied during the client synchronization process.
|
||||
yield return CreateAndStartNewClient();
|
||||
|
||||
var clientSideNetworkObjects = s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId];
|
||||
var clientSideInstance = clientSideNetworkObjects[serverSideInstance.NetworkObjectId].GetComponent<NetworkBehaviourOnSynchronizeComponent>();
|
||||
|
||||
// Validate the values match
|
||||
Assert.IsTrue(serverSideInstance.CustomSerializationData.Value1 == clientSideInstance.CustomSerializationData.Value1, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value1}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value1})");
|
||||
Assert.IsTrue(serverSideInstance.CustomSerializationData.Value2 == clientSideInstance.CustomSerializationData.Value2, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value2}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value2})");
|
||||
Assert.IsTrue(serverSideInstance.CustomSerializationData.Value3 == clientSideInstance.CustomSerializationData.Value3, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value3}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value3})");
|
||||
Assert.IsTrue(serverSideInstance.CustomSerializationData.Value4 == clientSideInstance.CustomSerializationData.Value4, $"Client-side instance Value1 ({serverSideInstance.CustomSerializationData.Value4}) does not equal server-side instance Value1 ({clientSideInstance.CustomSerializationData.Value4})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A test NetworkBeahviour that provides a varying NetworkList size as well as
|
||||
/// additional NetworkVariables to assure if a NetworkObject fails to be created
|
||||
/// the synchronization process will continue (i.e. it will skip over that block
|
||||
/// of the reader buffer).
|
||||
/// </summary>
|
||||
public class NetworkBehaviourWithNetworkVariables : NetworkBehaviour
|
||||
{
|
||||
public static int ServerSpawnCount { get; internal set; }
|
||||
public static readonly Dictionary<ulong, int> ClientSpawnCount = new Dictionary<ulong, int>();
|
||||
|
||||
public static void ResetSpawnCount()
|
||||
{
|
||||
ServerSpawnCount = 0;
|
||||
ClientSpawnCount.Clear();
|
||||
}
|
||||
|
||||
private const uint k_MinDataBlocks = 1;
|
||||
private const uint k_MaxDataBlocks = 64;
|
||||
|
||||
// Add various types of NetworkVariables
|
||||
public NetworkList<ulong> NetworkVariableData1;
|
||||
public NetworkVariable<int> NetworkVariableData2;
|
||||
public NetworkVariable<long> NetworkVariableData3;
|
||||
public NetworkVariable<byte> NetworkVariableData4;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
var dataBlocksAssigned = new List<ulong>();
|
||||
var numberDataBlocks = Random.Range(k_MinDataBlocks, k_MaxDataBlocks);
|
||||
for (var i = 0; i < numberDataBlocks; i++)
|
||||
{
|
||||
dataBlocksAssigned.Add((ulong)Random.Range(0.0f, float.MaxValue));
|
||||
}
|
||||
|
||||
NetworkVariableData1 = new NetworkList<ulong>(dataBlocksAssigned);
|
||||
NetworkVariableData2 = new NetworkVariable<int>(Random.Range(1, 1000));
|
||||
NetworkVariableData3 = new NetworkVariable<long>(Random.Range(1, 1000));
|
||||
NetworkVariableData4 = new NetworkVariable<byte>((byte)Random.Range(1, 255));
|
||||
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
ServerSpawnCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ClientSpawnCount.ContainsKey(NetworkManager.LocalClientId))
|
||||
{
|
||||
ClientSpawnCount.Add(NetworkManager.LocalClientId, 0);
|
||||
}
|
||||
ClientSpawnCount[NetworkManager.LocalClientId]++;
|
||||
}
|
||||
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A test NetworkBeahviour that has varying permissions in order to validate that
|
||||
/// when variable length safety checks are off NetworkVariables still are updated
|
||||
/// properly.
|
||||
/// </summary>
|
||||
public class NetworkBehaviourWithOwnerNetworkVariables : NetworkBehaviour
|
||||
{
|
||||
|
||||
// Should not synchronize on non-owners
|
||||
public NetworkVariable<int> NetworkVariableData1 = new NetworkVariable<int>(default, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server);
|
||||
// Should synchronize with everyone
|
||||
public NetworkVariable<long> NetworkVariableData2 = new NetworkVariable<long>();
|
||||
// Should not synchronize on non-owners
|
||||
public NetworkVariable<byte> NetworkVariableData3 = new NetworkVariable<byte>(default, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server);
|
||||
// Should synchronize with everyone
|
||||
public NetworkVariable<ushort> NetworkVariableData4 = new NetworkVariable<ushort>();
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
NetworkVariableData1.Value = Random.Range(1, 1000);
|
||||
NetworkVariableData2.Value = Random.Range(1, 1000);
|
||||
NetworkVariableData3.Value = (byte)Random.Range(1, 255);
|
||||
NetworkVariableData4.Value = (ushort)Random.Range(1, ushort.MaxValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A test NetworkBeahviour that simulates various types of synchronization failures
|
||||
/// and provides a synchronization success version to validate that synchronization
|
||||
/// will continue if user synchronization code fails.
|
||||
/// </summary>
|
||||
public class NetworkBehaviourSynchronizeFailureComponent : NetworkBehaviour
|
||||
{
|
||||
public static int NumberOfFailureTypes { get; internal set; }
|
||||
public static int ServerSpawnCount { get; internal set; }
|
||||
public static int ClientSpawnCount { get; internal set; }
|
||||
|
||||
private static FailureTypes s_FailureType = FailureTypes.None;
|
||||
|
||||
public enum FailureTypes
|
||||
{
|
||||
None,
|
||||
DuringWriting,
|
||||
DuringReading,
|
||||
DontReadAnything,
|
||||
ThrowWriteSideException,
|
||||
ThrowReadSideException
|
||||
}
|
||||
|
||||
public static void ResetBehaviour()
|
||||
{
|
||||
ServerSpawnCount = 0;
|
||||
ClientSpawnCount = 0;
|
||||
s_FailureType = FailureTypes.None;
|
||||
NumberOfFailureTypes = System.Enum.GetValues(typeof(FailureTypes)).Length;
|
||||
}
|
||||
|
||||
private MyCustomData m_MyCustomData;
|
||||
|
||||
private struct MyCustomData : INetworkSerializable
|
||||
{
|
||||
public FailureTypes FailureType;
|
||||
private ushort m_DataSize;
|
||||
private byte[] m_DataBlock;
|
||||
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
if (serializer.IsWriter)
|
||||
{
|
||||
var writer = serializer.GetFastBufferWriter();
|
||||
switch (FailureType)
|
||||
{
|
||||
case FailureTypes.None:
|
||||
// We want to write something for these two cases
|
||||
case FailureTypes.DuringReading:
|
||||
case FailureTypes.DontReadAnything:
|
||||
{
|
||||
writer.WriteValueSafe(m_DataSize);
|
||||
for (int i = 0; i < m_DataSize; i++)
|
||||
{
|
||||
writer.WriteValueSafe(m_DataBlock[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FailureTypes.DuringWriting:
|
||||
{
|
||||
writer.WriteValueSafe(m_DataSize);
|
||||
// Try to write past the allocated size to generate an exception
|
||||
// while also filling the buffer to verify that the buffer will be
|
||||
// reset back to the original position.
|
||||
for (int i = 0; i <= m_DataSize; i++)
|
||||
{
|
||||
writer.WriteValueSafe(m_DataBlock[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FailureTypes.ThrowWriteSideException:
|
||||
{
|
||||
throw new System.Exception("Write side exception!");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var reader = serializer.GetFastBufferReader();
|
||||
switch (FailureType)
|
||||
{
|
||||
case FailureTypes.None:
|
||||
{
|
||||
reader.ReadValueSafe(out m_DataSize);
|
||||
m_DataBlock = new byte[m_DataSize];
|
||||
for (int i = 0; i < m_DataSize; i++)
|
||||
{
|
||||
reader.ReadValueSafe(out m_DataBlock[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FailureTypes.DuringReading:
|
||||
{
|
||||
reader.ReadValueSafe(out m_DataSize);
|
||||
// Allocate more space than needed
|
||||
m_DataBlock = new byte[(int)(m_DataSize * 1.5f)];
|
||||
// Now read past the size of this message to verify
|
||||
// that the reader will get rest back to the appropriate
|
||||
// position and an error will be generated for this
|
||||
for (int i = 0; i < m_DataBlock.Length; i++)
|
||||
{
|
||||
reader.ReadValueSafe(out m_DataBlock[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FailureTypes.DontReadAnything:
|
||||
{
|
||||
// Don't read anything
|
||||
break;
|
||||
}
|
||||
case FailureTypes.ThrowReadSideException:
|
||||
{
|
||||
throw new System.Exception("Read side exception!");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateData(ushort size)
|
||||
{
|
||||
m_DataSize = size;
|
||||
m_DataBlock = new byte[size];
|
||||
for (int i = 0; i < m_DataSize; i++)
|
||||
{
|
||||
m_DataBlock[i] = (byte)Random.Range(0, 512);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This NetworkVariable is synchronized before OnSynchronize is invoked
|
||||
// which enables us to perform the tests.
|
||||
// Users could follow the same pattern for game assets and synchronize
|
||||
// clients based on NetworkVariable settings. (i.e. a specific NPC type or the like)
|
||||
private NetworkVariable<FailureTypes> m_FailureType;
|
||||
|
||||
public void AssignNextFailureType()
|
||||
{
|
||||
var currentPosition = (int)s_FailureType;
|
||||
currentPosition = (++currentPosition) % NumberOfFailureTypes;
|
||||
s_FailureType = (FailureTypes)currentPosition;
|
||||
m_FailureType.Value = s_FailureType;
|
||||
}
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_FailureType = new NetworkVariable<FailureTypes>();
|
||||
m_MyCustomData = new MyCustomData();
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
ServerSpawnCount++;
|
||||
m_MyCustomData.GenerateData((ushort)Random.Range(1, 512));
|
||||
}
|
||||
else
|
||||
{
|
||||
ClientSpawnCount++;
|
||||
}
|
||||
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
|
||||
protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
|
||||
{
|
||||
// Assign the failure type first
|
||||
m_MyCustomData.FailureType = m_FailureType.Value;
|
||||
// Now handle the serialization for this failure type
|
||||
m_MyCustomData.NetworkSerialize(serializer);
|
||||
}
|
||||
}
|
||||
|
||||
public class NetworkBehaviourOnSynchronizeComponent : NetworkBehaviour
|
||||
{
|
||||
public SomeCustomSerializationData CustomSerializationData = new SomeCustomSerializationData();
|
||||
|
||||
public struct SomeCustomSerializationData : INetworkSerializable
|
||||
{
|
||||
public uint Value1;
|
||||
public bool Value2;
|
||||
public long Value3;
|
||||
public float Value4;
|
||||
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
|
||||
{
|
||||
serializer.SerializeValue(ref Value1);
|
||||
serializer.SerializeValue(ref Value2);
|
||||
serializer.SerializeValue(ref Value3);
|
||||
serializer.SerializeValue(ref Value4);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
if (IsServer)
|
||||
{
|
||||
CustomSerializationData.Value1 = (uint)Random.Range(0, 10000);
|
||||
CustomSerializationData.Value2 = true;
|
||||
CustomSerializationData.Value3 = Random.Range(0, 10000);
|
||||
CustomSerializationData.Value4 = Random.Range(-1000.0f, 1000.0f);
|
||||
}
|
||||
base.OnNetworkSpawn();
|
||||
}
|
||||
|
||||
protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
|
||||
{
|
||||
serializer.SerializeNetworkSerializable(ref CustomSerializationData);
|
||||
base.OnSynchronize(ref serializer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,12 @@ namespace Unity.Netcode.RuntimeTests
|
||||
//Stop, shutdown, and destroy
|
||||
NetworkManagerHelper.ShutdownNetworkManager();
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
var networkObjects = UnityEngine.Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.InstanceID).ToList();
|
||||
#else
|
||||
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>().ToList();
|
||||
#endif
|
||||
|
||||
var networkObjectsList = networkObjects.Where(c => c.name.Contains(k_PrefabObjectName));
|
||||
foreach (var networkObject in networkObjectsList)
|
||||
{
|
||||
|
||||
@@ -8,16 +8,12 @@ using Unity.Netcode.TestHelpers.Runtime;
|
||||
|
||||
namespace Unity.Netcode.RuntimeTests
|
||||
{
|
||||
public class NetworkShowHideTestComponent : NetworkBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class ShowHideObject : NetworkBehaviour
|
||||
{
|
||||
public static List<ShowHideObject> ClientTargetedNetworkObjects = new List<ShowHideObject>();
|
||||
public static ulong ClientIdToTarget;
|
||||
public static bool Silent;
|
||||
public static int ValueAfterOwnershipChange = 0;
|
||||
|
||||
public static NetworkObject GetNetworkObjectById(ulong networkObjectId)
|
||||
{
|
||||
@@ -62,13 +58,35 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
public NetworkVariable<int> MyNetworkVariable;
|
||||
public NetworkList<int> MyListSetOnSpawn;
|
||||
public NetworkVariable<int> MyOwnerReadNetworkVariable;
|
||||
static public NetworkManager NetworkManagerOfInterest;
|
||||
|
||||
internal static int GainOwnershipCount = 0;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Debug.Log($"Awake {NetworkManager.LocalClientId}");
|
||||
MyNetworkVariable = new NetworkVariable<int>();
|
||||
MyNetworkVariable.OnValueChanged += Changed;
|
||||
|
||||
MyListSetOnSpawn = new NetworkList<int>();
|
||||
|
||||
MyOwnerReadNetworkVariable = new NetworkVariable<int>(readPerm: NetworkVariableReadPermission.Owner);
|
||||
MyOwnerReadNetworkVariable.OnValueChanged += OwnerReadChanged;
|
||||
}
|
||||
|
||||
public override void OnGainedOwnership()
|
||||
{
|
||||
GainOwnershipCount++;
|
||||
base.OnGainedOwnership();
|
||||
}
|
||||
|
||||
public void OwnerReadChanged(int before, int after)
|
||||
{
|
||||
if (NetworkManager == NetworkManagerOfInterest)
|
||||
{
|
||||
ValueAfterOwnershipChange = after;
|
||||
}
|
||||
}
|
||||
|
||||
public void Changed(int before, int after)
|
||||
@@ -94,11 +112,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
private NetworkObject m_Object2OnClient0;
|
||||
private NetworkObject m_Object3OnClient0;
|
||||
|
||||
protected override void OnCreatePlayerPrefab()
|
||||
{
|
||||
var networkTransform = m_PlayerPrefab.AddComponent<NetworkShowHideTestComponent>();
|
||||
}
|
||||
|
||||
protected override void OnServerAndClientsCreated()
|
||||
{
|
||||
m_PrefabToSpawn = CreateNetworkObjectPrefab("ShowHideObject");
|
||||
@@ -338,5 +351,48 @@ namespace Unity.Netcode.RuntimeTests
|
||||
|
||||
Assert.True(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId == m_ClientNetworkManagers[0].LocalClientId);
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator NetworkHideChangeOwnershipNotHidden()
|
||||
{
|
||||
ShowHideObject.ClientTargetedNetworkObjects.Clear();
|
||||
ShowHideObject.ClientIdToTarget = m_ClientNetworkManagers[1].LocalClientId;
|
||||
ShowHideObject.Silent = true;
|
||||
|
||||
var spawnedObject1 = SpawnObject(m_PrefabToSpawn, m_ServerNetworkManager);
|
||||
m_NetSpawnedObject1 = spawnedObject1.GetComponent<NetworkObject>();
|
||||
|
||||
// wait for host to have spawned and gained ownership
|
||||
while (ShowHideObject.GainOwnershipCount == 0)
|
||||
{
|
||||
yield return new WaitForSeconds(0.0f);
|
||||
}
|
||||
|
||||
// change the value
|
||||
m_NetSpawnedObject1.GetComponent<ShowHideObject>().MyOwnerReadNetworkVariable.Value++;
|
||||
|
||||
// wait for three ticks
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
|
||||
|
||||
// check we'll actually be changing owners
|
||||
Assert.False(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId == m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// only check for value change on one specific client
|
||||
ShowHideObject.NetworkManagerOfInterest = m_ClientNetworkManagers[0];
|
||||
|
||||
// change ownership
|
||||
m_NetSpawnedObject1.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// wait three ticks
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ServerNetworkManager, 3);
|
||||
yield return NetcodeIntegrationTestHelpers.WaitForTicks(m_ClientNetworkManagers[0], 3);
|
||||
|
||||
// verify ownership changed
|
||||
Assert.True(ShowHideObject.ClientTargetedNetworkObjects[0].OwnerClientId == m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
// verify the expected client got the OnValueChanged. (Only client 1 sets this value)
|
||||
Assert.True(ShowHideObject.ValueAfterOwnershipChange == 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,7 +734,6 @@ namespace Unity.Netcode.RuntimeTests
|
||||
Assert.IsTrue(m_DetectedPotentialInterpolatedTeleport == 0.0f, $"Detected possible interpolation on non-authority side! NonAuthority distance: {m_DetectedPotentialInterpolatedTeleport} | Target distance: {targetDistance}");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This test validates the <see cref="NetworkTransform.SetState(Vector3?, Quaternion?, Vector3?, bool)"/> method
|
||||
/// usage for the non-authoritative side. It will either be the owner or the server making/requesting state changes.
|
||||
@@ -842,7 +841,7 @@ namespace Unity.Netcode.RuntimeTests
|
||||
}
|
||||
if (!nonauthorityIsEqual)
|
||||
{
|
||||
VerboseDebug($"NonAuthority position {nonAuthorityRotationEuler} != rotation to match: {rotationEulerToMatch}!");
|
||||
VerboseDebug($"NonAuthority rotation {nonAuthorityRotationEuler} != rotation to match: {rotationEulerToMatch}!");
|
||||
}
|
||||
return auhtorityIsEqual && nonauthorityIsEqual;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,12 @@ namespace Unity.Netcode.RuntimeTests
|
||||
[UnityTest]
|
||||
public IEnumerator HiddenObjectsTest()
|
||||
{
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType<NetworkVisibilityComponent>(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == 2);
|
||||
#else
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType<NetworkVisibilityComponent>().Where((c) => c.IsSpawned).Count() == 2);
|
||||
#endif
|
||||
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for the visible object count to equal 2!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user