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)