From 5b4291be2bdd514c02ead88aa20630a201c0597b Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 16 Oct 2026 23:18:27 -0400 Subject: [PATCH 1/6] fix: Yamato jobs not testing built player (Backport of: #4194) * fix: Yamato jobs not testing built player * Next round of fixes * Set addressables to build on players * dotnet-fix * Fix console tests * Try again to remove graphics from desktop players * Fix DA NetworkObjectDeserializationFailure test * Remove the temporarily added N4E settings * Fix the test failures * Remove fix that was more a symptom than a cause (keep it simple) * Match the deregistration to the registration logic * Don't finish cleaning up if any scene is still loading * Fix the U-PR config * Fix IL2CPP player tests --- .pr_agent.toml | 1 - .yamato/cmb-service-standalone-tests.yml | 3 +- .yamato/console-standalone-test.yml | 13 ++- .yamato/desktop-standalone-tests.yml | 7 +- .yamato/mobile-standalone-test.yml | 7 +- Tools/CI/service.cmb/run_cmb_service.sh | 4 +- .../NetworkTransformOrderOfOperations.cs | 1 + .../NetworkVariable/NetworkVariableTests.cs | 13 +-- .../NetworkVariableTraitsTests.cs | 8 +- .../Components/ObjectNameIdentifier.cs | 12 +-- .../IntegrationTestSceneHandler.cs | 3 +- .../TestHelpers/NetcodeIntegrationTest.cs | 83 +++++++++++++++++-- .../UnityTransportConnectionTests.cs | 1 + .../AddressableAssetSettings.asset | 2 +- 14 files changed, 112 insertions(+), 46 deletions(-) diff --git a/.pr_agent.toml b/.pr_agent.toml index 71d8783c0c..9a8dba21cd 100644 --- a/.pr_agent.toml +++ b/.pr_agent.toml @@ -4,6 +4,5 @@ # https://developer.portal.internal.unity.com/catalog/default/component/u-pr/docs/configuration/automatic_runs/ [github_app] -handle_pr_actions = ['opened', 'ready_for_review'] # PR events that auto-run pr_commands pr_commands = ["/harness-review"] # what runs on those events reviewer_commands = ["/harness-review"] # what runs when @u-pr is added as reviewer diff --git a/.yamato/cmb-service-standalone-tests.yml b/.yamato/cmb-service-standalone-tests.yml index 145a9c1618..6cd8bfa375 100644 --- a/.yamato/cmb-service-standalone-tests.yml +++ b/.yamato/cmb-service-standalone-tests.yml @@ -56,8 +56,7 @@ cmb_service_standalone_test_{{ project.name }}_{{ platform.name }}_{{ backend }} # run_cmb_service.sh builds and starts a release version of the full CMB service (along with the limited echo server) - ./Tools/CI/service.cmb/run_cmb_service.sh -e $ECHO_SERVER_PORT -s $CMB_SERVICE_PORT -l artifacts - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %} {% if platform.name == "mac" %} --arch arm64 {% endif %} # For macOS we use ARM64 models - - UnifiedTestRunner --suite=playmode --player-load-path=build/players --artifacts-path=test-results --testproject={{ project.path }} --editor-location=.Editor --playergraphicsapi=Null --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --scripting-backend={{ backend }} --player-load-path=build/players --artifacts-path=test-results --testproject={{ project.path }} --extra-player-arg=-batchmode --extra-player-arg=-nographics --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --timeout={{ test_timeout }} artifacts: logs: paths: diff --git a/.yamato/console-standalone-test.yml b/.yamato/console-standalone-test.yml index 9574e07e1b..4df4ed8969 100644 --- a/.yamato/console-standalone-test.yml +++ b/.yamato/console-standalone-test.yml @@ -88,8 +88,17 @@ console_standalone_test_{{ project.name }}_{{ platform.name }}_{{ editor }}: model: {{ platform.model }} # This is set only in platforms where we want non-default model to use (more information in project.metafile) {% endif %} commands: - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor -c il2cpp -c {{ platform.name }} - - UnifiedTestRunner --suite=playmode --testproject={{ project.path }} --editor-location=.Editor --artifacts-path=test-results --player-load-path=build/players --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} + # Console players connect back to UTR's player connection listener on this VM, so the firewall must allow it + - command: gsudo NetSh Advfirewall set allprofiles state off + # Register the Bokken devkit with the platform's target tools so UTR can deploy and run the prebuilt player +{% if platform.name == "ps5" %} + - command: gsudo prospero-ctrl target add %BOKKEN_DEVICE_IP% +{% elsif platform.name == "ps4" %} + - command: orbis-ctrl add %BOKKEN_DEVICE_IP% +{% else %} + - command: '"%GameDK%/bin/xbconnect" /WS %BOKKEN_DEVICE_IP%' +{% endif %} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --scripting-backend=il2cpp --testproject={{ project.path }} --artifacts-path=test-results --player-load-path=build/players --player-connection-ip=%BOKKEN_HOST_IP% --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --timeout={{ test_timeout }} variables: # PS4 related SCE_ORBIS_SDK_DIR: 'C:\Users\bokken\SCE\ps4_sdk_12_00' diff --git a/.yamato/desktop-standalone-tests.yml b/.yamato/desktop-standalone-tests.yml index 551b8a91d3..13fd9508f0 100644 --- a/.yamato/desktop-standalone-tests.yml +++ b/.yamato/desktop-standalone-tests.yml @@ -43,8 +43,8 @@ desktop_standalone_build_{{ project.name }}_{{ platform.name }}_{{ backend }}_{{ model: {{ platform.model }} # This is set only in platforms where we want non-default model to use (more information in project.metafile) {% endif %} commands: - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %} - - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --testproject={{ project.path }} --scripting-backend={{ backend }} --testfilter="Unity.Netcode.RuntimeTests.*" --player-save-path=build/players --artifacts-path=artifacts --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} + - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %}{% if backend == "coreclr" %}{% unless coreclr_runtime_editors contains editor %} -c {{ platform.coreclr_component }} {% endunless %}{% endif %} --arch {{ platform.architecture }} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --testproject={{ project.path }} --scripting-backend={{ backend }} --testfilter="Unity.Netcode.RuntimeTests.*;TestProject.RuntimeTests.*" --playergraphicsapi=Null --player-save-path=build/players --artifacts-path=artifacts --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} artifacts: players: paths: @@ -79,8 +79,7 @@ desktop_standalone_test_{{ project.name }}_{{ platform.name }}_{{ backend }}_{{ {% endif %} commands: - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %} {% if platform.name == "mac" %} --arch arm64 {% endif %} # For macOS we use ARM64 models - - UnifiedTestRunner --suite=playmode --player-load-path=build/players --artifacts-path=test-results --testproject={{ project.path }} --editor-location=.Editor --playergraphicsapi=Null --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --scripting-backend={{ backend }} --player-load-path=build/players --artifacts-path=test-results --testproject={{ project.path }} --extra-player-arg=-batchmode --extra-player-arg=-nographics --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --timeout={{ test_timeout }} artifacts: logs: paths: diff --git a/.yamato/mobile-standalone-test.yml b/.yamato/mobile-standalone-test.yml index 4bb41db94e..686cfcb24d 100644 --- a/.yamato/mobile-standalone-test.yml +++ b/.yamato/mobile-standalone-test.yml @@ -82,9 +82,6 @@ mobile_standalone_test_{{ project.name }}_{{ platform.name }}_{{ editor }}: model: {{ platform.model }} # This is set only in platforms where we want non-default model to use (more information in project.metafile) {% endif %} commands: - # Installing editor. We still need the editor to run tests on standalone build and for that the Editor is required - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor -c il2cpp {% if platform.base == "mac" %} -c ios {% else %} -c android {% endif %} - {% if platform.standalone == "Android" %} # Download standalone UnityTestRunner and ADB setup - command: wget http://artifactory-slo.bf.unity3d.com/artifactory/mobile-generic/android/ADBKeys.zip!/adbkey.pub -O %USERPROFILE%/.android/adbkey.pub @@ -97,11 +94,11 @@ mobile_standalone_test_{{ project.name }}_{{ platform.name }}_{{ editor }}: # Run tests for Android devices - | set ANDROID_DEVICE_CONNECTION=%BOKKEN_DEVICE_IP% - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --artifacts-path=test-results --player-load-path=build/players --testproject={{ project.path }} --editor-location=.Editor --player-connection-ip=%BOKKEN_HOST_IP% --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} + UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --artifacts-path=test-results --player-load-path=build/players --testproject={{ project.path }} --player-connection-ip=%BOKKEN_HOST_IP% --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --timeout={{ test_timeout }} {% else %} # Run tests for non-Android devices - - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --artifacts-path=test-results --player-load-path=build/players --testproject={{ project.path }} --editor-location=.Editor --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} --device-id=%BOKKEN_DEVICE_ID% + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --artifacts-path=test-results --player-load-path=build/players --testproject={{ project.path }} --fail-on-assert --rerun-strategy=Test --retry={{ num_test_retries }} --timeout={{ test_timeout }} --device-id=%BOKKEN_DEVICE_ID% {% endif %} artifacts: logs: diff --git a/Tools/CI/service.cmb/run_cmb_service.sh b/Tools/CI/service.cmb/run_cmb_service.sh index 8dd26df88a..05fe686538 100755 --- a/Tools/CI/service.cmb/run_cmb_service.sh +++ b/Tools/CI/service.cmb/run_cmb_service.sh @@ -171,8 +171,8 @@ cargo build --release --locked # The infinite loop is required as the service will exit each time all connected clients disconnect. # This means the service will exit after each test. The infinite loop will immediately restart the service each time it exits. logMessage "Running service integration tests..." -echo "comb-server -l error --metrics-port 5000 standalone --port $service_port -t 60m --unity-version $unity_version" +echo "comb-server -l warn -l ngo::session=info -l comb_server::session=info --metrics-port 5000 standalone --port $service_port -t 60m --unity-version $unity_version" while :; do - ./target/release/comb-server -l error --metrics-port 5000 standalone --port $service_port -t 60m --unity-version $unity_version; + ./target/release/comb-server -l warn -l ngo::session=info -l comb_server::session=info --metrics-port 5000 standalone --port $service_port -t 60m --unity-version $unity_version; done & # <- use & to run the entire loop in the background diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs index 20630f0803..2f128459ec 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformOrderOfOperations.cs @@ -24,6 +24,7 @@ namespace Unity.Netcode.RuntimeTests [TestFixture(HostOrServer.DAHost)] [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] + [UnityPlatform(exclude = new[] { RuntimePlatform.PS4 })] // Ignored test tracked in MTT-16494 internal class NetworkTransformOrderOfOperations : IntegrationTestWithApproximation { #region Configuration, Properties, and Overrides diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs index a8aa926709..9f7b4c7a7b 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs @@ -1935,7 +1935,6 @@ public string ArrayStr(NativeArray arr) where T : unmanaged [Test] [UnityPlatform(exclude = new[] { RuntimePlatform.Android, RuntimePlatform.IPhonePlayer })] // Ignored test tracked in MTT-11343 - [Repeat(5)] #if ENABLE_CORECLR [Explicit("NGO NetworkVariable serialization codegen not generated for some types on CoreCLR (falls back to FallbackSerializer), see https://jira.unity3d.com/browse/UUM-149592")] #endif @@ -1998,7 +1997,7 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeArrayNetworkV } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetArarys(RandGenBytes); + (var original, var original2, var changed, var changed2) = GetArarys((rand) => rand.Next(2) == 1); TestValueTypeNativeArray(original, changed); TestValueTypeNativeArray(original2, changed2); } @@ -2400,7 +2399,6 @@ public string DictionaryStr(Dictionary list) [Test] [UnityPlatform(exclude = new[] { RuntimePlatform.Android, RuntimePlatform.IPhonePlayer })] // Ignored test tracked in MTT-11343 - [Repeat(5)] #if ENABLE_CORECLR [Explicit("NGO NetworkVariable serialization codegen not generated for some types on CoreCLR (falls back to FallbackSerializer), see https://jira.unity3d.com/browse/UUM-149592")] #endif @@ -2598,7 +2596,6 @@ public void WhenSerializingAndDeserializingVeryLargeListNetworkVariables_ValuesA [Test] [UnityPlatform(exclude = new[] { RuntimePlatform.Android, RuntimePlatform.IPhonePlayer })] // Ignored test tracked in MTT-11343 - [Repeat(5)] #if ENABLE_CORECLR [Explicit("NGO NetworkVariable serialization codegen not generated for some types on CoreCLR (falls back to FallbackSerializer), see https://jira.unity3d.com/browse/UUM-149592")] #endif @@ -2764,8 +2761,7 @@ public void WhenSerializingAndDeserializingVeryLargeHashSetNetworkVariables_Valu } [Test] - [UnityPlatform(exclude = new[] { RuntimePlatform.Android, RuntimePlatform.IPhonePlayer })] // Ignored test tracked in MTT-11343 - [Repeat(5)] + [UnityPlatform(exclude = new[] { RuntimePlatform.Android, RuntimePlatform.IPhonePlayer, RuntimePlatform.PS4, RuntimePlatform.PS5 })] // Ignored test tracked in MTT-11343, MTT-16494 #if ENABLE_CORECLR [Explicit("NGO NetworkVariable serialization codegen not generated for some types on CoreCLR (falls back to FallbackSerializer), see https://jira.unity3d.com/browse/UUM-149592")] #endif @@ -3910,7 +3906,6 @@ public string NativeHashMapStr(NativeHashMap list) } [Test] - [Repeat(5)] public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeListNetworkVariables_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), @@ -4101,11 +4096,10 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeListNetworkVa } [Test] - [Repeat(5)] public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashSetNetworkVariables_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(bool), typeof(char), typeof(float), typeof(double), + typeof(long), typeof(ulong), typeof(char), typeof(float), typeof(double), typeof(Vector2), typeof(Vector3), typeof(Vector2Int), typeof(Vector3Int), typeof(Vector4), typeof(Quaternion), typeof(Pose), typeof(HashableNetworkVariableTestStruct), typeof(FixedString32Bytes))] Type testType) @@ -4261,7 +4255,6 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashSetNetwor } [Test] - [Repeat(5)] public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashMapNetworkVariables_ValuesAreSerializedCorrectly( [Values(typeof(byte), typeof(ulong), typeof(Vector2), typeof(HashMapKeyStruct))] Type keyType, diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs index 0672b50077..acdd07cddd 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTraitsTests.cs @@ -100,7 +100,7 @@ public IEnumerator WhenNewValueIsLessThanThresholdButMaxTimeHasPassed_VariableIs var authorityComponent = GetAuthorityComponent(); authorityComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; authorityComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MaxSecondsBetweenUpdates = 1.0f }); - authorityComponent.TheVariable.LastUpdateSent = authorityComponent.NetworkManager.NetworkTimeSystem.LocalTime; + authorityComponent.TheVariable.UpdateLastSentTime(); var timeoutHelper = new TimeoutHelper(0.62f); var newValue = 0.05f; @@ -120,7 +120,7 @@ public IEnumerator WhenNewValueIsGreaterThanThresholdButMinTimeHasNotPassed_Vari var authorityComponent = GetAuthorityComponent(); authorityComponent.TheVariable.CheckExceedsDirtinessThreshold = (in float value, in float newValue) => Mathf.Abs(newValue - value) >= 0.1; authorityComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 1 }); - authorityComponent.TheVariable.LastUpdateSent = authorityComponent.NetworkManager.NetworkTimeSystem.LocalTime; + authorityComponent.TheVariable.UpdateLastSentTime(); var timeoutHelper = new TimeoutHelper(0.62f); var newValue = 0.15f; @@ -139,7 +139,7 @@ public IEnumerator WhenNoThresholdIsSetButMinTimeHasNotPassed_VariableIsNotSeria { var authorityComponent = GetAuthorityComponent(); authorityComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 1 }); - authorityComponent.TheVariable.LastUpdateSent = authorityComponent.NetworkManager.NetworkTimeSystem.LocalTime; + authorityComponent.TheVariable.UpdateLastSentTime(); var timeoutHelper = new TimeoutHelper(0.62f); var newValue = 0.15f; @@ -163,7 +163,7 @@ public IEnumerator WhenNonTraitsIsDirtyButTraitsIsNotReadyToSend() { var authorityComponent = GetAuthorityComponent(); authorityComponent.TheVariable.SetUpdateTraits(new NetworkVariableUpdateTraits { MinSecondsBetweenUpdates = 1 }); - authorityComponent.TheVariable.LastUpdateSent = authorityComponent.NetworkManager.NetworkTimeSystem.LocalTime; + authorityComponent.TheVariable.UpdateLastSentTime(); var timeoutHelper = new TimeoutHelper(0.62f); var firstValue = 0.15f; diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/Components/ObjectNameIdentifier.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/Components/ObjectNameIdentifier.cs index e33b6ea313..4df4cdd352 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/Components/ObjectNameIdentifier.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/Components/ObjectNameIdentifier.cs @@ -9,7 +9,7 @@ namespace Unity.Netcode.TestHelpers.Runtime /// public class ObjectNameIdentifier : NetworkBehaviour { - private ulong m_CurrentOwner; + private ulong m_RegisteredLocalClientId; private ulong m_CurrentNetworkObjectId; private bool m_IsRegistered; @@ -45,18 +45,18 @@ protected void RegisterAndLabelNetworkObject() // This is required otherwise it will try to continue to update the NetworkBehaviour even if // it has been destroyed. m_NetworkObject = NetworkObject; - m_CurrentOwner = OwnerClientId; + m_RegisteredLocalClientId = NetworkManager.LocalClientId; m_CurrentNetworkObjectId = NetworkObjectId; var serverOrClient = IsServer ? "Server" : "Client"; if (NetworkObject.IsPlayerObject) { - gameObject.name = NetworkManager.LocalClientId == OwnerClientId ? $"{m_OriginalName}-{k_TagInfoStart}{OwnerClientId}{k_TagInfoStop}-Local{m_OriginalName}" : - $"{m_OriginalName}-{k_TagInfoStart}{OwnerClientId}{k_TagInfoStop}- On{serverOrClient}{k_TagInfoStart}{NetworkManager.LocalClientId}{k_TagInfoStop}"; + gameObject.name = m_RegisteredLocalClientId == OwnerClientId ? $"{m_OriginalName}-{k_TagInfoStart}{OwnerClientId}{k_TagInfoStop}-Local{m_OriginalName}" : + $"{m_OriginalName}-{k_TagInfoStart}{OwnerClientId}{k_TagInfoStop}- On{serverOrClient}{k_TagInfoStart}{m_RegisteredLocalClientId}{k_TagInfoStop}"; } else { - gameObject.name = $"{m_OriginalName}{k_TagInfoStart}{NetworkObjectId}{k_TagInfoStop}-On{serverOrClient}{k_TagInfoStart}{NetworkManager.LocalClientId}{k_TagInfoStop}"; + gameObject.name = $"{m_OriginalName}{k_TagInfoStart}{NetworkObjectId}{k_TagInfoStop}-On{serverOrClient}{k_TagInfoStart}{m_RegisteredLocalClientId}{k_TagInfoStop}"; } // Don't add the player objects to the global list of NetworkObjects @@ -75,7 +75,7 @@ protected void DeRegisterNetworkObject() { if (m_IsRegistered) { - NetcodeIntegrationTest.DeregisterNetworkObject(m_CurrentOwner, m_CurrentNetworkObjectId); + NetcodeIntegrationTest.DeregisterNetworkObject(m_RegisteredLocalClientId, m_CurrentNetworkObjectId); m_IsRegistered = false; } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs index 209caf300b..22d37621d4 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/IntegrationTestSceneHandler.cs @@ -372,7 +372,8 @@ private bool ExcludeSceneFromSynchronizationCheck(Scene scene) public void ClearSceneTracking(NetworkManager networkManager) { - SceneNameToSceneHandles.Clear(); + // Only clear the calling NetworkManager's tracking, other NetworkManagers may still be tracking their own scenes + SceneNameToSceneHandles.Remove(networkManager); } public void StopTrackingScene(NetworkSceneHandle handle, string name, NetworkManager networkManager) diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs index fe1185462b..2f6b0becff 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs @@ -691,6 +691,8 @@ public IEnumerator SetUp() // In addition to setting the number of clients in the OneTimeSetup, we need to re-apply the number of clients for each unique test // in the event that a previous test stopped a client. m_NumberOfClients = NumberOfClients; + // Clear any time out state left by a previous test so it cannot fail this test's assertions + s_GlobalTimeoutHelper.TimedOut = false; VerboseDebugLog.Clear(); VerboseDebug($"Entering {nameof(SetUp)}"); NetcodeLogAssert = new NetcodeLogAssert(); @@ -1076,7 +1078,7 @@ protected void CreateAndStartNewClientWithTimeTravel() // Wait for the new client to connect var connected = WaitForClientsConnectedOrTimeOutWithTimeTravel(); - AssertOnTimeout($"{nameof(CreateAndStartNewClientWithTimeTravel)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}"); + Assert.IsTrue(connected, $"{nameof(CreateAndStartNewClientWithTimeTravel)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}"); OnNewClientStartedAndConnected(networkManager); if (!connected) @@ -1459,9 +1461,9 @@ protected void StartServerAndClientsWithTimeTravel() if (!m_BypassConnectionTimeout) { // Wait for all clients to connect - WaitForClientsConnectedOrTimeOutWithTimeTravel(); + var connected = WaitForClientsConnectedOrTimeOutWithTimeTravel(); - AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}"); + Assert.IsTrue(connected, $"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}"); if (m_UseHost || authorityManager.IsHost) { @@ -1484,8 +1486,8 @@ protected void StartServerAndClientsWithTimeTravel() { foreach (var networkManager in m_NetworkManagers) { - WaitForConditionOrTimeOutWithTimeTravel(() => AllPlayerObjectClonesSpawned(networkManager)); - AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!"); + var spawned = WaitForConditionOrTimeOutWithTimeTravel(() => AllPlayerObjectClonesSpawned(networkManager)); + Assert.IsTrue(spawned, $"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!"); } } @@ -1586,7 +1588,7 @@ protected void ShutdownAndCleanUp() } catch (Exception e) { - throw e; + Debug.LogException(e); } finally { @@ -1706,6 +1708,9 @@ public IEnumerator TearDown() { ShutdownAndCleanUp(); } + + // Wait until all the scene from this test are unloaded before starting the next test. + yield return WaitForRemainingScenesUnloaded(); } if (m_EnableTimeTravel) @@ -2588,22 +2593,84 @@ protected void AssertOnTimeout(string timeOutErrorMessage, TimeoutHelper assigne } - private void UnloadRemainingScenes() + private const float k_SceneUnloadTimeout = 5.0f; + private readonly List m_PendingSceneUnloads = new List(); + + /// true if any scene (other than the test runner scene) is still loading and could not be unloaded yet + private bool UnloadRemainingScenes() { // Unload any remaining scenes loaded but the test runner scene // Note: Some tests only unload the server-side instance, and this // just assures no currently loaded scenes will impact the next test + Scene testRunnerScene = default; + var sceneStillLoading = false; for (int i = 0; i < SceneManager.sceneCount; i++) { var scene = SceneManager.GetSceneAt(i); - if (!scene.IsValid() || !scene.isLoaded || scene.name.Contains(NetcodeIntegrationTestHelpers.FirstPartOfTestRunnerSceneName) || !OnCanSceneCleanUpUnload(scene)) + if (scene.name.Contains(NetcodeIntegrationTestHelpers.FirstPartOfTestRunnerSceneName)) + { + testRunnerScene = scene; + continue; + } + if (scene.IsValid() && !scene.isLoaded) + { + // Can't unload a scene that is still loading + sceneStillLoading = true; + continue; + } + if (!scene.IsValid() || !OnCanSceneCleanUpUnload(scene)) { continue; } VerboseDebug($"Unloading scene {scene.name}-{scene.handle}"); var asyncOperation = SceneManager.UnloadSceneAsync(scene); + if (asyncOperation != null) + { + m_PendingSceneUnloads.Add(asyncOperation); + } + } + + // Ensure the test runner scene is reset to be the active scene. + if (testRunnerScene.IsValid()) + { + if (SceneManager.GetActiveScene() != testRunnerScene) + { + SceneManager.SetActiveScene(testRunnerScene); + } + } + + return sceneStillLoading; + } + + /// + /// Waits (in real time) for all scenes left over by the test to finish unloading. + /// Scenes that finish loading after tear down started are also unloaded. + /// + private IEnumerator WaitForRemainingScenesUnloaded() + { + var timeOut = Time.realtimeSinceStartup + k_SceneUnloadTimeout; + while (true) + { + // Pick up any scenes that finished loading after the clean up started + var sceneStillLoading = UnloadRemainingScenes(); + + // Keep waiting while a scene is still loading so it can be unloaded once it finishes loading + if (!sceneStillLoading && m_PendingSceneUnloads.All(c => c.isDone)) + { + break; + } + + if (Time.realtimeSinceStartup >= timeOut) + { + Debug.LogWarning($"[{nameof(WaitForRemainingScenesUnloaded)}] Timed out waiting for scenes to unload!"); + break; + } + yield return null; + } + + m_PendingSceneUnloads.Clear(); } private StringBuilder m_WaitForLog = new StringBuilder(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs index 2bdce8f205..16ae641a6a 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs @@ -132,6 +132,7 @@ public IEnumerator ConnectSingleClient_WebSocket_IPAddressAndPath() #if HOSTNAME_RESOLUTION_AVAILABLE // Check connection with a single client (hostname). [UnityTest] + [UnityPlatform(exclude = new[] { RuntimePlatform.PS4, RuntimePlatform.PS5 })] // Ignored test tracked in MTT-16494 public IEnumerator ConnectSingleClient_Hostname() { InitializeTransport(out m_Server, out m_ServerEvents); diff --git a/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset b/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset index 69bec9b722..f44168c06f 100644 --- a/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset +++ b/testproject/Assets/AddressableAssetsData/AddressableAssetSettings.asset @@ -59,7 +59,7 @@ MonoBehaviour: m_ContentStateBuildPathProfileVariableName: m_CustomContentStateBuildPath: m_ContentStateBuildPath: - m_BuildAddressablesWithPlayerBuild: 2 + m_BuildAddressablesWithPlayerBuild: 1 m_overridePlayerVersion: m_GroupAssets: - {fileID: 11400000, guid: 783a7ba7cfd87084388760e6c08547b4, type: 2} From 6e1f09821ffa443ac03643203bb36965232d1937 Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 19 Oct 2026 10:24:17 -0400 Subject: [PATCH 2/6] Remove CoreCLR stuff --- .yamato/desktop-standalone-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.yamato/desktop-standalone-tests.yml b/.yamato/desktop-standalone-tests.yml index 13fd9508f0..1b104a853f 100644 --- a/.yamato/desktop-standalone-tests.yml +++ b/.yamato/desktop-standalone-tests.yml @@ -43,7 +43,7 @@ desktop_standalone_build_{{ project.name }}_{{ platform.name }}_{{ backend }}_{{ model: {{ platform.model }} # This is set only in platforms where we want non-default model to use (more information in project.metafile) {% endif %} commands: - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %}{% if backend == "coreclr" %}{% unless coreclr_runtime_editors contains editor %} -c {{ platform.coreclr_component }} {% endunless %}{% endif %} --arch {{ platform.architecture }} + - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %} - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --testproject={{ project.path }} --scripting-backend={{ backend }} --testfilter="Unity.Netcode.RuntimeTests.*;TestProject.RuntimeTests.*" --playergraphicsapi=Null --player-save-path=build/players --artifacts-path=artifacts --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} artifacts: players: From acbdebd3d4b0fc6ac336b14ba98f0675b6b7c4be Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Fri, 23 Oct 2026 11:00:06 -0400 Subject: [PATCH 3/6] feat: Improve error message on connection failure [2.X] (#4208) feat: Improve error message on connection failure --- .../Runtime/Transports/UTP/UnityTransport.cs | 36 ++++++++++++++++++- .../Connection/ClientOnlyConnectionTests.cs | 3 +- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index f8ce9d815c..1e23226161 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1144,7 +1144,7 @@ private bool ProcessEvent() // means a clean disconnect that doesn't require logging. if (!m_Driver.Listening && m_ServerClientId == default) { - Debug.LogError("Failed to connect to server."); + LogClientConnectionFailureMessage(); } // Set the disconnect event error code @@ -1172,6 +1172,40 @@ private bool ProcessEvent() return false; } + private void LogClientConnectionFailureMessage() + { + if (OnCurrentTopology() == NetworkTopologyTypes.ClientServer) + { + var reasons = new List { "Server/host is not running." }; + + if (m_ProtocolType == ProtocolType.RelayUnityTransport && !m_UseWebSockets) + { + reasons.Add("Relay port might be blocked on your network. Try using WebSockets."); + if (m_RelayServerData.IsSecure != 0) + { + reasons.Add("DTLS might be blocked on your network. Try using UDP or WebSockets."); + } + } + else if (m_ProtocolType != ProtocolType.RelayUnityTransport) + { + reasons.Add($"Server/host might not be reachable. Try \"ping {ConnectionData.Address}\" in a terminal."); + reasons.Add("The firewall on the server/host might be blocking the connection attempts."); + if (m_UseEncryption && !m_UseWebSockets) + { + reasons.Add("DTLS might be blocked on your network. Try using WebSockets."); + } + } + + const string prefix = "\n\t- "; + Debug.LogError("Failed to connect to server. Possible reasons:" + prefix + string.Join(prefix, reasons)); + } + else + { + // If using DA the SDK should have logged an actual useful error. + Debug.LogError("Failed to connect to server."); + } + } + /// /// Handles accepting new connections and processing transport events. /// diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs index 549f0d8d23..7e0dfb997d 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Text.RegularExpressions; using NUnit.Framework; using Unity.Netcode.TestHelpers.Runtime; using Unity.Netcode.Transports.UTP; @@ -48,7 +49,7 @@ public IEnumerator ClientFailsToConnect() m_ClientNetworkManager.StartClient(); // Unity Transport throws an error when it times out - LogAssert.Expect(LogType.Error, "Failed to connect to server."); + LogAssert.Expect(LogType.Error, new Regex("^Failed to connect to server\\.")); yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_WasDisconnected, m_TimeoutHelper); Assert.False(m_TimeoutHelper.TimedOut, "Timed out waiting for client to timeout waiting to connect!"); From 1ee3514f226307fb2be55e811904ccff413354e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Chrobot?= Date: Sat, 24 Oct 2026 13:14:36 +0200 Subject: [PATCH 4/6] Disabled automatic release preparation Disabled recurring trigger as in our current situation it would be more messy to handle automated release step. I will leave it manual for now --- .yamato/ngo-publish.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.yamato/ngo-publish.yml b/.yamato/ngo-publish.yml index 81f9f57b3b..62fc14a11b 100644 --- a/.yamato/ngo-publish.yml +++ b/.yamato/ngo-publish.yml @@ -1,10 +1,6 @@ ngo_release_preparation: name: "NGO release preparation" agent: { type: Unity::VM, flavor: b1.small, image: package-ci/ubuntu-22.04:v4 } - triggers: - recurring: - - branch: develop-2.0.0 # We make new releases from this branch - frequency: "10 ? * 1" # Runs every Sunday at 10:00 AM commands: - pip install PyGithub - pip install GitPython From d0cb2a35701433802d8918f5161859defce288a0 Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 26 Oct 2026 18:11:34 -0400 Subject: [PATCH 5/6] chore: Ensure the rerun strategy is baked into the built players (#4218) --- .yamato/console-standalone-test.yml | 2 +- .yamato/desktop-standalone-tests.yml | 2 +- .yamato/mobile-standalone-test.yml | 2 +- .yamato/webgl-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.yamato/console-standalone-test.yml b/.yamato/console-standalone-test.yml index 4df4ed8969..3aa654e718 100644 --- a/.yamato/console-standalone-test.yml +++ b/.yamato/console-standalone-test.yml @@ -50,7 +50,7 @@ console_standalone_build_{{ project.name }}_{{ platform.name }}_{{ editor }}: {% endif %} commands: - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor -c il2cpp -c {{ platform.name }} - - UnifiedTestRunner --testproject={{ project.path }} --architecture={% if platform.name == "switch" %}arm64{% else %}x64{% endif %} --scripting-backend=il2cpp --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --artifacts-path=artifacts --player-save-path=build/players --testfilter="Unity.Netcode.RuntimeTests.*" --extra-editor-arg=-batchmode --extra-editor-arg=-nographics{% if platform.name == "switch" %} --extra-editor-arg=-overrideTextureCompression --extra-editor-arg=ForceUncompressed{% endif %} --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout}} + - UnifiedTestRunner --testproject={{ project.path }} --architecture={% if platform.name == "switch" %}arm64{% else %}x64{% endif %} --scripting-backend=il2cpp --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --artifacts-path=artifacts --player-save-path=build/players --testfilter="Unity.Netcode.RuntimeTests.*" --extra-editor-arg=-batchmode --extra-editor-arg=-nographics{% if platform.name == "switch" %} --extra-editor-arg=-overrideTextureCompression --extra-editor-arg=ForceUncompressed{% endif %} --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --build-only --timeout={{ test_timeout}} variables: # PS4 related SCE_ORBIS_SDK_DIR: 'C:\Users\bokken\SCE\ps4_sdk_12_00' diff --git a/.yamato/desktop-standalone-tests.yml b/.yamato/desktop-standalone-tests.yml index 1b104a853f..9c83b2986a 100644 --- a/.yamato/desktop-standalone-tests.yml +++ b/.yamato/desktop-standalone-tests.yml @@ -44,7 +44,7 @@ desktop_standalone_build_{{ project.name }}_{{ platform.name }}_{{ backend }}_{{ {% endif %} commands: - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor {% if backend == "il2cpp" %} -c il2cpp {% endif %} - - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --testproject={{ project.path }} --scripting-backend={{ backend }} --testfilter="Unity.Netcode.RuntimeTests.*;TestProject.RuntimeTests.*" --playergraphicsapi=Null --player-save-path=build/players --artifacts-path=artifacts --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --editor-location=.Editor --testproject={{ project.path }} --scripting-backend={{ backend }} --testfilter="Unity.Netcode.RuntimeTests.*;TestProject.RuntimeTests.*" --playergraphicsapi=Null --player-save-path=build/players --artifacts-path=artifacts --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --build-only --timeout={{ test_timeout }} artifacts: players: paths: diff --git a/.yamato/mobile-standalone-test.yml b/.yamato/mobile-standalone-test.yml index 686cfcb24d..59c8f344cb 100644 --- a/.yamato/mobile-standalone-test.yml +++ b/.yamato/mobile-standalone-test.yml @@ -55,7 +55,7 @@ mobile_standalone_build_{{ project.name }}_{{ platform.name }}_{{ editor }}: UNITY_HANDLEUIINTERRUPTIONS: 1 commands: - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor -c il2cpp {% if platform.base == "mac" %} -c ios {% else %} -c android {% endif %} - - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --testproject={{ project.path }} --architecture={{ platform.architecture }} --scripting-backend=il2cpp --editor-location=.Editor --artifacts-path=artifacts --testfilter="Unity.Netcode.RuntimeTests.*" --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} + - UnifiedTestRunner --suite=playmode --platform={{ platform.standalone }} --testproject={{ project.path }} --architecture={{ platform.architecture }} --scripting-backend=il2cpp --editor-location=.Editor --artifacts-path=artifacts --testfilter="Unity.Netcode.RuntimeTests.*" --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --build-only --timeout={{ test_timeout }} artifacts: players: paths: diff --git a/.yamato/webgl-build.yml b/.yamato/webgl-build.yml index 1f028ce10f..47feed0ce5 100644 --- a/.yamato/webgl-build.yml +++ b/.yamato/webgl-build.yml @@ -45,7 +45,7 @@ webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}: # Engine is initialized in ‘nographics’ mode since we don't need any graphics for this case (--extra-editor-arg=-nographics) # In case of failure the job will be rerunned once (--reruncount=1) with clean library (--clean-library-on-rerun). Note that this is build only step so no tests are being executed # This will perform only building phase (--build-only) with a timeout set by the test_timeout variable in the project metafile. - - UnifiedTestRunner --suite=playmode --platform=WebGL --scripting-backend=il2cpp --testproject={{ project.path }} --editor-location=.Editor --artifacts_path=artifacts --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout={{ test_timeout }} + - UnifiedTestRunner --suite=playmode --platform=WebGL --scripting-backend=il2cpp --testproject={{ project.path }} --editor-location=.Editor --artifacts_path=artifacts --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --build-only --timeout={{ test_timeout }} artifacts: logs: paths: From df51caa7557b8e9fb78276931d2dfc5e175a7c1e Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Mon, 26 Oct 2026 15:13:31 -0500 Subject: [PATCH 6/6] fix: generate canonical bools in NetworkVariable serialization tests (#4198) * test: generate canonical bools in NetworkVariable serialization tests RandGenBytes filled each bool with a random byte, so most values were neither 0 nor 1. On mac arm64 IL2CPP the List and NativeHashMap cases then failed with both sides printing identical all-True contents. RandGenBool returns only false or true. * test: use RandGenBool for the NativeArray case * test: make changed2 always differ from original2 in collection generators With RandGenBool an overwrite keeps the existing value half the time, so when no elements were added or removed, changed2 could equal original2 and the "do not match" assertions failed. Each overwrite now redraws until it differs from the original element. --------- Co-authored-by: Emma (cherry picked from commit b5c186c43abd8a9d8b99f526cfbec36f911e3609) --- .../NetworkVariable/NetworkVariableTests.cs | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs index 9f7b4c7a7b..9fd5a1bc2c 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs @@ -1850,6 +1850,13 @@ public unsafe T RandGenBytes(System.Random rand) where T : unmanaged return t; } + // RandGenBytes yields bools whose byte is neither 0 nor 1, which IL2CPP on ARM64 can + // compare as unequal even though both print True. + public bool RandGenBool(System.Random rand) + { + return rand.Next(2) == 1; + } + public FixedString32Bytes RandGenFixedString32(System.Random rand) { var s = new FixedString32Bytes(); @@ -1917,6 +1924,11 @@ public string ArrayStr(NativeArray arr) where T : unmanaged { var idx = rand.Next(changed2.Length - 1); var item = generator(rand); + // Ensures changed2 differs from original2 when its length matches original2. + while (idx < original2.Length && EqualityComparer.Default.Equals(item, original2[idx])) + { + item = generator(rand); + } changed2[idx] = item; } @@ -1997,7 +2009,7 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeArrayNetworkV } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetArarys((rand) => rand.Next(2) == 1); + (var original, var original2, var changed, var changed2) = GetArarys(RandGenBool); TestValueTypeNativeArray(original, changed); TestValueTypeNativeArray(original2, changed2); } @@ -2215,6 +2227,11 @@ public string DictionaryStr(Dictionary list) { var idx = rand.Next(changed2.Count - 1); var item = generator(rand); + // Ensures changed2 differs from original2 when no elements are added or removed. + while (EqualityComparer.Default.Equals(item, original2[idx])) + { + item = generator(rand); + } changed2[idx] = item; } @@ -2461,7 +2478,7 @@ public void WhenSerializingAndDeserializingVeryLargeListNetworkVariables_ValuesA } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetLists(RandGenBytes); + (var original, var original2, var changed, var changed2) = GetLists(RandGenBool); TestList(original, changed); TestList(original2, changed2); } @@ -2657,7 +2674,7 @@ public void WhenSerializingAndDeserializingVeryLargeHashSetNetworkVariables_Valu } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBytes); + (var original, var original2, var changed, var changed2) = GetHashSets(RandGenBool); TestHashSet(original, changed); TestHashSet(original2, changed2); } @@ -3010,27 +3027,27 @@ public void WhenSerializingAndDeserializingVeryLargeDictionaryNetworkVariables_V { if (keyType == typeof(byte)) { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBool); TestDictionary(original, changed); TestDictionary(original2, changed2); } else if (keyType == typeof(ulong)) { - (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetDictionaries(RandGenBytes, RandGenBool); TestDictionary(original, changed); TestDictionary(original2, changed2); } else if (keyType == typeof(Vector2)) { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); + (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBool); TestDictionary(original, changed); TestDictionary(original2, changed2); } else if (keyType == typeof(HashMapKeyClass)) { - (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetDictionaries((rand) => new HashMapKeyClass { Data = RandGenBytes(rand) }, RandGenBool); TestDictionary(original, changed); TestDictionary(original2, changed2); } @@ -3722,6 +3739,11 @@ public string NativeHashMapStr(NativeHashMap list) { var idx = rand.Next(changed2.Length - 1); var item = generator(rand); + // Ensures changed2 differs from original2 when no elements are added or removed. + while (EqualityComparer.Default.Equals(item, original2[idx])) + { + item = generator(rand); + } changed2[idx] = item; } @@ -3965,7 +3987,7 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeListNetworkVa } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBytes); + (var original, var original2, var changed, var changed2) = GetNativeLists(RandGenBool); TestValueTypeNativeList(original, changed); TestValueTypeNativeList(original2, changed2); } @@ -4154,7 +4176,7 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashSetNetwor } else if (testType == typeof(bool)) { - (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBytes); + (var original, var original2, var changed, var changed2) = GetNativeHashSets(RandGenBool); TestValueTypeNativeHashSet(original, changed); TestValueTypeNativeHashSet(original2, changed2); } @@ -4500,27 +4522,27 @@ public void WhenSerializingAndDeserializingVeryLargeValueTypeNativeHashMapNetwor { if (keyType == typeof(byte)) { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBool); TestValueTypeNativeHashMap(original, changed); TestValueTypeNativeHashMap(original2, changed2); } else if (keyType == typeof(ulong)) { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBool); TestValueTypeNativeHashMap(original, changed); TestValueTypeNativeHashMap(original2, changed2); } else if (keyType == typeof(Vector2)) { - (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBytes); + (var original, var original2, var changed, var changed2) = GetMaps((rand) => new Vector2((float)rand.NextDouble(), (float)rand.NextDouble()), RandGenBool); TestValueTypeNativeHashMap(original, changed); TestValueTypeNativeHashMap(original2, changed2); } else if (keyType == typeof(HashMapKeyStruct)) { - (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBytes); + (var original, var original2, var changed, var changed2) = GetMaps(RandGenBytes, RandGenBool); TestValueTypeNativeHashMap(original, changed); TestValueTypeNativeHashMap(original2, changed2); }