com.unity.netcode.gameobjects@1.0.0-pre.7
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.0.0-pre.7] - 2022-04-01 ### Added - Added editor only check prior to entering into play mode if the currently open and active scene is in the build list and if not displays a dialog box asking the user if they would like to automatically add it prior to entering into play mode. (#1828) - Added `UnityTransport` implementation and `com.unity.transport` package dependency (#1823) - Added `NetworkVariableWritePermission` to `NetworkVariableBase` and implemented `Owner` client writable netvars. (#1762) - `UnityTransport` settings can now be set programmatically. (#1845) - `FastBufferWriter` and Reader IsInitialized property. (#1859) ### Changed - Updated `UnityTransport` dependency on `com.unity.transport` to 1.0.0 (#1849) ### Removed - Removed `SnapshotSystem` (#1852) - Removed `com.unity.modules.animation`, `com.unity.modules.physics` and `com.unity.modules.physics2d` dependencies from the package (#1812) - Removed `com.unity.collections` dependency from the package (#1849) ### Fixed - Fixed in-scene placed NetworkObjects not being found/ignored after a client disconnects and then reconnects. (#1850) - Fixed issue where `UnityTransport` send queues were not flushed when calling `DisconnectLocalClient` or `DisconnectRemoteClient`. (#1847) - Fixed NetworkBehaviour dependency verification check for an existing NetworkObject not searching from root parent transform relative GameObject. (#1841) - Fixed issue where entries were not being removed from the NetworkSpawnManager.OwnershipToObjectsTable. (#1838) - Fixed ClientRpcs would always send to all connected clients by default as opposed to only sending to the NetworkObject's Observers list by default. (#1836) - Fixed clarity for NetworkSceneManager client side notification when it receives a scene hash value that does not exist in its local hash table. (#1828) - Fixed client throws a key not found exception when it times out using UNet or UTP. (#1821) - Fixed network variable updates are no longer limited to 32,768 bytes when NetworkConfig.EnsureNetworkVariableLengthSafety is enabled. The limits are now determined by what the transport can send in a message. (#1811) - Fixed in-scene NetworkObjects get destroyed if a client fails to connect and shuts down the NetworkManager. (#1809) - Fixed user never being notified in the editor that a NetworkBehaviour requires a NetworkObject to function properly. (#1808) - Fixed PlayerObjects and dynamically spawned NetworkObjects not being added to the NetworkClient's OwnedObjects (#1801) - Fixed issue where NetworkManager would continue starting even if the NetworkTransport selected failed. (#1780) - Fixed issue when spawning new player if an already existing player exists it does not remove IsPlayer from the previous player (#1779) - Fixed lack of notification that NetworkManager and NetworkObject cannot be added to the same GameObject with in-editor notifications (#1777) - Fixed parenting warning printing for false positives (#1855)
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class FixedAllocatorTest
|
||||
{
|
||||
[Test]
|
||||
public void SimpleTest()
|
||||
{
|
||||
int pos;
|
||||
|
||||
var allocator = new IndexAllocator(20000, 200);
|
||||
allocator.DebugDisplay();
|
||||
|
||||
// allocate 20 bytes
|
||||
Assert.IsTrue(allocator.Allocate(0, 20, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// can't ask for negative amount of memory
|
||||
Assert.IsFalse(allocator.Allocate(1, -20, out pos));
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// can't ask for deallocation of negative index
|
||||
Assert.IsFalse(allocator.Deallocate(-1));
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// can't ask for the same index twice
|
||||
Assert.IsFalse(allocator.Allocate(0, 20, out pos));
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate another 20 bytes
|
||||
Assert.IsTrue(allocator.Allocate(1, 20, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate a third 20 bytes
|
||||
Assert.IsTrue(allocator.Allocate(2, 20, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// deallocate 0
|
||||
Assert.IsTrue(allocator.Deallocate(0));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// deallocate 1
|
||||
allocator.Deallocate(1);
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// deallocate 2
|
||||
allocator.Deallocate(2);
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate 50 bytes
|
||||
Assert.IsTrue(allocator.Allocate(0, 50, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate another 50 bytes
|
||||
Assert.IsTrue(allocator.Allocate(1, 50, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate a third 50 bytes
|
||||
Assert.IsTrue(allocator.Allocate(2, 50, out pos));
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// deallocate 1, a block in the middle this time
|
||||
allocator.Deallocate(1);
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
|
||||
// allocate a smaller one in its place
|
||||
allocator.Allocate(1, 25, out pos);
|
||||
allocator.DebugDisplay();
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReuseTest()
|
||||
{
|
||||
int count = 100;
|
||||
bool[] used = new bool[count];
|
||||
int[] pos = new int[count];
|
||||
int iterations = 10000;
|
||||
|
||||
var allocator = new IndexAllocator(20000, 200);
|
||||
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
int index = Random.Range(0, count);
|
||||
if (used[index])
|
||||
{
|
||||
Assert.IsTrue(allocator.Deallocate(index));
|
||||
used[index] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int position;
|
||||
int length = 10 * Random.Range(1, 10);
|
||||
Assert.IsTrue(allocator.Allocate(index, length, out position));
|
||||
pos[index] = position;
|
||||
used[index] = true;
|
||||
}
|
||||
Assert.IsTrue(allocator.Verify());
|
||||
}
|
||||
allocator.DebugDisplay();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -34,5 +34,49 @@ namespace Unity.Netcode.EditorTests
|
||||
// Clean up
|
||||
Object.DestroyImmediate(parent);
|
||||
}
|
||||
|
||||
public enum NetworkObjectPlacement
|
||||
{
|
||||
Root, // Added to the same root GameObject
|
||||
Child // Added to a child GameObject
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NetworkObjectNotAllowed([Values] NetworkObjectPlacement networkObjectPlacement)
|
||||
{
|
||||
var gameObject = new GameObject(nameof(NetworkManager));
|
||||
var targetforNetworkObject = gameObject;
|
||||
|
||||
if (networkObjectPlacement == NetworkObjectPlacement.Child)
|
||||
{
|
||||
var childGameObject = new GameObject($"{nameof(NetworkManager)}-Child");
|
||||
childGameObject.transform.parent = targetforNetworkObject.transform;
|
||||
targetforNetworkObject = childGameObject;
|
||||
}
|
||||
|
||||
var networkManager = gameObject.AddComponent<NetworkManager>();
|
||||
|
||||
// Trap for the error message generated when a NetworkObject is discovered on the same GameObject or any children under it
|
||||
LogAssert.Expect(LogType.Error, NetworkManagerHelper.Singleton.NetworkManagerAndNetworkObjectNotAllowedMessage());
|
||||
|
||||
// Add the NetworkObject
|
||||
var networkObject = targetforNetworkObject.AddComponent<NetworkObject>();
|
||||
|
||||
// Since this is an in-editor test, we must force this invocation
|
||||
NetworkManagerHelper.Singleton.CheckAndNotifyUserNetworkObjectRemoved(networkManager, true);
|
||||
|
||||
// Validate that the NetworkObject has been removed
|
||||
if (networkObjectPlacement == NetworkObjectPlacement.Root)
|
||||
{
|
||||
Assert.IsNull(networkManager.gameObject.GetComponent<NetworkObject>(), $"There is still a {nameof(NetworkObject)} on {nameof(NetworkManager)}'s GameObject!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.IsNull(networkManager.gameObject.GetComponentInChildren<NetworkObject>(), $"There is still a {nameof(NetworkObject)} on {nameof(NetworkManager)}'s child GameObject!");
|
||||
}
|
||||
|
||||
// Clean up
|
||||
Object.DestroyImmediate(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
Tests/Editor/NetworkVar.meta
Normal file
3
Tests/Editor/NetworkVar.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed3be13d96c34bc4b8676ce550cee041
|
||||
timeCreated: 1647861659
|
||||
41
Tests/Editor/NetworkVar/NetworkVarTests.cs
Normal file
41
Tests/Editor/NetworkVar/NetworkVarTests.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Unity.Netcode.EditorTests.NetworkVar
|
||||
{
|
||||
public class NetworkVarTests
|
||||
{
|
||||
[Test]
|
||||
public void TestAssignmentUnchanged()
|
||||
{
|
||||
var intVar = new NetworkVariable<int>();
|
||||
|
||||
intVar.Value = 314159265;
|
||||
|
||||
intVar.OnValueChanged += (value, newValue) =>
|
||||
{
|
||||
Assert.Fail("OnValueChanged was invoked when setting the same value");
|
||||
};
|
||||
|
||||
intVar.Value = 314159265;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAssignmentChanged()
|
||||
{
|
||||
var intVar = new NetworkVariable<int>();
|
||||
|
||||
intVar.Value = 314159265;
|
||||
|
||||
var changed = false;
|
||||
|
||||
intVar.OnValueChanged += (value, newValue) =>
|
||||
{
|
||||
changed = true;
|
||||
};
|
||||
|
||||
intVar.Value = 314159266;
|
||||
|
||||
Assert.True(changed);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Tests/Editor/NetworkVar/NetworkVarTests.cs.meta
Normal file
3
Tests/Editor/NetworkVar/NetworkVarTests.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7cdd8c1251f4352b1f1d4825dc85182
|
||||
timeCreated: 1647861669
|
||||
@@ -393,6 +393,34 @@ namespace Unity.Netcode.EditorTests
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingNewFastBufferReader_IsInitializedIsTrue()
|
||||
{
|
||||
var array = new NativeArray<byte>(100, Allocator.Temp);
|
||||
var reader = new FastBufferReader(array, Allocator.Temp);
|
||||
Assert.AreEqual(true, reader.IsInitialized);
|
||||
reader.Dispose();
|
||||
array.Dispose();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenDisposingFastBufferReader_IsInitializedIsFalse()
|
||||
{
|
||||
var array = new NativeArray<byte>(100, Allocator.Temp);
|
||||
var reader = new FastBufferReader(array, Allocator.Temp);
|
||||
reader.Dispose();
|
||||
Assert.AreEqual(false, reader.IsInitialized);
|
||||
array.Dispose();
|
||||
Assert.AreEqual(false, reader.IsInitialized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenUsingDefaultFastBufferReader_IsInitializedIsFalse()
|
||||
{
|
||||
FastBufferReader writer = default;
|
||||
Assert.AreEqual(false, writer.IsInitialized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCallingReadByteWithoutCallingTryBeingReadFirst_OverflowExceptionIsThrown()
|
||||
{
|
||||
|
||||
@@ -891,6 +891,29 @@ namespace Unity.Netcode.EditorTests
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenCreatingNewFastBufferWriter_IsInitializedIsTrue()
|
||||
{
|
||||
var writer = new FastBufferWriter(100, Allocator.Temp);
|
||||
Assert.AreEqual(true, writer.IsInitialized);
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenDisposingFastBufferWriter_IsInitializedIsFalse()
|
||||
{
|
||||
var writer = new FastBufferWriter(100, Allocator.Temp);
|
||||
writer.Dispose();
|
||||
Assert.AreEqual(false, writer.IsInitialized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenUsingDefaultFastBufferWriter_IsInitializedIsFalse()
|
||||
{
|
||||
FastBufferWriter writer = default;
|
||||
Assert.AreEqual(false, writer.IsInitialized);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WhenRequestingWritePastBoundsForNonGrowingWriter_TryBeginWriteReturnsFalse()
|
||||
{
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class SnapshotRttTests
|
||||
{
|
||||
private const double k_Epsilon = 0.0001;
|
||||
|
||||
[Test]
|
||||
public void TestBasicRtt()
|
||||
{
|
||||
var snapshot = new SnapshotSystem(null, new NetworkConfig(), null);
|
||||
var client1 = snapshot.GetConnectionRtt(0);
|
||||
|
||||
client1.NotifySend(0, 0.0);
|
||||
client1.NotifySend(1, 10.0);
|
||||
|
||||
client1.NotifyAck(1, 15.0);
|
||||
|
||||
client1.NotifySend(2, 20.0);
|
||||
client1.NotifySend(3, 30.0);
|
||||
client1.NotifySend(4, 32.0);
|
||||
|
||||
client1.NotifyAck(4, 38.0);
|
||||
client1.NotifyAck(3, 40.0);
|
||||
|
||||
ConnectionRtt.Rtt ret = client1.GetRtt();
|
||||
Assert.True(ret.AverageSec < 7.0 + k_Epsilon);
|
||||
Assert.True(ret.AverageSec > 7.0 - k_Epsilon);
|
||||
Assert.True(ret.WorstSec < 10.0 + k_Epsilon);
|
||||
Assert.True(ret.WorstSec > 10.0 - k_Epsilon);
|
||||
Assert.True(ret.BestSec < 5.0 + k_Epsilon);
|
||||
Assert.True(ret.BestSec > 5.0 - k_Epsilon);
|
||||
|
||||
// note: `last` latency is latest received Ack, not latest sent sequence.
|
||||
Assert.True(ret.LastSec < 10.0 + k_Epsilon);
|
||||
Assert.True(ret.LastSec > 10.0 - k_Epsilon);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEdgeCasesRtt()
|
||||
{
|
||||
var snapshot = new SnapshotSystem(null, new NetworkConfig(), null);
|
||||
var client1 = snapshot.GetConnectionRtt(0);
|
||||
var iterationCount = NetworkConfig.RttWindowSize * 3;
|
||||
var extraCount = NetworkConfig.RttWindowSize * 2;
|
||||
|
||||
// feed in some messages
|
||||
for (var iteration = 0; iteration < iterationCount; iteration++)
|
||||
{
|
||||
client1.NotifySend(iteration, 25.0 * iteration);
|
||||
}
|
||||
// ack some random ones in there (1 out of each 9), always 7.0 later
|
||||
for (var iteration = 0; iteration < iterationCount; iteration += 9)
|
||||
{
|
||||
client1.NotifyAck(iteration, 25.0 * iteration + 7.0);
|
||||
}
|
||||
// ack some unused key, to check it doesn't throw off the values
|
||||
for (var iteration = iterationCount; iteration < iterationCount + extraCount; iteration++)
|
||||
{
|
||||
client1.NotifyAck(iteration, 42.0);
|
||||
}
|
||||
|
||||
ConnectionRtt.Rtt ret = client1.GetRtt();
|
||||
Assert.True(ret.AverageSec < 7.0 + k_Epsilon);
|
||||
Assert.True(ret.AverageSec > 7.0 - k_Epsilon);
|
||||
Assert.True(ret.WorstSec < 7.0 + k_Epsilon);
|
||||
Assert.True(ret.WorstSec > 7.0 - k_Epsilon);
|
||||
Assert.True(ret.BestSec < 7.0 + k_Epsilon);
|
||||
Assert.True(ret.BestSec > 7.0 - k_Epsilon);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,363 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using NUnit.Framework;
|
||||
using Random = System.Random;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class SnapshotTests
|
||||
{
|
||||
private SnapshotSystem m_SendSnapshot;
|
||||
private SnapshotSystem m_RecvSnapshot;
|
||||
|
||||
private NetworkTimeSystem m_SendTimeSystem;
|
||||
private NetworkTickSystem m_SendTickSystem;
|
||||
private NetworkTimeSystem m_RecvTimeSystem;
|
||||
private NetworkTickSystem m_RecvTickSystem;
|
||||
|
||||
private int m_SpawnedObjectCount;
|
||||
private int m_DespawnedObjectCount;
|
||||
private int m_NextSequence;
|
||||
private uint m_TicksPerSec = 15;
|
||||
private int m_MinSpawns;
|
||||
private int m_MinDespawns;
|
||||
|
||||
private bool m_ExpectSpawns;
|
||||
private bool m_ExpectDespawns;
|
||||
private bool m_LoseNextMessage;
|
||||
private bool m_PassBackResponses;
|
||||
|
||||
public void Prepare()
|
||||
{
|
||||
PrepareSendSideSnapshot();
|
||||
PrepareRecvSideSnapshot();
|
||||
}
|
||||
|
||||
public void AdvanceOneTickSendSide()
|
||||
{
|
||||
m_SendTimeSystem.Advance(1.0f / m_TicksPerSec);
|
||||
m_SendTickSystem.UpdateTick(m_SendTimeSystem.LocalTime, m_SendTimeSystem.ServerTime);
|
||||
m_SendSnapshot.NetworkUpdate(NetworkUpdateStage.EarlyUpdate);
|
||||
}
|
||||
|
||||
public void AdvanceOneTickRecvSide()
|
||||
{
|
||||
m_RecvTimeSystem.Advance(1.0f / m_TicksPerSec);
|
||||
m_RecvTickSystem.UpdateTick(m_RecvTimeSystem.LocalTime, m_RecvTimeSystem.ServerTime);
|
||||
m_RecvSnapshot.NetworkUpdate(NetworkUpdateStage.EarlyUpdate);
|
||||
}
|
||||
|
||||
public void AdvanceOneTick()
|
||||
{
|
||||
AdvanceOneTickSendSide();
|
||||
AdvanceOneTickRecvSide();
|
||||
}
|
||||
|
||||
internal int SpawnObject(SnapshotSpawnCommand command)
|
||||
{
|
||||
m_SpawnedObjectCount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int DespawnObject(SnapshotDespawnCommand command)
|
||||
{
|
||||
m_DespawnedObjectCount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int SendMessage(ref SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
{
|
||||
if (!m_PassBackResponses)
|
||||
{
|
||||
// we're not ack'ing anything, so those should stay 0
|
||||
Debug.Assert(message.Ack.LastReceivedSequence == 0);
|
||||
}
|
||||
|
||||
Debug.Assert(message.Ack.ReceivedSequenceMask == 0);
|
||||
Debug.Assert(message.Sequence == m_NextSequence); // sequence has to be the expected one
|
||||
|
||||
if (m_ExpectSpawns)
|
||||
{
|
||||
Debug.Assert(message.Spawns.Length >= m_MinSpawns); // there has to be multiple spawns per SnapshotMessage
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(message.Spawns.Length == 0); // Spawns were not expected
|
||||
}
|
||||
|
||||
if (m_ExpectDespawns)
|
||||
{
|
||||
Debug.Assert(message.Despawns.Length >= m_MinDespawns); // there has to be multiple despawns per SnapshotMessage
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(message.Despawns.IsEmpty); // this test should not have despawns
|
||||
}
|
||||
|
||||
Debug.Assert(message.Entries.Length == 0);
|
||||
|
||||
m_NextSequence++;
|
||||
|
||||
if (!m_LoseNextMessage)
|
||||
{
|
||||
using var writer = new FastBufferWriter(1024, Allocator.Temp);
|
||||
message.Serialize(writer);
|
||||
using var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
var context = new NetworkContext { SenderId = 0, Timestamp = 0.0f, SystemOwner = new Tuple<SnapshotSystem, ulong>(m_RecvSnapshot, 0) };
|
||||
var newMessage = new SnapshotDataMessage();
|
||||
newMessage.Deserialize(reader, ref context);
|
||||
newMessage.Handle(ref context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal int SendMessageRecvSide(ref SnapshotDataMessage message, NetworkDelivery delivery, ulong clientId)
|
||||
{
|
||||
if (m_PassBackResponses)
|
||||
{
|
||||
using var writer = new FastBufferWriter(1024, Allocator.Temp);
|
||||
message.Serialize(writer);
|
||||
using var reader = new FastBufferReader(writer, Allocator.Temp);
|
||||
var context = new NetworkContext { SenderId = 0, Timestamp = 0.0f, SystemOwner = new Tuple<SnapshotSystem, ulong>(m_SendSnapshot, 1) };
|
||||
var newMessage = new SnapshotDataMessage();
|
||||
newMessage.Deserialize(reader, ref context);
|
||||
newMessage.Handle(ref context);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private void PrepareSendSideSnapshot()
|
||||
{
|
||||
var config = new NetworkConfig();
|
||||
|
||||
m_SendTickSystem = new NetworkTickSystem(m_TicksPerSec, 0.0, 0.0);
|
||||
m_SendTimeSystem = new NetworkTimeSystem(0.2, 0.2, 1.0);
|
||||
|
||||
config.UseSnapshotDelta = false;
|
||||
config.UseSnapshotSpawn = true;
|
||||
|
||||
m_SendSnapshot = new SnapshotSystem(null, config, m_SendTickSystem);
|
||||
|
||||
m_SendSnapshot.IsServer = true;
|
||||
m_SendSnapshot.IsConnectedClient = false;
|
||||
m_SendSnapshot.ServerClientId = 0;
|
||||
m_SendSnapshot.ConnectedClientsId.Clear();
|
||||
m_SendSnapshot.ConnectedClientsId.Add(0);
|
||||
m_SendSnapshot.ConnectedClientsId.Add(1);
|
||||
m_SendSnapshot.MockSendMessage = SendMessage;
|
||||
m_SendSnapshot.MockSpawnObject = SpawnObject;
|
||||
m_SendSnapshot.MockDespawnObject = DespawnObject;
|
||||
}
|
||||
|
||||
private void PrepareRecvSideSnapshot()
|
||||
{
|
||||
var config = new NetworkConfig();
|
||||
|
||||
m_RecvTickSystem = new NetworkTickSystem(m_TicksPerSec, 0.0, 0.0);
|
||||
m_RecvTimeSystem = new NetworkTimeSystem(0.2, 0.2, 1.0);
|
||||
|
||||
config.UseSnapshotDelta = false;
|
||||
config.UseSnapshotSpawn = true;
|
||||
|
||||
m_RecvSnapshot = new SnapshotSystem(null, config, m_RecvTickSystem);
|
||||
|
||||
m_RecvSnapshot.IsServer = false;
|
||||
m_RecvSnapshot.IsConnectedClient = true;
|
||||
m_RecvSnapshot.ServerClientId = 0;
|
||||
m_RecvSnapshot.ConnectedClientsId.Clear();
|
||||
m_SendSnapshot.ConnectedClientsId.Add(0);
|
||||
m_SendSnapshot.ConnectedClientsId.Add(1);
|
||||
m_RecvSnapshot.MockSendMessage = SendMessageRecvSide;
|
||||
m_RecvSnapshot.MockSpawnObject = SpawnObject;
|
||||
m_RecvSnapshot.MockDespawnObject = DespawnObject;
|
||||
}
|
||||
|
||||
private void SendSpawnToSnapshot(ulong objectId)
|
||||
{
|
||||
SnapshotSpawnCommand command = default;
|
||||
// identity
|
||||
command.NetworkObjectId = objectId;
|
||||
// archetype
|
||||
command.GlobalObjectIdHash = 0;
|
||||
command.IsSceneObject = true;
|
||||
// parameters
|
||||
command.IsPlayerObject = false;
|
||||
command.OwnerClientId = 0;
|
||||
command.ParentNetworkId = 0;
|
||||
command.ObjectPosition = default;
|
||||
command.ObjectRotation = default;
|
||||
command.ObjectScale = new Vector3(1.0f, 1.0f, 1.0f);
|
||||
command.TargetClientIds = new List<ulong> { 1 };
|
||||
m_SendSnapshot.Spawn(command);
|
||||
}
|
||||
|
||||
private void SendDespawnToSnapshot(ulong objectId)
|
||||
{
|
||||
SnapshotDespawnCommand command = default;
|
||||
// identity
|
||||
command.NetworkObjectId = objectId;
|
||||
command.TargetClientIds = new List<ulong> { 1 };
|
||||
m_SendSnapshot.Despawn(command);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSnapshotSpawn()
|
||||
{
|
||||
Prepare();
|
||||
|
||||
m_SpawnedObjectCount = 0;
|
||||
m_NextSequence = 0;
|
||||
m_ExpectSpawns = true;
|
||||
m_ExpectDespawns = false;
|
||||
m_MinSpawns = 2; // many spawns are to be sent together
|
||||
m_LoseNextMessage = false;
|
||||
m_PassBackResponses = false;
|
||||
|
||||
var ticksToRun = 20;
|
||||
|
||||
// spawns one more than current buffer size
|
||||
var objectsToSpawn = m_SendSnapshot.SpawnsBufferCount + 1;
|
||||
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
SendSpawnToSnapshot((ulong)i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ticksToRun; i++)
|
||||
{
|
||||
AdvanceOneTick();
|
||||
}
|
||||
|
||||
Debug.Assert(m_SpawnedObjectCount == objectsToSpawn);
|
||||
Debug.Assert(m_SendSnapshot.SpawnsBufferCount > objectsToSpawn); // spawn buffer should have grown
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSnapshotSpawnDespawns()
|
||||
{
|
||||
Prepare();
|
||||
|
||||
// test that buffers actually shrink and will grow back to needed size
|
||||
m_SendSnapshot.ReduceBufferUsage();
|
||||
m_RecvSnapshot.ReduceBufferUsage();
|
||||
Debug.Assert(m_SendSnapshot.SpawnsBufferCount == 1);
|
||||
Debug.Assert(m_SendSnapshot.DespawnsBufferCount == 1);
|
||||
Debug.Assert(m_RecvSnapshot.SpawnsBufferCount == 1);
|
||||
Debug.Assert(m_RecvSnapshot.DespawnsBufferCount == 1);
|
||||
|
||||
m_SpawnedObjectCount = 0;
|
||||
m_DespawnedObjectCount = 0;
|
||||
|
||||
m_NextSequence = 0;
|
||||
m_ExpectSpawns = true;
|
||||
m_ExpectDespawns = false;
|
||||
m_MinDespawns = 2; // many despawns are to be sent together
|
||||
m_LoseNextMessage = false;
|
||||
m_PassBackResponses = false;
|
||||
|
||||
var ticksToRun = 20;
|
||||
|
||||
// spawns one more than current buffer size
|
||||
var objectsToSpawn = 10;
|
||||
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
SendSpawnToSnapshot((ulong)i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ticksToRun; i++)
|
||||
{
|
||||
AdvanceOneTick();
|
||||
}
|
||||
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
SendDespawnToSnapshot((ulong)i);
|
||||
}
|
||||
|
||||
m_ExpectSpawns = true; // the un'acked spawns will still be present
|
||||
m_MinSpawns = 1; // but we don't really care how they are grouped then
|
||||
m_ExpectDespawns = true;
|
||||
|
||||
for (int i = 0; i < ticksToRun; i++)
|
||||
{
|
||||
AdvanceOneTick();
|
||||
}
|
||||
|
||||
Debug.Assert(m_DespawnedObjectCount == objectsToSpawn);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSnapshotMessageLoss()
|
||||
{
|
||||
var r = new Random();
|
||||
Prepare();
|
||||
|
||||
m_SpawnedObjectCount = 0;
|
||||
m_NextSequence = 0;
|
||||
m_ExpectSpawns = true;
|
||||
m_ExpectDespawns = false;
|
||||
m_MinSpawns = 1;
|
||||
m_LoseNextMessage = false;
|
||||
m_PassBackResponses = false;
|
||||
|
||||
var ticksToRun = 10;
|
||||
|
||||
for (int i = 0; i < ticksToRun; i++)
|
||||
{
|
||||
m_LoseNextMessage = (r.Next() % 2) > 0;
|
||||
|
||||
SendSpawnToSnapshot((ulong)i);
|
||||
AdvanceOneTick();
|
||||
}
|
||||
|
||||
m_LoseNextMessage = false;
|
||||
AdvanceOneTick();
|
||||
AdvanceOneTick();
|
||||
|
||||
Debug.Assert(m_SpawnedObjectCount == ticksToRun);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSnapshotAcks()
|
||||
{
|
||||
Prepare();
|
||||
|
||||
m_SpawnedObjectCount = 0;
|
||||
m_NextSequence = 0;
|
||||
m_ExpectSpawns = true;
|
||||
m_ExpectDespawns = false;
|
||||
m_MinSpawns = 1;
|
||||
m_LoseNextMessage = false;
|
||||
m_PassBackResponses = true;
|
||||
|
||||
var objectsToSpawn = 10;
|
||||
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
SendSpawnToSnapshot((ulong)i);
|
||||
}
|
||||
AdvanceOneTickSendSide(); // let's tick the send multiple time, to check it still tries to send
|
||||
AdvanceOneTick();
|
||||
|
||||
m_ExpectSpawns = false; // all spawns should have made it back and forth and be absent from next messages
|
||||
AdvanceOneTick();
|
||||
|
||||
for (int i = 0; i < objectsToSpawn; i++)
|
||||
{
|
||||
SendDespawnToSnapshot((ulong)i);
|
||||
}
|
||||
|
||||
m_ExpectDespawns = true; // we should now be seeing despawns
|
||||
AdvanceOneTickSendSide(); // let's tick the send multiple time, to check it still tries to send
|
||||
AdvanceOneTick();
|
||||
|
||||
Debug.Assert(m_SpawnedObjectCount == objectsToSpawn);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Tests/Editor/Transports.meta
Normal file
8
Tests/Editor/Transports.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4ecf3bb8c5654c1aae7f73d21e8c56e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
193
Tests/Editor/Transports/BatchedReceiveQueueTests.cs
Normal file
193
Tests/Editor/Transports/BatchedReceiveQueueTests.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using Unity.Networking.Transport;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class BatchedReceiveQueueTests
|
||||
{
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_EmptyReader()
|
||||
{
|
||||
var data = new NativeArray<byte>(0, Allocator.Temp);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_SingleMessage()
|
||||
{
|
||||
var dataLength = sizeof(int) + 1;
|
||||
|
||||
var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
writer.WriteInt(1);
|
||||
writer.WriteByte((byte)42);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
|
||||
var message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_MultipleMessages()
|
||||
{
|
||||
var dataLength = (sizeof(int) + 1) * 2;
|
||||
|
||||
var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
writer.WriteInt(1);
|
||||
writer.WriteByte((byte)42);
|
||||
writer.WriteInt(1);
|
||||
writer.WriteByte((byte)142);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
|
||||
var message1 = q.PopMessage();
|
||||
Assert.AreEqual(1, message1.Count);
|
||||
Assert.AreEqual((byte)42, message1.Array[message1.Offset]);
|
||||
|
||||
var message2 = q.PopMessage();
|
||||
Assert.AreEqual(1, message2.Count);
|
||||
Assert.AreEqual((byte)142, message2.Array[message2.Offset]);
|
||||
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_PartialMessage()
|
||||
{
|
||||
var dataLength = sizeof(int);
|
||||
|
||||
var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
writer.WriteInt(42);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_PushReader_ToFilledQueue()
|
||||
{
|
||||
var data1Length = sizeof(int);
|
||||
var data2Length = sizeof(byte);
|
||||
|
||||
var data1 = new NativeArray<byte>(data1Length, Allocator.Temp);
|
||||
var data2 = new NativeArray<byte>(data2Length, Allocator.Temp);
|
||||
|
||||
var writer1 = new DataStreamWriter(data1);
|
||||
writer1.WriteInt(1);
|
||||
var writer2 = new DataStreamWriter(data2);
|
||||
writer2.WriteByte(42);
|
||||
|
||||
var reader1 = new DataStreamReader(data1);
|
||||
var reader2 = new DataStreamReader(data2);
|
||||
|
||||
var q = new BatchedReceiveQueue(reader1);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
|
||||
q.PushReader(reader2);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
|
||||
var message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_PushReader_ToPartiallyFilledQueue()
|
||||
{
|
||||
var dataLength = sizeof(int) + 1;
|
||||
|
||||
var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
writer.WriteInt(1);
|
||||
writer.WriteByte((byte)42);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
|
||||
reader = new DataStreamReader(data);
|
||||
q.PushReader(reader);
|
||||
|
||||
var message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
reader = new DataStreamReader(data);
|
||||
q.PushReader(reader);
|
||||
|
||||
message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedReceiveQueue_PushReader_ToEmptyQueue()
|
||||
{
|
||||
var dataLength = sizeof(int) + 1;
|
||||
|
||||
var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
writer.WriteInt(1);
|
||||
writer.WriteByte((byte)42);
|
||||
|
||||
var reader = new DataStreamReader(data);
|
||||
var q = new BatchedReceiveQueue(reader);
|
||||
|
||||
Assert.False(q.IsEmpty);
|
||||
|
||||
q.PopMessage();
|
||||
|
||||
Assert.True(q.IsEmpty);
|
||||
|
||||
reader = new DataStreamReader(data);
|
||||
q.PushReader(reader);
|
||||
|
||||
var message = q.PopMessage();
|
||||
Assert.AreEqual(1, message.Count);
|
||||
Assert.AreEqual((byte)42, message.Array[message.Offset]);
|
||||
|
||||
Assert.AreEqual(default(ArraySegment<byte>), q.PopMessage());
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d41788be1de34b7c8bcfce6a2877754
|
||||
guid: aabb21b30a80142ea86e59d1b4d5c587
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
266
Tests/Editor/Transports/BatchedSendQueueTests.cs
Normal file
266
Tests/Editor/Transports/BatchedSendQueueTests.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Unity.Collections;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using Unity.Networking.Transport;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class BatchedSendQueueTests
|
||||
{
|
||||
private const int k_TestQueueCapacity = 1024;
|
||||
private const int k_TestMessageSize = 42;
|
||||
|
||||
private ArraySegment<byte> m_TestMessage;
|
||||
|
||||
private void AssertIsTestMessage(NativeArray<byte> data)
|
||||
{
|
||||
var reader = new DataStreamReader(data);
|
||||
Assert.AreEqual(k_TestMessageSize, reader.ReadInt());
|
||||
for (int i = 0; i < k_TestMessageSize; i++)
|
||||
{
|
||||
Assert.AreEqual(m_TestMessage.Array[i], reader.ReadByte());
|
||||
}
|
||||
}
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void InitializeTestMessage()
|
||||
{
|
||||
var data = new byte[k_TestMessageSize];
|
||||
for (int i = 0; i < k_TestMessageSize; i++)
|
||||
{
|
||||
data[i] = (byte)i;
|
||||
}
|
||||
m_TestMessage = new ArraySegment<byte>(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_EmptyOnCreation()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
|
||||
Assert.AreEqual(0, q.Length);
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_NotCreatedAfterDispose()
|
||||
{
|
||||
var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
q.Dispose();
|
||||
Assert.False(q.IsCreated);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_PushMessageReturnValue()
|
||||
{
|
||||
// Will fit a single test message, but not two (with overhead included).
|
||||
var queueCapacity = (k_TestMessageSize * 2) + BatchedSendQueue.PerMessageOverhead;
|
||||
|
||||
using var q = new BatchedSendQueue(queueCapacity);
|
||||
|
||||
Assert.True(q.PushMessage(m_TestMessage));
|
||||
Assert.False(q.PushMessage(m_TestMessage));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_LengthIncreasedAfterPush()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
Assert.AreEqual(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead, q.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_PushedMessageGeneratesCopy()
|
||||
{
|
||||
var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
var queueCapacity = messageLength * 2;
|
||||
|
||||
using var q = new BatchedSendQueue(queueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
q.Consume(messageLength);
|
||||
Assert.IsTrue(q.PushMessage(m_TestMessage));
|
||||
Assert.AreEqual(queueCapacity, q.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_ReturnValue()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
var filled = q.FillWriterWithMessages(ref writer);
|
||||
Assert.AreEqual(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead, filled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_NoopIfNoPushedMessages()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(0, q.FillWriterWithMessages(ref writer));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_NoopIfNotEnoughCapacity()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(2, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(0, q.FillWriterWithMessages(ref writer));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_SinglePushedMessage()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
q.FillWriterWithMessages(ref writer);
|
||||
AssertIsTestMessage(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_MultiplePushedMessages()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
q.FillWriterWithMessages(ref writer);
|
||||
|
||||
var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
AssertIsTestMessage(data);
|
||||
AssertIsTestMessage(data.GetSubArray(messageLength, messageLength));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithMessages_PartialPushedMessages()
|
||||
{
|
||||
var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(messageLength, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(messageLength, q.FillWriterWithMessages(ref writer));
|
||||
AssertIsTestMessage(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithBytes_NoopIfNoData()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(0, q.FillWriterWithBytes(ref writer));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityMoreThanLength()
|
||||
{
|
||||
var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(k_TestQueueCapacity, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer));
|
||||
AssertIsTestMessage(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityLessThanLength()
|
||||
{
|
||||
var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer));
|
||||
AssertIsTestMessage(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_FillWriterWithBytes_WriterCapacityEqualToLength()
|
||||
{
|
||||
var dataLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
using var data = new NativeArray<byte>(dataLength, Allocator.Temp);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var writer = new DataStreamWriter(data);
|
||||
Assert.AreEqual(dataLength, q.FillWriterWithBytes(ref writer));
|
||||
AssertIsTestMessage(data);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_ConsumeLessThanLength()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
var messageLength = k_TestMessageSize + BatchedSendQueue.PerMessageOverhead;
|
||||
q.Consume(messageLength);
|
||||
Assert.AreEqual(messageLength, q.Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_ConsumeExactLength()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
q.Consume(k_TestMessageSize + BatchedSendQueue.PerMessageOverhead);
|
||||
Assert.AreEqual(0, q.Length);
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BatchedSendQueue_ConsumeMoreThanLength()
|
||||
{
|
||||
using var q = new BatchedSendQueue(k_TestQueueCapacity);
|
||||
|
||||
q.PushMessage(m_TestMessage);
|
||||
|
||||
q.Consume(k_TestQueueCapacity);
|
||||
Assert.AreEqual(0, q.Length);
|
||||
Assert.True(q.IsEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85ac488e1432d49668c711fa625a0743
|
||||
guid: 51a68dc80bf18443180f3600eb5890d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
84
Tests/Editor/Transports/UnityTransportTests.cs
Normal file
84
Tests/Editor/Transports/UnityTransportTests.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using NUnit.Framework;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Unity.Netcode.EditorTests
|
||||
{
|
||||
public class UnityTransportTests
|
||||
{
|
||||
// Check that starting a server doesn't immediately result in faulted tasks.
|
||||
[Test]
|
||||
public void BasicInitServer()
|
||||
{
|
||||
UnityTransport transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
Assert.True(transport.StartServer());
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
|
||||
// Check that starting a client doesn't immediately result in faulted tasks.
|
||||
[Test]
|
||||
public void BasicInitClient()
|
||||
{
|
||||
UnityTransport transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
Assert.True(transport.StartClient());
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
|
||||
// Check that we can't restart a server.
|
||||
[Test]
|
||||
public void NoRestartServer()
|
||||
{
|
||||
UnityTransport transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
transport.StartServer();
|
||||
Assert.False(transport.StartServer());
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
|
||||
// Check that we can't restart a client.
|
||||
[Test]
|
||||
public void NoRestartClient()
|
||||
{
|
||||
UnityTransport transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
transport.StartClient();
|
||||
Assert.False(transport.StartClient());
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
|
||||
// Check that we can't start both a server and client on the same transport.
|
||||
[Test]
|
||||
public void NotBothServerAndClient()
|
||||
{
|
||||
UnityTransport transport;
|
||||
|
||||
// Start server then client.
|
||||
transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
transport.StartServer();
|
||||
Assert.False(transport.StartClient());
|
||||
|
||||
transport.Shutdown();
|
||||
|
||||
// Start client then server.
|
||||
transport = new GameObject().AddComponent<UnityTransport>();
|
||||
transport.Initialize();
|
||||
|
||||
transport.StartClient();
|
||||
Assert.False(transport.StartServer());
|
||||
|
||||
transport.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a05afab7f08d44c07b2c5e144ba0b45a
|
||||
guid: 1b0137a26ef0140f0bf5167c09eecb96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -9,7 +9,8 @@
|
||||
"Unity.Multiplayer.MetricTypes",
|
||||
"Unity.Multiplayer.NetStats",
|
||||
"Unity.Multiplayer.Tools.MetricTypes",
|
||||
"Unity.Multiplayer.Tools.NetStats"
|
||||
"Unity.Multiplayer.Tools.NetStats",
|
||||
"Unity.Networking.Transport"
|
||||
],
|
||||
"optionalUnityReferences": [
|
||||
"TestAssemblies"
|
||||
|
||||
Reference in New Issue
Block a user