diff --git a/.yamato/project.metafile b/.yamato/project.metafile index 1117c4badf..3dcd7ce879 100644 --- a/.yamato/project.metafile +++ b/.yamato/project.metafile @@ -219,25 +219,6 @@ unified_test_platforms: image: package-ci/ubuntu-22.04:v4.87.0 flavor: b1.large -# Restricts the unified job to unified-only tests so nothing else runs on the alpha editor. -# -# This is a REGULAR EXPRESSION, not a glob. UTR passes it to the editor as -testFilter, which ends up -# in UnityEngine.TestRunner's FullNameFilter -> NUnit ValueMatchFilter -> new Regex(pattern).IsMatch(). -# A glob-style "*Unified*" throws "Quantifier {x,y} following nothing" and fails the whole run. -# The other jobs' "Unity.Netcode.RuntimeTests.*" works because it is also a valid regex - it just -# happens to read like a glob. -# -# The match is against the NUnit *full* test name, which includes both fixture and method arguments. -# -# DO NOT widen this to ".*Unified.*". "Unified" appearing in a test name does NOT mean that test was -# deliberately converted to run against hybrid prefabs. HostOrServer gained UnifiedServer/UnifiedHost -# members under UNIFIED_NETCODE, and NUnit expands a bare [Values] on an enum parameter (and -# enum-typed fixture constructors) to every member. So with N4E installed, much of the existing suite -# silently grows unified cases - e.g. NetworkVariableTests(Default).AllNetworkVariableTypes(UnifiedHost), -# which nobody wrote. ".*Unified.*" selected 138 tests, 84 of which failed, against the 1 test this -# job exists to validate. Deciding which of those should pass, and how they opt in, is Goal-2. -unified_test_filter: ".*UnifiedNetworkTransformTest.*" - # Scripting backends used by Standalone RunTimeTests--------------------------------------------------- diff --git a/.yamato/unified-tests.yml b/.yamato/unified-tests.yml index cadadec765..fa6dc9b308 100644 --- a/.yamato/unified-tests.yml +++ b/.yamato/unified-tests.yml @@ -2,47 +2,17 @@ --- # DESCRIPTION-------------------------------------------------------------------------- - # This job validates NGO running against Netcode for Entities (N4E) through the unified API. - # A "hybrid prefab" is an NGO prefab (NetworkObject at the root) that also carries a GhostObject. - # When one or more hybrid prefabs are in the NetworkManager's prefab list, NGO hands transform - # synchronization to N4E's snapshot system and tunnels its own batched messages over - # UnifiedNetcodeTransport (N4E's out-of-band RPC) instead of using a NetworkTransport such as UTP. - # UnifiedNetworkTransformTest is the validation test that this path works end to end. - -# WHY THIS JOB IS SEPARATE FROM EVERY OTHER JOB------------------------------------------ - # 1. It needs an editor that bundles a com.unity.netcode with the unified API. That editor - # (unified_editors.default in project.metafile) is not one of the validation_editors, and NGO - # still has to keep building and testing against editors that have no unified API at all. - # 2. It needs com.unity.netcode in the testproject so that the UNIFIED_NETCODE define is set - # (see the versionDefines in Unity.Netcode.Runtime.asmdef). The committed - # testproject/Packages/manifest.json deliberately does NOT reference it, so this job swaps in - # testproject/Packages/manifest-unified.json instead. - # 3. It is wired into pr_code_changes_checks and develop_nightly the same way the CMB service tests - # are, so it runs automatically on PRs targeting develop / develop-3.x.x / release. Be aware that - # this makes an unsupported alpha editor part of the PR gate: when N4E lands breaking changes in - # trunk this job goes red and the pin has to be bumped to unblock PRs. - # _triggers.yml also has unified_pr_checks, so it can be kicked off with "/ci unified" on PRs - # that pr_code_changes_checks does not cover. + # The NGO job that runs unified netcode hybrid prefab based integration tests. # CONFIGURATION STRUCTURE-------------------------------------------------------------- # Jobs are generated using nested loops: # 1. For all unified test platforms (currently Ubuntu only, see project.metafile) # 2. For all unified editors (currently a single pinned alpha, see project.metafile) -# TECHNICAL CONSIDERATIONS--------------------------------------------------------------- - # This job runs in Editor context only (no player builds required), like project-tests.yml. - # Only playmode is run: every unified test is an integration test and there are no unified EditMode tests. - # The run is restricted to unified tests via unified_test_filter so that nothing else is exercised - # on the alpha editor. Non-unified tests are covered by the regular jobs on the supported editors. - # packages-lock.json is removed because the committed lock was resolved against a much older editor - # and its builtin package versions do not exist in the unified editor. - # QUALITY CONSIDERATIONS-------------------------------------------------------------------- # TODO: the manifest swap means testproject/Packages/manifest-unified.json has to be kept in sync # with manifest.json by hand. Revisit once N4E is a hard dependency of NGO and one manifest # can cover both cases. - # TODO: unified_test_filter is a test-name pattern. Replacing it with an NUnit category (for - # example [Category("Unified")]) would be less fragile once more fixtures gain unified variants. #------------------------------------------------------------------------------------ @@ -58,18 +28,28 @@ unified_test_{{ project.name }}_{{ platform.name }}_{{ editor }}: {% if platform.model %} model: {{ platform.model }} # This is set only in platforms where we want non-default model to use (more information in project.metafile) {% endif %} + + variables: + # When UNIFIED_TESTS is set, only integration tests that opt in via overriding NetcodeIntegrationTest.UseUnifiedTests and returning true will run during this job. + # NetcodeIntegrationTest.UseUnifiedTests defaults to returning false (for now) making this an opt-in mode. + # Note: If USE_CMB_SERVICE is set along with UNIFIED_TESTS, then UNIFIED_TESTS is ignored until distributed authority is supported. + UNIFIED_TESTS: "true" + commands: - # Swap in the manifest that pulls in com.unity.netcode (N4E). This is what causes UNIFIED_NETCODE - # to be defined and therefore what makes the unified tests compile at all. + # Swap in the manifest that has the unified packages and versions required. + # Without the N4E package, UNIFIED_NETCODE is undefined and the unified API excluded. - cp {{ project.path }}/Packages/manifest-unified.json {{ project.path }}/Packages/manifest.json - - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor # Installing basic editor for tests execution - - UnifiedTestRunner --testproject={{ project.path }} --suite=playmode --artifacts-path=test-results --editor-location=.Editor --testfilter="{{ unified_test_filter }}" --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} + # Remove the committed lock as it is configured for 6000.6 which does not contain the unified API required. + - rm -f {{ project.path }}/Packages/packages-lock.json + + - unity-downloader-cli --fast --wait -u {{ editor }} -c Editor + - UnifiedTestRunner --testproject={{ project.path }} --suite=playmode --artifacts-path=test-results --editor-location=.Editor --rerun-strategy=Test --retry={{ num_test_retries }} --clean-library-on-rerun --timeout={{ test_timeout }} artifacts: logs: paths: - "test-results/**/*" dependencies: - - .yamato/_run-all.yml#run_quick_checks # initial checks to perform fast validation of common errors + - .yamato/_run-all.yml#run_quick_checks {% endfor -%} {% endfor -%} {% endfor -%} diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index 1b702e76fc..0a3fee02d7 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -1412,12 +1412,12 @@ private bool UnifiedIsConfiguredCorrectly() { if (NetCodeConfig.Global == null) { - Log.Error(new Context(LogLevel.Error, "You must create a {nameof(NetCodeConfig)} and set it to a single world in order to run in hybrid mode!").AddTag("Unified")); + Log.Error(new Context(LogLevel.Error, $"You must create a {nameof(NetCodeConfig)} and set it to a single world in order to run in hybrid mode!").AddTag("Unified")); return false; } if (NetCodeConfig.Global.HostWorldModeSelection != NetCodeConfig.HostWorldMode.SingleWorld) { - Log.Error(new Context(LogLevel.Error, "You must configure {nameof(NetCodeConfig)} to only use a single world in order to run in hybrid mode!").AddTag("Unified")); + Log.Error(new Context(LogLevel.Error, $"You must configure {nameof(NetCodeConfig)} to only use a single world in order to run in hybrid mode!").AddTag("Unified")); return false; } return true; diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs index 549f0d8d23..fc580a721a 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs @@ -20,6 +20,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [SetUp] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NestedNetworkManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NestedNetworkManagerTests.cs index 9f2d76dd7b..c97b94b646 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NestedNetworkManagerTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NestedNetworkManagerTests.cs @@ -15,6 +15,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [Test] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs index da5e0b17ce..b59add95e0 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs @@ -11,6 +11,8 @@ public void OneTimeSetup() { // This test does not need to run against the Rust server. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [Test] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerEventsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerEventsTests.cs index 93d13c9e18..32d998c0b7 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerEventsTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerEventsTests.cs @@ -22,6 +22,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } /// diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerSceneManagerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerSceneManagerTests.cs index 39b1bc9e14..6e0649ef69 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerSceneManagerTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerSceneManagerTests.cs @@ -11,6 +11,8 @@ public void OneTimeSetup() { // This test does not need to run against the Rust server. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [Test] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs index 1c4d346a61..ea6f1bf210 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerTransportTests.cs @@ -16,6 +16,8 @@ public void OneTimeSetup() { // This test does not need to run against the Rust server. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [Test] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs index afa575c7ed..79c2278b10 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/NetworkTransformStateTests.cs @@ -12,6 +12,8 @@ namespace Unity.Netcode.RuntimeTests { // These tests do not need to run against the Rust server. [IgnoreIfServiceEnvironmentVariableSet] + // These tests do not exercise hybrid prefabs. + [IgnoreIfUnifiedTestsEnvironmentVariableSet] internal class NetworkTransformStateTests { [Test] @@ -199,6 +201,8 @@ private void AssertTransformStateEquals(bool[] expected, NetworkTransformState a // These tests do not need to run against the Rust server. [IgnoreIfServiceEnvironmentVariableSet] + // These tests do not exercise hybrid prefabs. + [IgnoreIfUnifiedTestsEnvironmentVariableSet] [TestFixture(TransformSpace.World, Precision.Full, Rotation.Euler)] [TestFixture(TransformSpace.World, Precision.Half, Rotation.Euler)] [TestFixture(TransformSpace.Local, Precision.Full, Rotation.Euler)] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/UnifiedNetworkTransformTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/UnifiedNetworkTransformTest.cs index fc128ae31f..a0faaa26da 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/UnifiedNetworkTransformTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkTransform/UnifiedNetworkTransformTest.cs @@ -40,6 +40,12 @@ public UnifiedNetworkTransformTest(HostOrServer hostOrServer) : base(hostOrServe { } + // This is the validation test for the unified API, so it always runs during a unified test pass. + protected override bool UseUnifiedTests() + { + return true; + } + protected override bool OnSetVerboseDebug() { return false; diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkUpdateLoopTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkUpdateLoopTests.cs index 7f4dba5f16..fc52e5069d 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkUpdateLoopTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkUpdateLoopTests.cs @@ -18,6 +18,8 @@ public void OneTimeSetup() { // This test does not need to run against the Rust server. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [Test] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs index 85a72d9f19..59fd0a9aa4 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableTests.cs @@ -282,6 +282,11 @@ protected override void OnOneTimeTearDown() /// private void InitializeServerAndClients(HostOrServer useHost) { +#if UNIFIED_NETCODE + // HostOrServer arrives as a test method parameter here, so the base class cannot filter the + // hybrid prefab cases NUnit generates from the enum. Do it before anything is started. + ApplyUnifiedTestFilter(useHost); +#endif s_ClientNetworkVariableTestInstances.Clear(); m_PlayerPrefab.AddComponent(); @@ -351,6 +356,10 @@ private void InitializeServerAndClients(HostOrServer useHost) [Test] public void AllNetworkVariableTypes([Values] HostOrServer useHost) { +#if UNIFIED_NETCODE + // Filter before CreateNetworkObjectPrefab, which routes to CreateHybridPrefab for hybrid cases. + ApplyUnifiedTestFilter(useHost); +#endif var prefabToSpawn = CreateNetworkObjectPrefab("NetVarTest"); prefabToSpawn.AddComponent(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabHandlerTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabHandlerTests.cs index 56b6eb710d..bbce03bb3e 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabHandlerTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Prefabs/NetworkPrefabHandlerTests.cs @@ -23,6 +23,8 @@ protected override void OnOneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); base.OnOneTimeSetup(); } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcQueueTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcQueueTests.cs index 94741ad3e5..e09c8dda4f 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcQueueTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Rpc/RpcQueueTests.cs @@ -21,6 +21,8 @@ protected override void OnOneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); base.OnOneTimeSetup(); } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs index 699f4a21f9..139a4a9e4f 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Serialization/NetworkObjectReferenceTests.cs @@ -28,6 +28,8 @@ protected override void OnOneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); base.OnOneTimeSetup(); } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/StartStopTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/StartStopTests.cs index eaa4ebe91e..d60cca0d66 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/StartStopTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/StartStopTests.cs @@ -13,6 +13,8 @@ public void OneTimeSetup() { // This test does not need to run against the Rust server. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [SetUp] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs new file mode 100644 index 0000000000..a30c674295 --- /dev/null +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs @@ -0,0 +1,26 @@ +using System; +using NUnit.Framework; +using NUnit.Framework.Interfaces; +using NUnit.Framework.Internal; + +namespace Unity.Netcode.TestHelpers.Runtime +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + internal class IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute : NUnitAttribute, IApplyToTest + { + public void ApplyToTest(Test test) + { + // NotRunnable is the more weighty status, always respect it first + if (test.RunState == RunState.NotRunnable) + { + return; + } + + if (NetcodeIntegrationTestHelpers.UnifiedTestRun()) + { + test.RunState = RunState.Ignored; + test.Properties.Set("_SKIPREASON", NetcodeIntegrationTestHelpers.IgnoredForUnifiedTestsReason); + } + } + } +} diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs.meta b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs.meta new file mode 100644 index 0000000000..aa897ae623 --- /dev/null +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NUnitExtensions/IgnoreIfUnifiedTestsEnvironmentVariableSetAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8275a1756a05fb0581cd5b53bc4cb90d +timeCreated: 1787179374 diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs index c1a6becc11..f7a1ba1001 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTest.cs @@ -405,6 +405,107 @@ protected virtual bool UseCMBService() return m_UseCmbService; } +#if UNIFIED_NETCODE + /// + /// Indicates whether the currently running test is using hybrid prefabs via the unified (NGO + N4E) API. + /// + /// Can only be true if returns true. + protected bool m_UseUnifiedTests { get; private set; } + + private string m_UseUnifiedTestsEnvString = null; + private bool m_UseUnifiedTestsEnv; + + /// + /// Will check the environment variable once and then always return the results + /// of the first check. + /// + /// + /// This resets its properties during , so it will + /// check the environment variable once per test set. + /// + /// or + private bool GetUnifiedTestsEnvironmentVariable() + { + if (!m_UseUnifiedTestsEnv && m_UseUnifiedTestsEnvString == null) + { + m_UseUnifiedTestsEnvString = NetcodeIntegrationTestHelpers.GetUnifiedTestsEnvironmentVariable(); + if (bool.TryParse(m_UseUnifiedTestsEnvString.ToLower(), out bool isTrue)) + { + m_UseUnifiedTestsEnv = isTrue; + } + else + { + Debug.LogWarning($"The UNIFIED_TESTS ({m_UseUnifiedTestsEnvString}) value is an invalid bool string. {nameof(m_UseUnifiedTests)} is being set to false."); + m_UseUnifiedTestsEnv = false; + } + } + // A CMB service run always wins: distributed authority is not compatible with hybrid prefab spawning. + return m_UseUnifiedTestsEnv && !GetServiceEnvironmentVariable(); + } + + /// + /// Indicates whether this test's hybrid prefab cases have been validated against the unified API. + /// + /// + /// Defaults to false, which makes hybrid prefab test cases opt-in. Unified features are brought + /// online one feature set at a time, and because NUnit expands an enum parameter to every member + /// most / cases + /// exist without anyone having written them. + /// Override to return true once a test's hybrid prefab cases pass. + /// + /// if this test should run its hybrid prefab cases; otherwise it returns . + protected virtual bool UseUnifiedTests() + { + return false; + } + + /// + /// Ignores the current test case unless it is one the active test pass selects. + /// + /// Relies on throwing, so it returns only when the test should run. + private void ApplyUnifiedTestFilter() + { + // Hybrid prefab test cases exist on every test that takes a HostOrServer, because NUnit expands + // an enum parameter to all of its members. They only run during a unified test pass. + if (m_AllPrefabsAsHybrid && !GetUnifiedTestsEnvironmentVariable()) + { + Assert.Ignore(NetcodeIntegrationTestHelpers.IgnoredWithoutUnifiedTestsReason); + } + // Within a unified test pass a hybrid prefab test case still has to opt in via UseUnifiedTests. + if (m_AllPrefabsAsHybrid && !m_UseUnifiedTests) + { + Assert.Ignore(NetcodeIntegrationTestHelpers.NotOptedInForUnifiedTestsReason); + } + // Everything that is not a hybrid prefab test case is skipped during a unified test pass. Those + // tests have already run on the supported editors, and this pass only validates the unified API. + if (!m_AllPrefabsAsHybrid && GetUnifiedTestsEnvironmentVariable()) + { + Assert.Ignore(NetcodeIntegrationTestHelpers.IgnoredForUnifiedTestsReason); + } + } + + /// + /// Applies the unified test pass filtering for a test that takes its as a + /// test method parameter rather than as a fixture argument. Call it before starting any instances. + /// + /// + /// The fixture constructor never sees a test method parameter, so cannot + /// filter these cases: it runs once for the whole fixture and the value is not known yet. NUnit still + /// expands the enum to every member, so the and + /// cases are generated whether or not anyone wrote them. + /// + /// The the test method was invoked with. + protected void ApplyUnifiedTestFilter(HostOrServer hostOrServer) + { + m_AllPrefabsAsHybrid = hostOrServer == HostOrServer.UnifiedServer || hostOrServer == HostOrServer.UnifiedHost; + if (m_AllPrefabsAsHybrid && GetUnifiedTestsEnvironmentVariable()) + { + m_UseUnifiedTests = UseUnifiedTests(); + } + ApplyUnifiedTestFilter(); + } +#endif + /// /// Override this virtual method to control what kind of to use. /// @@ -591,11 +692,14 @@ public void OneTimeSetup() Assert.Ignore("[CMB-Server Test Run] Skipping non-distributed authority test."); return; } - else - { - // Otherwise, continue with the test - InternalOnOneTimeSetup(); - } +#if UNIFIED_NETCODE + // Only For Unified Tests: + // Note: this cannot filter a test that takes its HostOrServer as a test method parameter, since + // the value is not known until the method runs. Those call ApplyUnifiedTestFilter themselves. + ApplyUnifiedTestFilter(); +#endif + // Otherwise, continue with the test + InternalOnOneTimeSetup(); } private void InternalOnOneTimeSetup() @@ -1806,6 +1910,10 @@ public void OneTimeTearDown() IsRunning = false; m_UseCmbServiceEnvString = null; m_UseCmbServiceEnv = false; +#if UNIFIED_NETCODE + m_UseUnifiedTestsEnvString = null; + m_UseUnifiedTestsEnv = false; +#endif } /// @@ -2726,6 +2834,12 @@ private void InitializeTestConfiguration(NetworkTopologyTypes networkTopologyTyp #if UNIFIED_NETCODE m_UseHost = hostOrServer == HostOrServer.Host || hostOrServer == HostOrServer.DAHost || hostOrServer == HostOrServer.UnifiedHost; m_AllPrefabsAsHybrid = (hostOrServer == HostOrServer.UnifiedServer || hostOrServer == HostOrServer.UnifiedHost); + // If this is a hybrid prefab test case and the environment variable to run the unified tests + // is set, then perform the m_UseUnifiedTests check. + if (m_AllPrefabsAsHybrid && GetUnifiedTestsEnvironmentVariable()) + { + m_UseUnifiedTests = UseUnifiedTests(); + } #else m_UseHost = hostOrServer == HostOrServer.Host || hostOrServer == HostOrServer.DAHost; #endif diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs index 8f32fc1916..a8103aac87 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/TestHelpers/NetcodeIntegrationTestHelpers.cs @@ -215,6 +215,52 @@ internal static void IgnoreIfServiceEnviromentVariableSet() } } + /// + /// Gets the UNIFIED_TESTS environment variable or returns "false" if it does not exist + /// + /// + internal static string GetUnifiedTestsEnvironmentVariable() + { +#if UNIFIED_TESTS + return "true"; +#else + return Environment.GetEnvironmentVariable("UNIFIED_TESTS") ?? "false"; +#endif + } + + /// + /// Determines whether this is a unified (NGO + N4E) hybrid prefab test run. + /// + /// + /// A CMB service run always wins: distributed authority is not compatible with hybrid prefab + /// spawning, so the two can never be the same run. + /// + /// or + internal static bool UnifiedTestRun() + { + if (bool.TryParse(GetCMBServiceEnvironentVariable(), out bool useCmbService) ? useCmbService : false) + { + return false; + } + return bool.TryParse(GetUnifiedTestsEnvironmentVariable(), out bool isTrue) ? isTrue : false; + } + + internal static readonly string IgnoredForUnifiedTestsReason = "[Unified Test Run] Skipping non-hybrid prefab test."; + internal static readonly string IgnoredWithoutUnifiedTestsReason = "[Non-Unified Test Run] Skipping hybrid prefab test."; + internal static readonly string NotOptedInForUnifiedTestsReason = "[Unified Test Run] Skipping hybrid prefab test that has not opted in via UseUnifiedTests."; + + /// + /// Use for non derived integration tests to automatically ignore the + /// test if running a unified (NGO + N4E) hybrid prefab test pass. + /// + internal static void IgnoreIfUnifiedTestsEnvironmentVariableSet() + { + if (UnifiedTestRun()) + { + Assert.Ignore(IgnoredForUnifiedTestsReason); + } + } + private static readonly string k_TransportHost = GetAddressToBind(); private static readonly ushort k_TransportPort = GetPortToBind(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Timing/NetworkTimeSystemTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Timing/NetworkTimeSystemTests.cs index 64cfcf030e..8dca0b69d6 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Timing/NetworkTimeSystemTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Timing/NetworkTimeSystemTests.cs @@ -22,6 +22,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [SetUp] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Timing/TimeInitializationTest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Timing/TimeInitializationTest.cs index 28053fe167..cd249707a8 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Timing/TimeInitializationTest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Timing/TimeInitializationTest.cs @@ -20,6 +20,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnityTest] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs index 2bdce8f205..fc83715898 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportConnectionTests.cs @@ -28,6 +28,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnityTearDown] diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs index 89283f83f6..9b224d6bfe 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs @@ -40,6 +40,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnityTearDown] diff --git a/testproject/.gitignore b/testproject/.gitignore index 2800399634..adf747b1fc 100644 --- a/testproject/.gitignore +++ b/testproject/.gitignore @@ -7,6 +7,7 @@ /[Oo]bj/ /[Bb]uild/ /[Bb]uilds/ +/*[Bb]uilds/ /[Ll]ogs/ /[Uu]ser[Ss]ettings/ diff --git a/testproject/Assets/Tests/Runtime/HelpUrlTests.cs b/testproject/Assets/Tests/Runtime/HelpUrlTests.cs index 0a0eb95f54..5ad70d585d 100644 --- a/testproject/Assets/Tests/Runtime/HelpUrlTests.cs +++ b/testproject/Assets/Tests/Runtime/HelpUrlTests.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using NUnit.Framework; using Unity.Netcode.Runtime; +using Unity.Netcode.TestHelpers.Runtime; using UnityEngine; using UnityEngine.TestTools; @@ -22,6 +23,16 @@ internal class HelpUrlTests private bool m_VerboseLogging = false; + [OneTimeSetUp] + public void OneTimeSetup() + { + // This test does not need to run against the Rust server. + NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); + } + [UnityTest] public IEnumerator ValidateUrlsAreValid() { diff --git a/testproject/Assets/Tests/Runtime/MessageOrdering.cs b/testproject/Assets/Tests/Runtime/MessageOrdering.cs index f4ef5a7fbd..1a0af87ae2 100644 --- a/testproject/Assets/Tests/Runtime/MessageOrdering.cs +++ b/testproject/Assets/Tests/Runtime/MessageOrdering.cs @@ -24,6 +24,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnitySetUp] diff --git a/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs b/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs index 61a8a8d112..344090fefb 100644 --- a/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs +++ b/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs @@ -29,6 +29,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } /// diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs index 70ca7c24d2..bd54bba384 100644 --- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/NetworkSceneManagerDDOLTests.cs @@ -24,6 +24,8 @@ public void OneTimeSetup() { // This does not need to be tested against a CMB Server NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnitySetUp] diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/SceneEventDataTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/SceneEventDataTests.cs index f1bdc67c66..1ed74831c7 100644 --- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/SceneEventDataTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/SceneEventDataTests.cs @@ -22,6 +22,8 @@ public void OneTimeSetup() { // This test does not need to run against a CMB server NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } /// diff --git a/testproject/Assets/Tests/Runtime/NetworkVariableInitializationOnNetworkSpawnTest.cs b/testproject/Assets/Tests/Runtime/NetworkVariableInitializationOnNetworkSpawnTest.cs index 1a54eefa90..47ac243114 100644 --- a/testproject/Assets/Tests/Runtime/NetworkVariableInitializationOnNetworkSpawnTest.cs +++ b/testproject/Assets/Tests/Runtime/NetworkVariableInitializationOnNetworkSpawnTest.cs @@ -17,6 +17,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [UnitySetUp] diff --git a/testproject/Assets/Tests/Runtime/NoMemoryLeakOnNetworkManagerShutdownTest.cs b/testproject/Assets/Tests/Runtime/NoMemoryLeakOnNetworkManagerShutdownTest.cs index 9204454cd5..8ed88024bb 100644 --- a/testproject/Assets/Tests/Runtime/NoMemoryLeakOnNetworkManagerShutdownTest.cs +++ b/testproject/Assets/Tests/Runtime/NoMemoryLeakOnNetworkManagerShutdownTest.cs @@ -17,6 +17,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } [SetUp] diff --git a/testproject/Assets/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs b/testproject/Assets/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs index c080cac7c5..c61f8ec6e7 100644 --- a/testproject/Assets/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs +++ b/testproject/Assets/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs @@ -43,6 +43,8 @@ public void OneTimeSetup() { // TODO: [CmbServiceTests] if this test is deemed needed to test against the CMB server then update this test. NetcodeIntegrationTestHelpers.IgnoreIfServiceEnviromentVariableSet(); + // Excluding from unified tests. If deemed needed, update test, then remove. + NetcodeIntegrationTestHelpers.IgnoreIfUnifiedTestsEnvironmentVariableSet(); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode)