Skip to content

Commit 67a55b2

Browse files
committed
Add a test for resetting extended ownership flags
1 parent 7cca38b commit 67a55b2

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/OwnershipPermissionsTests.cs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,108 @@ private IEnumerator ValidateRequestAndPermissionsChangeRaceCondition(NetworkObje
499499
AssertOnTimeout($"[{newStatus}][Set RequestRequired][Permissions mismatch] {firstClient.name}");
500500
}
501501

502+
[UnityTest]
503+
public IEnumerator ResetExtendedOwnershipFlagsOnRespawn()
504+
{
505+
var extendedFlags = (NetworkObject.OwnershipStatusExtended[])Enum.GetValues(typeof(NetworkObject.OwnershipStatusExtended));
506+
Assert.That(extendedFlags.Length, Is.LessThan(NumberOfClients), "This test should have at least one more non-authority client than extended flags!");
507+
508+
var spawnedObjects = new List<NetworkObject>();
509+
while (spawnedObjects.Count <= extendedFlags.Length)
510+
{
511+
var ownerClient = GetNonAuthorityNetworkManager(spawnedObjects.Count);
512+
var spawnedObject = SpawnObject(m_PermissionsObject, ownerClient).GetComponent<NetworkObject>();
513+
spawnedObject.SetOwnershipStatus(NetworkObject.OwnershipStatus.RequestRequired, true);
514+
spawnedObjects.Add(spawnedObject);
515+
}
516+
517+
yield return WaitForSpawnedOnAllOrTimeOut(spawnedObjects);
518+
AssertOnTimeout("[InitialSpawn] Not all objects are spawned on all clients!");
519+
520+
for (int i = 0; i < extendedFlags.Length; i++)
521+
{
522+
var flag = extendedFlags[i];
523+
var obj = spawnedObjects[i];
524+
obj.AddOwnershipExtended(flag);
525+
obj.SendOwnershipStatusUpdate();
526+
527+
m_ObjectToValidate = obj;
528+
yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients);
529+
AssertOnTimeout($"[{flag}] Not all clients have set the permission on the object!");
530+
}
531+
532+
// Despawn the objects
533+
foreach (var networkObject in spawnedObjects)
534+
{
535+
networkObject.Despawn(false);
536+
}
537+
538+
yield return WaitForDespawnedOnAllOrTimeOut(spawnedObjects);
539+
AssertOnTimeout("Not all clients have despawned all objects!");
540+
541+
// Respawn the objects
542+
foreach (var networkObject in spawnedObjects)
543+
{
544+
networkObject.Spawn();
545+
}
546+
547+
yield return WaitForSpawnedOnAllOrTimeOut(spawnedObjects);
548+
AssertOnTimeout("[ReSpawn] Not all objects are spawned on all clients!");
549+
550+
// Requesting ownership should work as expected
551+
var nonAuthorityIndex = 1; // Start the index at one more than the initial ownership
552+
var objectToOwner = new Dictionary<NetworkObject, NetworkManager>();
553+
foreach (var networkObject in spawnedObjects)
554+
{
555+
var nextOwner = GetNonAuthorityNetworkManager(nonAuthorityIndex++);
556+
Assert.That(nextOwner.LocalClientId, Is.Not.EqualTo(networkObject.OwnerClientId));
557+
Assert.IsTrue(nextOwner.SpawnManager.SpawnedObjects.TryGetValue(networkObject.NetworkObjectId, out var nextOwnerInstance));
558+
Assert.That(nextOwnerInstance, Is.Not.Null);
559+
560+
var requestStatus = nextOwnerInstance.RequestOwnership();
561+
Assert.That(requestStatus, Is.EqualTo(NetworkObject.OwnershipRequestStatus.RequestSent));
562+
563+
objectToOwner.Add(networkObject, nextOwner);
564+
}
565+
566+
yield return WaitForConditionOrTimeOut(errorLog =>
567+
{
568+
foreach (var client in m_NetworkManagers)
569+
{
570+
foreach (var (networkObject, expectedOwner) in objectToOwner)
571+
{
572+
if (!client.SpawnManager.SpawnedObjects.TryGetValue(networkObject.NetworkObjectId, out var clientInstance))
573+
{
574+
errorLog.AppendLine($"Object-{networkObject.NetworkObjectId} is not spawned on client-{client.LocalClientId}");
575+
return false;
576+
}
577+
578+
if (clientInstance.OwnerClientId != expectedOwner.LocalClientId)
579+
{
580+
errorLog.AppendLine($"Client-{client.LocalClientId} has the incorrect owner for Object-{networkObject.NetworkObjectId}");
581+
return false;
582+
}
583+
584+
if (clientInstance.IsOwner != (client == expectedOwner))
585+
{
586+
errorLog.AppendLine($"Client-{client.LocalClientId} has the incorrect IsOwner for Object-{networkObject.NetworkObjectId}");
587+
return false;
588+
}
589+
}
590+
}
591+
592+
return true;
593+
});
594+
AssertOnTimeout("Some ownership requests failed!");
595+
596+
foreach (var networkObject in spawnedObjects)
597+
{
598+
m_ObjectToValidate = networkObject;
599+
yield return WaitForConditionOrTimeOut(ValidatePermissionsOnAllClients);
600+
AssertOnTimeout($"[Object-{networkObject.NetworkObjectId}] Not all clients have set the permission on the object!");
601+
}
602+
}
603+
502604
internal class OwnershipPermissionsTestHelper : NetworkBehaviour
503605
{
504606
public static NetworkObject CurrentOwnedInstance;

com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,33 @@ bool ValidateObjectsSpawnedOnAllClients(StringBuilder errorLog)
20012001
yield return WaitForConditionOrTimeOut(ValidateObjectsSpawnedOnAllClients, timeOutHelper);
20022002
}
20032003

2004+
/// <summary>
2005+
/// Waits until all given NetworkObjects are spawned on all clients or a timeout occurs.
2006+
/// </summary>
2007+
/// <param name="networkObjects">The list of <see cref="NetworkObject"/>s to wait for.</param>
2008+
/// <param name="timeOutHelper">An optional <see cref="TimeoutHelper"/> to control the timeout period. If null, the default timeout is used.</param>
2009+
/// <returns>An <see cref="IEnumerator"/> for use in Unity coroutines.</returns>
2010+
protected IEnumerator WaitForDespawnedOnAllOrTimeOut(List<NetworkObject> networkObjects, TimeoutHelper timeOutHelper = null)
2011+
{
2012+
bool ValidateObjectsDespawnedOnAllClients(StringBuilder errorLog)
2013+
{
2014+
foreach (var client in m_NetworkManagers)
2015+
{
2016+
foreach (var networkObject in networkObjects)
2017+
{
2018+
if (client.SpawnManager.SpawnedObjects.TryGetValue(networkObject.NetworkObjectId, out NetworkObject clientObj) && clientObj.IsSpawned)
2019+
{
2020+
errorLog.Append($"Object-{networkObject.NetworkObjectId} is still spawned on Client-{client.LocalClientId}!");
2021+
return false;
2022+
}
2023+
}
2024+
}
2025+
return true;
2026+
}
2027+
2028+
yield return WaitForConditionOrTimeOut(ValidateObjectsDespawnedOnAllClients, timeOutHelper);
2029+
}
2030+
20042031
/// <summary>
20052032
/// Validates that all remote clients (i.e. non-server) detect they are connected
20062033
/// to the server and that the server reflects the appropriate number of clients

0 commit comments

Comments
 (0)