-
Notifications
You must be signed in to change notification settings - Fork 461
fix: Don't let exceptions in OnNetworkSpawn/OnNetworkDespawn block processing of the next callback. [MTT-1378] #1739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
6b3e1ab
d502aa1
ef344d2
4749f46
23d4b15
012aa98
530e728
84b195a
032202b
cede7c3
2ece99f
8a7c8b8
a70c778
3753803
5017321
0fe6471
2ba24c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| using System; | ||
| using System.Collections; | ||
| using Unity.Netcode; | ||
| using Unity.Netcode.RuntimeTests; | ||
| using UnityEngine; | ||
| using UnityEngine.Assertions; | ||
| using UnityEngine.TestTools; | ||
|
|
||
| namespace TestProject.RuntimeTests | ||
| { | ||
|
|
||
| public class OnNetworkSpawnThrowsExceptionComponent : NetworkBehaviour | ||
| { | ||
| public static int NumClientSpawns = 0; | ||
| public override void OnNetworkSpawn() | ||
| { | ||
| if (IsClient) | ||
| { | ||
| ++NumClientSpawns; | ||
| if (NumClientSpawns > 2) | ||
| { | ||
| throw new Exception("I'm misbehaving"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| public class OnNetworkDespawnThrowsExceptionComponent : NetworkBehaviour | ||
| { | ||
| public static int NumClientDespawns = 0; | ||
| public override void OnNetworkDespawn() | ||
| { | ||
| if (IsClient) | ||
| { | ||
| ++NumClientDespawns; | ||
| if (NumClientDespawns > 2) | ||
| { | ||
| throw new Exception("I'm misbehaving"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } | ||
| public class OnNetworkSpawnExceptionTests : BaseMultiInstanceTest | ||
| { | ||
| private GameObject m_Prefab; | ||
| private GameObject[] m_Objects = new GameObject[5]; | ||
|
|
||
| [UnityTest] | ||
| public IEnumerator WhenOnNetworkSpawnThrowsException_FutureOnNetworkSpawnsAreNotPrevented() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These tests feel pretty rough in their current state.
While it's a very contentious topic, generally speaking, the more self-contained a test is, the better for understanding and lower the risk for future false positives. I'm not personally a fan of having to read 3 classes and 6 methods to understand what's actually happening in this 1 line test case.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While throwing an exception in a component added to the player prefab is valid, I think this test should add more NetworkBehaviour derived components because the real test is to validate that all NetworkBehaviour components on a GameObject get OnNetworkSpawn and OnNetworkDespawn invoked even if one of the components throws and exception.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I've addressed everything you mentioned here, except for the use of multi-instance tests. I think it's valuable to test that the behavior is the same on both server and client. I did, however, update the test to make sure it isn't exclusively a client-side test, since OnNetworkSpawn and OnNetworkDespawn are called on the server too. |
||
| { | ||
| //Spawning was done during setup | ||
| Assert.AreEqual(5, OnNetworkSpawnThrowsExceptionComponent.NumClientSpawns); | ||
| yield return null; | ||
| } | ||
|
|
||
| [UnityTest] | ||
| public IEnumerator WhenOnNetworkDespawnThrowsException_FutureOnNetworkDespawnsAreNotPrevented() | ||
| { | ||
| //Spawning was done during setup. Now we despawn. | ||
| for (var i = 0; i < 5; ++i) | ||
| { | ||
| m_Objects[i].GetComponent<NetworkObject>().Despawn(); | ||
| } | ||
|
|
||
| var result = new MultiInstanceHelpers.CoroutineResultWrapper<bool>(); | ||
| yield return MultiInstanceHelpers.Run( | ||
| MultiInstanceHelpers.WaitForCondition( | ||
| () => OnNetworkDespawnThrowsExceptionComponent.NumClientDespawns == 5, result)); | ||
| Assert.IsTrue(result.Result); | ||
| } | ||
|
|
||
| public override IEnumerator Setup() | ||
| { | ||
| yield return StartSomeClientsAndServerWithPlayers(true, NbClients, _ => | ||
| { | ||
| m_Prefab = new GameObject(); | ||
| var networkObject = m_Prefab.AddComponent<NetworkObject>(); | ||
| m_Prefab.AddComponent<OnNetworkSpawnThrowsExceptionComponent>(); | ||
| MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject); | ||
|
|
||
| var validNetworkPrefab = new NetworkPrefab(); | ||
| validNetworkPrefab.Prefab = m_Prefab; | ||
| m_ServerNetworkManager.NetworkConfig.NetworkPrefabs.Add(validNetworkPrefab); | ||
| foreach (var client in m_ClientNetworkManagers) | ||
| { | ||
| client.NetworkConfig.NetworkPrefabs.Add(validNetworkPrefab); | ||
| } | ||
| }); | ||
|
|
||
| for (var i = 0; i < 5; ++i) | ||
| { | ||
| var obj = UnityEngine.Object.Instantiate(m_Prefab); | ||
| m_Objects[i] = obj; | ||
| obj.GetComponent<NetworkObject>().NetworkManagerOwner = m_ServerNetworkManager; | ||
| obj.GetComponent<NetworkObject>().Spawn(); | ||
| } | ||
|
|
||
| var result = new MultiInstanceHelpers.CoroutineResultWrapper<bool>(); | ||
| MultiInstanceHelpers.Run( | ||
| MultiInstanceHelpers.WaitForCondition( | ||
| () => OnNetworkSpawnThrowsExceptionComponent.NumClientSpawns == 5, result)); | ||
| Assert.IsTrue(result.Result); | ||
| } | ||
| protected override int NbClients => 1; | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.