diff --git a/.yamato/wrench/recipe-regeneration.yml b/.yamato/wrench/recipe-regeneration.yml index d3b33987c7..5f3a545a0b 100644 --- a/.yamato/wrench/recipe-regeneration.yml +++ b/.yamato/wrench/recipe-regeneration.yml @@ -9,14 +9,14 @@ test_-_wrench_jobs_up_to_date: type: Unity::VM flavor: b1.large commands: - - command: dotnet run --project Tools\CI\NGO.Cookbook.csproj + - command: dotnet run --project Tools/CI/NGO.Cookbook.csproj - command: |- if [ -n "$(git status --porcelain -- .yamato/wrench)" ]; then git status echo "Your repo is not clean - diff output:" git diff echo "You must run recipe generation after updating recipes to update the generated YAML!" - echo "Run 'dotnet run --project Tools\CI\NGO.Cookbook.csproj' from the root of your repository to regenerate all job definitions created by wrench." + echo "Run 'dotnet run --project Tools/CI/NGO.Cookbook.csproj' from the root of your repository to regenerate all job definitions created by wrench." exit 1 fi variables: diff --git a/.yamato/wrench/validation-jobs.yml b/.yamato/wrench/validation-jobs.yml index a01530421d..1ddd5c8a43 100644 --- a/.yamato/wrench/validation-jobs.yml +++ b/.yamato/wrench/validation-jobs.yml @@ -21,7 +21,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -30,7 +30,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -87,7 +87,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -96,7 +96,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -153,7 +153,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -162,7 +162,7 @@ validate_-_netcode_gameobjects_-_2021_3_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd @@ -219,7 +219,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -228,7 +228,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -285,7 +285,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -294,7 +294,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -351,7 +351,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -360,7 +360,7 @@ validate_-_netcode_gameobjects_-_2022_3_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd @@ -417,7 +417,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -426,7 +426,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -483,7 +483,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -492,7 +492,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -549,7 +549,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -558,7 +558,7 @@ validate_-_netcode_gameobjects_-_6000_0_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd @@ -615,7 +615,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -624,7 +624,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -681,7 +681,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -690,7 +690,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -747,7 +747,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -756,7 +756,7 @@ validate_-_netcode_gameobjects_-_6000_1_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd @@ -813,7 +813,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -822,7 +822,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -879,7 +879,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -888,7 +888,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -945,7 +945,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -954,7 +954,7 @@ validate_-_netcode_gameobjects_-_6000_2_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd @@ -1011,7 +1011,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_macos: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -1020,7 +1020,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_macos: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-mac.sh @@ -1077,7 +1077,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_ubuntu: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -1086,7 +1086,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_ubuntu: timeout: 10 retries: 0 - command: 'UnifiedTestRunner --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: bash .yamato/generated-scripts/infrastructure-instability-detection-linux.sh @@ -1143,7 +1143,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_windows: retries: 1 - command: echo No internal packages to add. - command: upm-pvp test --unity .Editor --packages "upm-ci~/packages/*.tgz" --results upm-ci~/pvp - timeout: 40 + timeout: 180 retries: 0 - command: upm-pvp require "pkgprom-promote -PVP-29-2 rme" --results upm-ci~/pvp --exemptions upm-ci~/pvp/failures.json timeout: 5 @@ -1152,7 +1152,7 @@ validate_-_netcode_gameobjects_-_6000_3_-_windows: timeout: 10 retries: 0 - command: 'UnifiedTestRunner.exe --testproject=testproject --editor-location=.Editor --clean-library --reruncount=1 --clean-library-on-rerun --artifacts-path=artifacts --suite=Editor --suite=Playmode "--ff={ops.upmpvpevidence.enable=true}" ' - timeout: 40 + timeout: 180 retries: 1 after: - command: .yamato\generated-scripts\infrastructure-instability-detection-win.cmd diff --git a/.yamato/wrench/wrench_config.json b/.yamato/wrench/wrench_config.json index eb96a94c64..8e170db3e2 100644 --- a/.yamato/wrench/wrench_config.json +++ b/.yamato/wrench/wrench_config.json @@ -33,5 +33,5 @@ "branch_pattern": "ReleaseSlash", "wrench_version": "0.12.2.0", "pvp_exemption_path": ".yamato/wrench/pvp-exemptions.json", - "cs_project_path": "Tools\\CI\\NGO.Cookbook.csproj" + "cs_project_path": "Tools/CI/NGO.Cookbook.csproj" } \ No newline at end of file diff --git a/Tools/CI/Settings/NGOSettings.cs b/Tools/CI/Settings/NGOSettings.cs index a174da52e2..fc4aa2663d 100644 --- a/Tools/CI/Settings/NGOSettings.cs +++ b/Tools/CI/Settings/NGOSettings.cs @@ -12,7 +12,7 @@ public class NGOSettings : AnnotatedSettingsBase static ValidationOptions validationOptions = new ValidationOptions() { ProjectPath = "testproject", - UtrTestingYamatoTimeout = 40 + UtrTestingYamatoTimeout = 180 // 3h This it to address the issue that we are running both package and project test and that their execution is much slower on editors below 6000 }; // update this to list all packages in this repo that you want to release. diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index e62a0101bb..7fdab72391 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -10,12 +10,15 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +### Added + ### Fixed - Fixed issue where NetworkConfig.ConnectionData could cause the ConnectionRequestMessage to exceed the transport's MTU size and would result in a buffer overflow error. (#3565) ### Changed + ## [1.14.0] - 2025-07-21 ### Added diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Messaging/MessageCorruptionTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Messaging/MessageCorruptionTests.cs index b37454f233..0feb759c4a 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Messaging/MessageCorruptionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Messaging/MessageCorruptionTests.cs @@ -95,7 +95,8 @@ public unsafe void Send(ulong clientId, NetworkDelivery delivery, FastBufferWrit for (int i = 0; i < 4; i++) { var currentByte = batchData.GetUnsafePtr()[i]; - batchData.WriteByteSafe((byte)(currentByte == 0 ? 1 : 0)); + currentByte = (byte)((currentByte + 1) % 255); + batchData.WriteByteSafe(currentByte); MessageQueue.Add(batchData.ToArray()); } break; diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApprovalTimeoutTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApprovalTimeoutTests.cs index 9ccccfc11a..14b4b033f0 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApprovalTimeoutTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApprovalTimeoutTests.cs @@ -55,12 +55,19 @@ protected override void OnServerAndClientsCreated() base.OnServerAndClientsCreated(); } + private MessageCatcher m_ConnectionRequestCatcher; + private MessageCatcher m_ConnectionApprovedCatcher; protected override IEnumerator OnStartedServerAndClients() { + m_ClientStopped = false; + m_ServerStopped = false; + m_ClientNetworkManagers[0].OnClientStopped += OnClientStopped; + m_ServerNetworkManager.OnServerStopped += OnServerStopped; if (m_ApprovalFailureType == ApprovalTimedOutTypes.ServerDoesNotRespond) { // We catch (don't process) the incoming approval message to simulate the server not sending the approved message in time - m_ClientNetworkManagers[0].ConnectionManager.MessageManager.Hook(new MessageCatcher(m_ClientNetworkManagers[0])); + m_ConnectionApprovedCatcher = new MessageCatcher(m_ClientNetworkManagers[0], m_EnableVerboseDebug); + m_ClientNetworkManagers[0].ConnectionManager.MessageManager.Hook(m_ConnectionApprovedCatcher); m_ExpectedLogMessage = new Regex("Timed out waiting for the server to approve the connection request."); m_LogType = LogType.Log; } @@ -68,7 +75,8 @@ protected override IEnumerator OnStartedServerAndClients() { // We catch (don't process) the incoming connection request message to simulate a transport connection but the client never // sends (or takes too long to send) the connection request. - m_ServerNetworkManager.ConnectionManager.MessageManager.Hook(new MessageCatcher(m_ServerNetworkManager)); + m_ConnectionRequestCatcher = new MessageCatcher(m_ServerNetworkManager, m_EnableVerboseDebug); + m_ServerNetworkManager.ConnectionManager.MessageManager.Hook(m_ConnectionRequestCatcher); // For this test, we know the timed out client will be Client-1 m_ExpectedLogMessage = new Regex("Server detected a transport connection from Client-1, but timed out waiting for the connection request message."); @@ -98,6 +106,43 @@ public IEnumerator ValidateApprovalTimeout() Assert.AreEqual(0, m_ServerNetworkManager.ConnectionManager.PendingClients.Count, $"Expected no pending clients when there were {m_ServerNetworkManager.ConnectionManager.PendingClients.Count} pending clients!"); Assert.True(!m_ClientNetworkManagers[0].LocalClient.IsApproved, $"Expected the client to not have been approved, but it was!"); + + if (m_ApprovalFailureType == ApprovalTimedOutTypes.ServerDoesNotRespond) + { + m_ConnectionApprovedCatcher.ClearMessages(); + } + else + { + m_ConnectionRequestCatcher.ClearMessages(); + } + + if (!m_ClientStopped) + { + m_ClientNetworkManagers[0].Shutdown(); + } + + if (!m_ServerStopped) + { + m_ServerNetworkManager.Shutdown(); + } + + yield return WaitForConditionOrTimeOut(() => m_ClientStopped && m_ServerStopped); + AssertOnTimeout($"Timed out waiting for the client or server to stop!"); + } + + private bool m_ClientStopped; + private void OnClientStopped(bool obj) + { + m_ClientNetworkManagers[0].OnClientStopped -= OnClientStopped; + m_ClientStopped = true; } + + private bool m_ServerStopped; + private void OnServerStopped(bool obj) + { + m_ServerNetworkManager.OnServerStopped -= OnServerStopped; + m_ServerStopped = true; + } + } } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/MessageCatcher.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/MessageCatcher.cs index f408532871..3b57154d47 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/MessageCatcher.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/MessageCatcher.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Unity.Collections; +using UnityEngine; namespace Unity.Netcode.RuntimeTests { @@ -8,7 +9,9 @@ internal class MessageCatcher : INetworkHooks where TMessageType : { private NetworkManager m_OwnerNetworkManager; - public MessageCatcher(NetworkManager ownerNetworkManager) + private bool m_VerboseDebug; + + public MessageCatcher(NetworkManager ownerNetworkManager, bool verboseDebug = false) { m_OwnerNetworkManager = ownerNetworkManager; } @@ -23,9 +26,38 @@ private struct TriggerData } private readonly List m_CaughtMessages = new List(); - public void ReleaseMessages() + + private void Log(string message) { + if (!m_VerboseDebug) + { + return; + } + Debug.Log($"[Client-{m_OwnerNetworkManager.LocalClientId}] {message}"); + } + + internal void ClearMessages() + { + if (m_CaughtMessages.Count == 0) + { + return; + } + Log($"Clearing messages."); + foreach (var caughtSpawn in m_CaughtMessages) + { + if (caughtSpawn.Reader.IsInitialized) + { + Log($"Disposing reader (size: {caughtSpawn.Reader.Length})."); + caughtSpawn.Reader.Dispose(); + } + } + + m_CaughtMessages.Clear(); + } + + public void ReleaseMessages() + { foreach (var caughtSpawn in m_CaughtMessages) { // Reader will be disposed within HandleMessage diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs index c33f268b2a..6736d6a017 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs @@ -43,6 +43,7 @@ public IEnumerator Cleanup() // Need to destroy the GameObject (all assigned components will get destroyed too) UnityEngine.Object.DestroyImmediate(m_Server.gameObject); + m_Server = null; } if (m_Client1) @@ -51,6 +52,7 @@ public IEnumerator Cleanup() // Need to destroy the GameObject (all assigned components will get destroyed too) UnityEngine.Object.DestroyImmediate(m_Client1.gameObject); + m_Client1 = null; } if (m_Client2) @@ -59,6 +61,7 @@ public IEnumerator Cleanup() // Need to destroy the GameObject (all assigned components will get destroyed too) UnityEngine.Object.DestroyImmediate(m_Client2.gameObject); + m_Client2 = null; } m_ServerEvents?.Clear(); @@ -315,7 +318,7 @@ public IEnumerator DisconnectOnReliableSendQueueOverflow() m_Server.StartServer(); m_Client1.StartClient(); - yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events); + yield return WaitForNetworkEvent(NetworkEvent.Connect, m_Client1Events, 5.0f); m_Server.Shutdown(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/UniversalRpcTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/UniversalRpcTests.cs index 69674c20d9..09fb9cbff4 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/UniversalRpcTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/UniversalRpcTests.cs @@ -475,6 +475,7 @@ protected override NetworkManagerInstatiationMode OnSetIntegrationTestMode() protected override bool m_TearDownIsACoroutine => false; protected GameObject m_ServerObject; + internal NetworkObject ServerNetworkObject; protected override void OnCreatePlayerPrefab() { @@ -483,16 +484,9 @@ protected override void OnCreatePlayerPrefab() protected override void OnServerAndClientsCreated() { - m_ServerObject = new GameObject { name = "Server Object" }; - var networkObject = m_ServerObject.AddComponent(); + m_ServerObject = CreateNetworkObjectPrefab("Server Object"); + ServerNetworkObject = m_ServerObject.GetComponent(); m_ServerObject.AddComponent(); - networkObject.NetworkManagerOwner = m_ServerNetworkManager; - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject); - m_ServerNetworkManager.AddNetworkPrefab(m_ServerObject); - foreach (var client in m_ClientNetworkManagers) - { - client.AddNetworkPrefab(m_ServerObject); - } } protected override void OnInlineTearDown() @@ -539,9 +533,31 @@ protected UniversalRpcNetworkBehaviour GetPlayerObject(ulong ownerClientId, ulon return m_PlayerNetworkObjects[onClient][ownerClientId].GetComponent(); } + internal UniversalRpcNetworkBehaviour InternalGetPlayerObject(ulong ownerClientId, ulong senderClientId) + { + var networkObjectId = 0UL; + + var senderNetworkManager = senderClientId == NetworkManager.ServerClientId ? m_ServerNetworkManager : + m_ClientNetworkManagers.Where((c) => c.LocalClientId == senderClientId).First(); + var ownerNetworkManager = ownerClientId == NetworkManager.ServerClientId ? m_ServerNetworkManager : + m_ClientNetworkManagers.Where((c) => c.LocalClientId == ownerClientId).First(); + + if (ownerClientId == NetworkManager.ServerClientId && !m_ServerNetworkManager.IsHost) + { + networkObjectId = ServerNetworkObject.NetworkObjectId; + } + else + { + networkObjectId = ownerNetworkManager.LocalClient.PlayerObject.NetworkObjectId; + } + + return senderNetworkManager.SpawnManager.SpawnedObjects[networkObjectId].GetComponent(); + } + + #region VERIFY METHODS protected void VerifyLocalReceived(ulong objectOwner, ulong sender, string name, bool verifyReceivedFrom, int expectedReceived = 1) { - var obj = GetPlayerObject(objectOwner, sender); + var obj = InternalGetPlayerObject(objectOwner, sender); Assert.AreEqual(name, obj.Received); Assert.That(obj.ReceivedCount, Is.EqualTo(expectedReceived)); Assert.IsNull(obj.ReceivedParams); @@ -553,7 +569,7 @@ protected void VerifyLocalReceived(ulong objectOwner, ulong sender, string name, protected void VerifyLocalReceivedWithParams(ulong objectOwner, ulong sender, string name, int i, bool b, float f, string s) { - var obj = GetPlayerObject(objectOwner, sender); + var obj = InternalGetPlayerObject(objectOwner, sender); Assert.AreEqual(name, obj.Received); Assert.That(obj.ReceivedCount, Is.EqualTo(1)); Assert.IsNotNull(obj.ReceivedParams); @@ -567,7 +583,7 @@ protected void VerifyNotReceived(ulong objectOwner, ulong[] receivedBy) { foreach (var client in receivedBy) { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); + UniversalRpcNetworkBehaviour playerObject = InternalGetPlayerObject(objectOwner, client); Assert.AreEqual(string.Empty, playerObject.Received); Assert.That(playerObject.ReceivedCount, Is.EqualTo(0)); Assert.IsNull(playerObject.ReceivedParams); @@ -640,7 +656,7 @@ protected void VerifyRemoteReceived(ulong objectOwner, ulong sender, string mess foreach (var client in receivedBy) { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); + UniversalRpcNetworkBehaviour playerObject = InternalGetPlayerObject(objectOwner, client); Assert.AreEqual(message, playerObject.Received); Assert.That(playerObject.ReceivedCount, Is.EqualTo(expectedReceived)); Assert.IsNull(playerObject.ReceivedParams); @@ -714,7 +730,7 @@ protected void VerifyRemoteReceivedWithParams(ulong objectOwner, ulong sender, s foreach (var client in receivedBy) { - UniversalRpcNetworkBehaviour playerObject = GetPlayerObject(objectOwner, client); + UniversalRpcNetworkBehaviour playerObject = InternalGetPlayerObject(objectOwner, client); Assert.AreEqual(message, playerObject.Received); Assert.That(playerObject.ReceivedCount, Is.EqualTo(1)); @@ -904,6 +920,7 @@ public void VerifySentToNotMeWithParams(ulong objectOwner, ulong sender, string { VerifySentToNotIdWithParams(objectOwner, sender, sender, methodName, i, b, f, s); } + #endregion public void RethrowTargetInvocationException(Action action) { @@ -918,6 +935,506 @@ public void RethrowTargetInvocationException(Action action) } } + [Timeout(2400000)] // Extended time out + [TestFixture(HostOrServer.Host)] + [TestFixture(HostOrServer.Server)] + internal class UniversalRpcGroupedTests : UniversalRpcTestsBase + { + public enum TestTypes + { + DisallowedOverride, + SenderClientId, + SendingNoOverride, + SendingNoOverrideWithParams, + SendingNoOverrideWithParamsAndRpcParams, + SendingWithTargetOverride, + TestRequireOwnership, + } + + public enum TestTypesC + { + SendingWithGroupNotOverride, + SendingWithGroupOverride, + } + + private enum TestTables + { + ActionTableA, + ActionTableB, + ActionTableC + } + + private Dictionary> m_TestTypeToActionTableA = new Dictionary>(); + private Dictionary> m_TestTypeToActionTableB = new Dictionary>(); + private Dictionary> m_TestTypeToActionTableC = new Dictionary>(); + + private delegate IEnumerator TestTypeHandler(TestTypes testType); + private Dictionary m_TestTypesToTableTypes = new Dictionary(); + private Dictionary> m_TableTypesToTestStartAction = new Dictionary>(); + + + private Dictionary m_TypeToRecipientGroupsTable = new Dictionary(); + + public UniversalRpcGroupedTests(HostOrServer hostOrServer) : base(hostOrServer) + { + InitTestTypeToActionTable(); + } + + private void AddTestTypeA(TestTypes testType, Action action) + { + m_TestTypesToTableTypes.Add(testType, TestTables.ActionTableA); + m_TestTypeToActionTableA.Add(testType, action); + } + + private void AddTestTypeB(TestTypes testType, Action action) + { + m_TestTypesToTableTypes.Add(testType, TestTables.ActionTableB); + m_TestTypeToActionTableB.Add(testType, action); + } + + private void AddTestTypeC(TestTypesC testType, Action action) + { + m_TestTypeToActionTableC.Add(testType, action); + } + + private void InitTestTypeToActionTable() + { + // Create a look up table to know what kind of test table action will be invoked + m_TableTypesToTestStartAction.Add(TestTables.ActionTableA, RunTestTypeA); + m_TableTypesToTestStartAction.Add(TestTables.ActionTableB, RunTestTypeB); + + // Type A action registrations + AddTestTypeA(TestTypes.DisallowedOverride, DisallowedOverride); + AddTestTypeA(TestTypes.SenderClientId, SenderClientId); + AddTestTypeA(TestTypes.SendingNoOverride, SendingNoOverride); + AddTestTypeA(TestTypes.SendingNoOverrideWithParams, SendingNoOverrideWithParams); + AddTestTypeA(TestTypes.SendingNoOverrideWithParamsAndRpcParams, SendingNoOverrideWithParamsAndRpcParams); + AddTestTypeA(TestTypes.TestRequireOwnership, TestRequireOwnership); + + // Type B action registrations + AddTestTypeB(TestTypes.SendingWithTargetOverride, SendingWithTargetOverride); + + // Type C action registrations + AddTestTypeC(TestTypesC.SendingWithGroupOverride, SendingWithGroupOverride); + m_TypeToRecipientGroupsTable.Add(TestTypesC.SendingWithGroupOverride, RecipientGroupsA); + AddTestTypeC(TestTypesC.SendingWithGroupNotOverride, SendingWithGroupNotOverride); + m_TypeToRecipientGroupsTable.Add(TestTypesC.SendingWithGroupNotOverride, RecipientGroupsB); + } + + private Action GetTestTypeActionA(TestTypes testType) + { + if (m_TestTypeToActionTableA.ContainsKey(testType)) + { + return m_TestTypeToActionTableA[testType]; + } + return MockSendA; + } + + private Action GetTestTypeActionB(TestTypes testType) + { + if (m_TestTypeToActionTableB.ContainsKey(testType)) + { + return m_TestTypeToActionTableB[testType]; + } + return MockSendB; + } + + private Action GetTestTypeActionC(TestTypesC testType) + { + if (m_TestTypeToActionTableC.ContainsKey(testType)) + { + return m_TestTypeToActionTableC[testType]; + } + return MockSendC; + } + + [UnityTest] + public IEnumerator RunGroupTestTypes([Values] TestTypes testType) + { + var testTypeToRun = m_TestTypesToTableTypes[testType]; + m_TableTypesToTestStartAction[testTypeToRun].Invoke(testType); + // Provide a small break to test runner in-between each test type + // since they are running all iterations of the legacy test type's + // values. + yield return s_DefaultWaitForTick; + } + + [Timeout(900000)] + [UnityTest] + public IEnumerator RunGroupWithGroupOverridesTestTypes([Values] TestTypesC testType, [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost)] SendTo sendTo) + { + RunTestTypeC(testType, sendTo); + + // Provide a small break to test runner in-between each test type + // since they are running all iterations of the legacy test type's + // values. + yield return s_DefaultWaitForTick; + } + + #region TYPE-A Tests + + private void RunTestTypeA(TestTypes testType) + { + var sendToValues = new List() { SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost }; + var numberOfClientsULong = (ulong)NumberOfClients; + var actionToInvoke = GetTestTypeActionA(testType); + try + { + foreach (var sendTo in sendToValues) + { + UnityEngine.Debug.Log($"[{testType}][{sendTo}]"); + for (ulong objectOwner = 0; objectOwner <= numberOfClientsULong; objectOwner++) + { + for (ulong sender = 0; sender <= numberOfClientsULong; sender++) + { + actionToInvoke.Invoke(sendTo, objectOwner, sender); + Clear(); + MockTransport.ClearQueues(); + } + } + } + } + catch (Exception ex) + { + Assert.Fail($"Threw Exception:{ex.Message}!\n{ex.StackTrace}"); + } + } + + /// + /// Invoked if a does not have an action yet for this action. + /// + private void MockSendA(SendTo sendTo, ulong objectOwner, ulong sender) + { + } + private void SenderClientId(SendTo sendTo, ulong objectOwner, ulong sender) + { + var sendMethodName = $"DefaultTo{sendTo}WithRpcParamsRpc"; + var verifyMethodName = $"VerifySentTo{sendTo}WithReceivedFrom"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { new RpcParams() }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); + } + + private void DisallowedOverride(SendTo sendTo, ulong objectOwner, ulong sender) + { + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var methodName = $"DefaultTo{sendTo}WithRpcParamsRpc"; + var method = senderObject.GetType().GetMethod(methodName); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Everyone }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Owner }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.NotOwner }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Server }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.NotServer }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.ClientsAndHost }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Me }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.NotMe }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Single(0, RpcTargetUse.Temp) }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Not(0, RpcTargetUse.Temp) }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Group(new[] { 0ul, 1ul, 2ul }, RpcTargetUse.Temp) }))); + Assert.Throws(() => RethrowTargetInvocationException(() => method.Invoke(senderObject, new object[] { (RpcParams)senderObject.RpcTarget.Not(new[] { 0ul, 1ul, 2ul }, RpcTargetUse.Temp) }))); + } + + private void SendingNoOverride(SendTo sendTo, ulong objectOwner, ulong sender) + { + var sendMethodName = $"DefaultTo{sendTo}Rpc"; + var verifyMethodName = $"VerifySentTo{sendTo}"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); + } + + private void SendingNoOverrideWithParams(SendTo sendTo, ulong objectOwner, ulong sender) + { + var rand = new Random(); + var i = rand.Next(); + var f = (float)rand.NextDouble(); + var b = rand.Next() % 2 == 1; + var s = ""; + var numChars = rand.Next() % 5 + 5; + const string chars = "abcdefghijklmnopqrstuvwxycABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-=_+[]{}\\|;':\",./<>?"; + for (var j = 0; j < numChars; ++j) + { + s += chars[rand.Next(chars.Length)]; + } + + var sendMethodName = $"DefaultTo{sendTo}WithParamsRpc"; + var verifyMethodName = $"VerifySentTo{sendTo}WithParams"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { i, b, f, s }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName, i, b, f, s }); + } + + private void SendingNoOverrideWithParamsAndRpcParams(SendTo sendTo, ulong objectOwner, ulong sender) + { + var rand = new Random(); + var i = rand.Next(); + var f = (float)rand.NextDouble(); + var b = rand.Next() % 2 == 1; + var s = ""; + var numChars = rand.Next() % 5 + 5; + const string chars = "abcdefghijklmnopqrstuvwxycABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-=_+[]{}\\|;':\",./<>?"; + for (var j = 0; j < numChars; ++j) + { + s += chars[rand.Next(chars.Length)]; + } + + var sendMethodName = $"DefaultTo{sendTo}WithParamsAndRpcParamsRpc"; + var verifyMethodName = $"VerifySentTo{sendTo}WithParams"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { i, b, f, s, new RpcParams() }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName, i, b, f, s }); + } + + private void TestRequireOwnership(SendTo sendTo, ulong objectOwner, ulong sender) + { + var sendMethodName = $"DefaultTo{sendTo}RequireOwnershipRpc"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + if (sender != objectOwner) + { + Assert.Throws(() => RethrowTargetInvocationException(() => sendMethod.Invoke(senderObject, new object[] { }))); + } + else + { + var verifyMethodName = $"VerifySentTo{sendTo}"; + sendMethod.Invoke(senderObject, new object[] { }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); + } + } + #endregion + + #region TYPE-B Tests + private void RunTestTypeB(TestTypes testType) + { + var sendToValues = new List() { SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost }; + var numberOfClientsULong = (ulong)NumberOfClients; + var actionToInvoke = GetTestTypeActionB(testType); + try + { + foreach (var defaultSendTo in sendToValues) + { + UnityEngine.Debug.Log($"[{testType}][{defaultSendTo}]"); + foreach (var overrideSendTo in sendToValues) + { + for (ulong objectOwner = 0; objectOwner <= numberOfClientsULong; objectOwner++) + { + for (ulong sender = 0; sender <= numberOfClientsULong; sender++) + { + actionToInvoke.Invoke(defaultSendTo, overrideSendTo, objectOwner, sender); + Clear(); + MockTransport.ClearQueues(); + } + } + } + } + } + catch (Exception ex) + { + Assert.Fail($"Threw Exception:{ex.Message}!\n{ex.StackTrace}"); + } + } + + /// + /// Invoked if a does not have an action yet for this action. + /// + private void MockSendB(SendTo defaultSendTo, SendTo overrideSendTo, ulong objectOwner, ulong sender) + { + } + private void SendingWithTargetOverride(SendTo defaultSendTo, SendTo overrideSendTo, ulong objectOwner, ulong sender) + { + var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; + var targetField = typeof(RpcTarget).GetField(overrideSendTo.ToString()); + var verifyMethodName = $"VerifySentTo{overrideSendTo}"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var target = (BaseRpcTarget)targetField.GetValue(senderObject.RpcTarget); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); + + var verifyMethod = GetType().GetMethod(verifyMethodName); + verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); + } + #endregion + + #region TYPE-C Tests + public static ulong[][] RecipientGroupsA = new[]{ + new[] { 0ul }, + new[] { 1ul }, + new[] { 0ul, 1ul }, + new[] { 0ul, 1ul, 2ul } + }; + + public static ulong[][] RecipientGroupsB = new[] +{ + new ulong[] {}, + new[] { 0ul }, + new[] { 1ul }, + new[] { 0ul, 1ul }, + }; + + public enum AllocationType + { + Array, + NativeArray, + NativeList, + List + } + + private void RunTestTypeC(TestTypesC testType, SendTo defaultSendTo) + { + var allocationTypes = new List() { AllocationType.Array, AllocationType.NativeArray, AllocationType.NativeList, AllocationType.List }; + var numberOfClientsULong = (ulong)NumberOfClients; + var actionToInvoke = GetTestTypeActionC(testType); + var recipientGroups = m_TypeToRecipientGroupsTable[testType]; + foreach (var sendGroup in recipientGroups) + { + try + { + for (ulong objectOwner = 0; objectOwner <= numberOfClientsULong; objectOwner++) + { + for (ulong sender = 0; sender <= numberOfClientsULong; sender++) + { + foreach (var allocationType in allocationTypes) + { + actionToInvoke.Invoke(defaultSendTo, sendGroup, objectOwner, sender, allocationType); + TimeTravel(s_DefaultWaitForTick.waitTime, 4); + Clear(); + MockTransport.ClearQueues(); + } + } + } + } + catch (Exception ex) + { + Assert.Fail($"Threw Exception:{ex.Message}!\n{ex.StackTrace}"); + } + } + } + + private void MockSendC(SendTo defaultSendTo, ulong[] recipient, ulong objectOwner, ulong sender, AllocationType allocationType) + { + } + + private void SendingWithGroupOverride(SendTo defaultSendTo, ulong[] recipient, ulong objectOwner, ulong sender, AllocationType allocationType) + { + var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + BaseRpcTarget target = null; + switch (allocationType) + { + case AllocationType.Array: + target = senderObject.RpcTarget.Group(recipient, RpcTargetUse.Temp); + break; + case AllocationType.List: + target = senderObject.RpcTarget.Group(recipient.ToList(), RpcTargetUse.Temp); + break; + case AllocationType.NativeArray: + var arr = new NativeArray(recipient, Allocator.Temp); + target = senderObject.RpcTarget.Group(arr, RpcTargetUse.Temp); + arr.Dispose(); + break; + case AllocationType.NativeList: + // For some reason on 2020.3, calling list.AsArray() and passing that to the next function + // causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later + // versions of Unity. + var list = new NativeList(recipient.Length, Allocator.TempJob); + foreach (var id in recipient) + { + list.Add(id); + } + target = senderObject.RpcTarget.Group(list, RpcTargetUse.Temp); + list.Dispose(); + break; + } + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); + + VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient.Contains(c)).ToArray(), false); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray()); + + // Pass some time to make sure that no other client ever receives this + TimeTravel(1f, 30); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray()); + } + + private void SendingWithGroupNotOverride(SendTo defaultSendTo, ulong[] recipient, ulong objectOwner, ulong sender, AllocationType allocationType) + { + var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; + + var senderObject = InternalGetPlayerObject(objectOwner, sender); + BaseRpcTarget target = null; + switch (allocationType) + { + case AllocationType.Array: + target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp); + break; + case AllocationType.List: + target = senderObject.RpcTarget.Not(recipient.ToList(), RpcTargetUse.Temp); + break; + case AllocationType.NativeArray: + var arr = new NativeArray(recipient, Allocator.Temp); + target = senderObject.RpcTarget.Not(arr, RpcTargetUse.Temp); + arr.Dispose(); + break; + case AllocationType.NativeList: + // For some reason on 2020.3, calling list.AsArray() and passing that to the next function + // causes Allocator.Temp allocations to become invalid somehow. This is not an issue on later + // versions of Unity. + var list = new NativeList(recipient.Length, Allocator.TempJob); + foreach (var id in recipient) + { + list.Add(id); + } + target = senderObject.RpcTarget.Not(list, RpcTargetUse.Temp); + list.Dispose(); + break; + } + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); + + VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => !recipient.Contains(c)).ToArray(), false); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray()); + + // Pass some time to make sure that no other client ever receives this + TimeTravel(1f, 30); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray()); + } + #endregion + + } + +#if USE_LEGACY_UNIVERSALRPC_TESTS + [Timeout(1200000)] // Tracked in MTT-11359 + [TestFixture(HostOrServer.Host)] + [TestFixture(HostOrServer.Server)] + internal class UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner : UniversalRpcTestsBase + { + public UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner(HostOrServer hostOrServer) : base(hostOrServer) + { + + } + } + [Timeout(1200000)] // Tracked in MTT-11359 [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] @@ -929,24 +1446,44 @@ public UniversalRpcTestSendingNoOverride(HostOrServer hostOrServer) : base(hostO } [Test] - public void TestSendingNoOverride( - // Excludes SendTo.SpecifiedInParams - [Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost)] SendTo sendTo, - [Values(0u, 1u, 2u)] ulong objectOwner, - [Values(0u, 1u, 2u)] ulong sender - ) + public void TestSendingNoOverride() + { + var sendToValues = new List() { SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost }; + var numberOfClientsULong = (ulong)NumberOfClients; + var progressLog = new StringBuilder(); + try + { + foreach (var sendTo in sendToValues) + { + for (ulong objectOwner = 0; objectOwner <= numberOfClientsULong; objectOwner++) + { + for (ulong sender = 0; sender <= numberOfClientsULong; sender++) + { + progressLog.AppendLine($"[SendTo: {sendTo}][Owner: {objectOwner}][Sender:{sender}]"); + InternalTestSendingNoOverride(sendTo, objectOwner, sender); + Clear(); + } + } + } + } + catch(Exception ex) + { + Assert.Fail($"Threw Exception:{ex.Message}!\n{progressLog.ToString()}"); + } + } + + private void InternalTestSendingNoOverride(SendTo sendTo, ulong objectOwner, ulong sender) { var sendMethodName = $"DefaultTo{sendTo}Rpc"; var verifyMethodName = $"VerifySentTo{sendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); + var senderObject = GetPlayerObjectNext(objectOwner, sender); var sendMethod = senderObject.GetType().GetMethod(sendMethodName); sendMethod.Invoke(senderObject, new object[] { }); var verifyMethod = GetType().GetMethod(verifyMethodName); - verifyMethod.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); + verifyMethod?.Invoke(this, new object[] { objectOwner, sender, sendMethodName }); } - } [Timeout(1200000)] // Tracked in MTT-11359 @@ -1173,6 +1710,9 @@ public void TestSendingWithTargetOverride( } +#endif + + #region ALREADY-OPTIMIZED-GROUP-A [Timeout(1200000)] // Tracked in MTT-11359 [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] @@ -1184,41 +1724,37 @@ public UniversalRpcTestSendingWithSingleOverride(HostOrServer hostOrServer) : ba } [UnityTest] - public IEnumerator TestSendingWithSingleOverride() + public IEnumerator TestSendingWithSingleOverride([Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost)] SendTo defaultSendTo) { - foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo))) + for (ulong recipient = 0u; recipient <= 2u; ++recipient) { - for (ulong recipient = 0u; recipient <= 2u; ++recipient) + for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner) { - for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner) + for (ulong sender = 0u; sender <= 2u; ++sender) { - for (ulong sender = 0u; sender <= 2u; ++sender) + if (++YieldCheck % YieldCycleCount == 0) { - if (++YieldCheck % YieldCycleCount == 0) - { - yield return null; - } - OnInlineSetup(); - var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; + yield return null; + } + OnInlineSetup(); + var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; - var senderObject = GetPlayerObject(objectOwner, sender); - var target = senderObject.RpcTarget.Single(recipient, RpcTargetUse.Temp); - var sendMethod = senderObject.GetType().GetMethod(sendMethodName); - sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var target = senderObject.RpcTarget.Single(recipient, RpcTargetUse.Temp); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); - VerifyRemoteReceived(objectOwner, sender, sendMethodName, new[] { recipient }, false); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray()); + VerifyRemoteReceived(objectOwner, sender, sendMethodName, new[] { recipient }, false); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray()); - // Pass some time to make sure that no other client ever receives this - TimeTravel(1f, 30); - VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray()); - OnInlineTearDown(); - } + // Pass some time to make sure that no other client ever receives this + TimeTravel(1f, 30); + VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient != c).ToArray()); + OnInlineTearDown(); } } } } - } [Timeout(1200000)] // Tracked in MTT-11359 @@ -1232,43 +1768,42 @@ public UniversalRpcTestSendingWithSingleNotOverride(HostOrServer hostOrServer) : } [UnityTest] - public IEnumerator TestSendingWithSingleNotOverride() + public IEnumerator TestSendingWithSingleNotOverride([Values(SendTo.Everyone, SendTo.Me, SendTo.Owner, SendTo.Server, SendTo.NotMe, SendTo.NotOwner, SendTo.NotServer, SendTo.ClientsAndHost)] SendTo defaultSendTo) { - foreach (var defaultSendTo in Enum.GetValues(typeof(SendTo))) + for (ulong recipient = 0u; recipient <= 2u; ++recipient) { - for (ulong recipient = 0u; recipient <= 2u; ++recipient) + for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner) { - for (ulong objectOwner = 0u; objectOwner <= 2u; ++objectOwner) + for (ulong sender = 0u; sender <= 2u; ++sender) { - for (ulong sender = 0u; sender <= 2u; ++sender) + if (++YieldCheck % YieldCycleCount == 0) { - if (++YieldCheck % YieldCycleCount == 0) - { - yield return null; - } - OnInlineSetup(); - var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; + yield return null; + } + OnInlineSetup(); + var sendMethodName = $"DefaultTo{defaultSendTo}AllowOverrideRpc"; - var senderObject = GetPlayerObject(objectOwner, sender); - var target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp); - var sendMethod = senderObject.GetType().GetMethod(sendMethodName); - sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); + var senderObject = InternalGetPlayerObject(objectOwner, sender); + var target = senderObject.RpcTarget.Not(recipient, RpcTargetUse.Temp); + var sendMethod = senderObject.GetType().GetMethod(sendMethodName); + sendMethod.Invoke(senderObject, new object[] { (RpcParams)target }); - VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient != c).ToArray(), false); - VerifyNotReceived(objectOwner, new[] { recipient }); + VerifyRemoteReceived(objectOwner, sender, sendMethodName, s_ClientIds.Where(c => recipient != c).ToArray(), false); + VerifyNotReceived(objectOwner, new[] { recipient }); - // Pass some time to make sure that no other client ever receives this - TimeTravel(1f, 30); - VerifyNotReceived(objectOwner, new[] { recipient }); - OnInlineTearDown(); - } + // Pass some time to make sure that no other client ever receives this + TimeTravel(1f, 30); + VerifyNotReceived(objectOwner, new[] { recipient }); + OnInlineTearDown(); } } } } } + #endregion +#if USE_LEGACY_UNIVERSALRPC_TESTS [Timeout(1200000)] // Tracked in MTT-11359 [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] @@ -1347,7 +1882,6 @@ [Values] AllocationType allocationType } } - [Timeout(1200000)] // Tracked in MTT-11359 [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] @@ -1426,18 +1960,9 @@ [Values] AllocationType allocationType VerifyNotReceived(objectOwner, s_ClientIds.Where(c => recipient.Contains(c)).ToArray()); } } +#endif - [Timeout(1200000)] // Tracked in MTT-11359 - [TestFixture(HostOrServer.Host)] - [TestFixture(HostOrServer.Server)] - internal class UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner : UniversalRpcTestsBase - { - public UniversalRpcTestDefaultSendToSpecifiedInParamsSendingToServerAndOwner(HostOrServer hostOrServer) : base(hostOrServer) - { - - } - } - + #region ALREADY-OPTIMIZED-OR-LOW-IMPACT-GROUP-B [Timeout(1200000)] // Tracked in MTT-11359 [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] @@ -1536,7 +2061,7 @@ public IEnumerator TestDeferLocal() var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc"; var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); + var senderObject = InternalGetPlayerObject(objectOwner, sender); var sendMethod = senderObject.GetType().GetMethod(sendMethodName); sendMethod.Invoke(senderObject, new object[] { new RpcParams() }); @@ -1574,7 +2099,7 @@ public IEnumerator TestDeferLocalOverrideToTrue() var sendMethodName = $"DefaultTo{defaultSendTo}WithRpcParamsRpc"; var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); + var senderObject = InternalGetPlayerObject(objectOwner, sender); var sendMethod = senderObject.GetType().GetMethod(sendMethodName); sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.Defer }); @@ -1612,7 +2137,7 @@ public IEnumerator TestDeferLocalOverrideToFalse() var sendMethodName = $"DefaultTo{defaultSendTo}DeferLocalRpc"; var verifyMethodName = $"VerifySentTo{defaultSendTo}"; - var senderObject = GetPlayerObject(objectOwner, sender); + var senderObject = InternalGetPlayerObject(objectOwner, sender); var sendMethod = senderObject.GetType().GetMethod(sendMethodName); sendMethod.Invoke(senderObject, new object[] { (RpcParams)LocalDeferMode.SendImmediate }); @@ -1623,7 +2148,6 @@ public IEnumerator TestDeferLocalOverrideToFalse() OnInlineTearDown(); } } - } [Timeout(1200000)] // Tracked in MTT-11359 @@ -1639,7 +2163,7 @@ public UniversalRpcTestMutualRecursion(HostOrServer hostOrServer) : base(hostOrS [Test] public void TestMutualRecursion() { - var serverObj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); + var serverObj = InternalGetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); serverObj.MutualRecursionClientRpc(); @@ -1690,7 +2214,7 @@ public UniversalRpcTestSelfRecursion(HostOrServer hostOrServer) : base(hostOrSer [Test] public void TestSelfRecursion() { - var serverObj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); + var serverObj = InternalGetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); serverObj.SelfRecursiveRpc(); @@ -1809,11 +2333,11 @@ protected override void OnTimeTravelServerAndClientsConnected() if (m_ObjType == ObjType.Server) { - m_Obj = GetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); + m_Obj = InternalGetPlayerObject(NetworkManager.ServerClientId, NetworkManager.ServerClientId); } else { - m_Obj = GetPlayerObject(1, 1); + m_Obj = InternalGetPlayerObject(1, 1); } } @@ -1935,5 +2459,6 @@ public void TestRpcTargetUseNotSingle() } } + #endregion } #endif diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json index 4014062faa..fd6398ebe1 100644 --- a/com.unity.netcode.gameobjects/package.json +++ b/com.unity.netcode.gameobjects/package.json @@ -2,7 +2,7 @@ "name": "com.unity.netcode.gameobjects", "displayName": "Netcode for GameObjects", "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", - "version": "1.13.1", + "version": "1.14.1", "unity": "2021.3", "dependencies": { "com.unity.nuget.mono-cecil": "1.10.1", diff --git a/testproject/ProjectSettings/ProjectSettings.asset b/testproject/ProjectSettings/ProjectSettings.asset index fbf187f5a1..717a85d5e1 100644 --- a/testproject/ProjectSettings/ProjectSettings.asset +++ b/testproject/ProjectSettings/ProjectSettings.asset @@ -51,7 +51,7 @@ PlayerSettings: m_MTRendering: 1 mipStripping: 0 numberOfMipsStripped: 0 - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + m_StackTraceTypes: 010000000100000001000000000000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 iosUseCustomAppBackgroundBehavior: 0